Clippy pendantic and more refactors#219
Conversation
|
Ah it seems I accidentally used some nightly features |
src/bin/lychee/main.rs
Outdated
| let bar = ProgressBar::new(links.len() as u64) | ||
| .with_style(ProgressStyle::default_bar().template( | ||
| let with_progress = !cfg.no_progress; | ||
| let pb = with_progress.then(|| { |
There was a problem hiding this comment.
Hum... I find the old version easier to understand. 🤔
There was a problem hiding this comment.
I can see that I'll revert it when I rebase on the new master when #208 is merged.
src/client.rs
Outdated
| .and_then(|token| { | ||
| (!token.is_empty()).then(|| Github::new(user_agent, Credentials::Token(token))) | ||
| }) | ||
| .transpose()?; |
There was a problem hiding this comment.
Aha! transpose does make sense here.
There was a problem hiding this comment.
Yeah I was so happy when I found out about transpose
|
Great improvements! Thanks a lot for this. |
|
Seems like a good Idea although doing this again on the new master might actually be less work than rebasing. |
|
There's no need to merge this. |
|
Which is why the plan is to rebase on top of your PR. |
|
@soruh |
|
I think there are some additional changes, I'll try to rebase it when I find the time and will make a new PR if there are significant changes left / close this one if there aren't. |
|
Thanks! |
|
I just rebased my code onto master, there is not a huge amount left but still enough for keeping this open I think. I re-added my old solution of converting file extensions to lower-case before checking them. By now I have realized that this is probably not the optimal solution (as is always heap allocates). A version of I personally like the There a a few things I would like an opinion on (annotated with |
| None => tokio::runtime::Runtime::new()?, | ||
| }; | ||
| None => tokio::runtime::Runtime::new(), | ||
| }?; |
There was a problem hiding this comment.
ok. but easy to miss when reading.
There was a problem hiding this comment.
We are creating a runtime in both cases and are checking if that failed after which I find more readable.
There was a problem hiding this comment.
the ? operator in }?; is quite easy to miss.
| return match e.kind() { | ||
| ErrorKind::NotFound => Ok(None), | ||
| _ => Err(Error::from(e)), | ||
| _ => Err(e.into()), |
There was a problem hiding this comment.
No I deliberately avoid using Into::into().
It's hard to figure out what it is converting to.
There was a problem hiding this comment.
We are calling .into() inside of an Err(...), the Error:: doesn't give you any new information here and just makes the more verbose.
There was a problem hiding this comment.
How do you figure out what's the type of E in a Result<T, E>?
Error::from(e) clearly shows E is of type Error, while e.into() has no such information.
| let pb = if cfg.no_progress { | ||
| None | ||
| } else { | ||
| let pb = cfg.no_progress.not().then(|| { |
There was a problem hiding this comment.
Does this increase any readability or performance?
There was a problem hiding this comment.
I think the functional style is clearer but I agree that the .not() may not be (see my original comment).
There was a problem hiding this comment.
The issue is not with not, the main issue is the functional style.
std::option::Option::then() is a fairly new addition. If it's the more idiomatic way of handling Boolean conditionals, it'd be added much earlier.
| let github_token = self | ||
| .github_token | ||
| .as_ref() | ||
| .and_then(|token| { |
There was a problem hiding this comment.
Again.
When I refactored these code, I deliberately avoided this kind of pattern.
There was a problem hiding this comment.
I agree that the not() should be a ! but think this is way more readable than the Some(ref token) if !token.is_empty() => Some( incantation it replaced. I agree that this is a matter of opinion though.
There was a problem hiding this comment.
No.
I deliberately keep Some(ref token). this make it very clear of the type signature.
( Calling as_ref() has the same effect. )
The not readable part is the nested and_then and then. Unless you add explicit type signature, it's less clear. But if you did, it's too verbose.
| (attr_name, elem_name), | ||
| // TODO: re-enable once `or-patterns` become stable in Rust 1.53 | ||
| // ("href" | "src" | "srcset" | "cite", _) | ("data", "object") | ("onhashchange", "body") | ||
| ("href", _) |
There was a problem hiding this comment.
When I refactored this part, it's requested to keep the current form for readability.
| // assert_eq!(FileType::from(Path::new("/")), FileType::Plaintext); | ||
| // assert_eq!(FileType::from("test"), FileType::Plaintext); | ||
| assert_eq!(FileType::from("test.md"), FileType::Markdown); | ||
| assert_eq!(FileType::from("TEST.MD"), FileType::Markdown); |
There was a problem hiding this comment.
-1
On modern file system it's case sensitive.
According to mimeinfo of text/markdown, valid extension is one of .md .mkd and .markdown.
If a .MD extension is recognized as markdown, it IS A BUG.
There was a problem hiding this comment.
Are you saying that handling an html file incorrectly because it is called "index.HTML" is okay? Or are you only referring to Markdown files? In that case I guess If we do what I proposed in my comment above we can only check if certain extension match insensitively, I don't see how handling files with extensions that are not technically in spec is an improvement
There was a problem hiding this comment.
I'm not talking about the REVIEW comment.
What I'm taking is the additional assert_eq tests you added are not sound. They should be removed.
There was a problem hiding this comment.
Ah, that makes sense, are you okay with changing that to a ".HTML" test or are uppercase extension not technically in-spec in general?
There was a problem hiding this comment.
To incorporate them is very complicated.
For modern Linux/Unix/FreeBSD systems, the file system should be case-sensitive. Thus these are unknown schemes and are recognized as planttext. (But newer Linux kernel supports opt-in case-insensitive feature)
For macOS, HFS/HFS+ defaults to case-insensitive if operating system is installed before 10.3. Otherwise it's case-sensitive. For APS, it's case-sensitive.
For Windows, NTFS is actually case sensitive internally, but defaults to case-insensitive in user space.
If you really want to incorporate those tests, you need conditional compilations based on operating system and whehther the filesystem is case sensitive.
My opinion is these cases are too complicated to handle. Just remove those tests.
| Status::Timeout(Some(code)) => format!(" [{}]", code), | ||
| Status::Error(e) => format!(" ({})", e), | ||
| _ => "".to_owned(), | ||
| _ => "".into(), |
There was a problem hiding this comment.
No.
When converting a &str to String, I deliberately use .to_owned() to indicate the memory allocation.
There was a problem hiding this comment.
This doesn't allocate; I thought about using String::new() but decided that this is clearer.
There was a problem hiding this comment.
The whole code base consistently use str::to_owned() for this type of conversion.
When you refactor you need to take the overall coding style and convention into account.
| } else { | ||
| None | ||
| }; | ||
| let base_url = base_url |
There was a problem hiding this comment.
Again, not necessarily more readable.
There was a problem hiding this comment.
I disagree but again, I guess it's a matter of opinion if you think the functional or the imperative style is more readable
|
I will be reverting some of the changes of the original rebase (at least the Regarding the lowercase file extension handling I do think it makes sense to do but can remove it if again if deemed unnecessary. P.S. @lebensterben I would like to inform you that the way you have reviewed my code has honestly been a very bad experience; This had been the only time that I did not look forward to reading a review of my code. P.P.S I'm pretty tired though which may be affecting my irritability, in that regard. I'll review the rest tomorrow. |
|
FYI when I refactor, there are a few things taken into account
Also, I always prefer to make things more explicit. Without writing type signatures everywhere, a way to achieve this to use more specific function/methods.
|
|
I agree with the first part and usually do the same. |
|
@soruh are you still planning to work on this or shall we close the PR and open a new one if time allows? |
|
Ah yeah sorry, I think I'll just close this (don't really have time to work on this at the moment). |
clippy::pedantic, fix most of it's complaints and ignore the rest (mostly documentation tasks).OptionandResultinstead of matches.P.S.: my rustfmt seems to have collapsed some
uses and comment, if you dislike this I can try to undo that manually.P.P.S.: sorry for creating another relatively large PR :)