Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add new lint paths_from_format #8833

Closed
wants to merge 7 commits into from

Conversation

merelymyself
Copy link

@merelymyself merelymyself commented May 15, 2022

Please write a short comment explaining your change (or "none" for internal only changes)

As per #8812

changelog: Add new lint [`path_from_format`]

@rust-highfive
Copy link

Thanks for the pull request, and welcome! The Rust team is excited to review your changes, and you should hear from @camsteffen (or someone else) soon.

Please see the contribution instructions for more information.

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties label May 15, 2022
@merelymyself merelymyself changed the title Add new lint `[path_from_format]` Add new lint [path_from_format] May 15, 2022
@merelymyself merelymyself changed the title Add new lint [path_from_format] Add new lint path_from_format May 15, 2022
@bors
Copy link
Contributor

bors commented May 25, 2022

☔ The latest upstream changes (presumably #8882) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented May 26, 2022

☔ The latest upstream changes (presumably #8866) made this pull request unmergeable. Please resolve the merge conflicts.

@xFrednet
Copy link
Member

Hey @merelymyself, welcome to the project!

r? @dswij (I'd appreciate it if you could leave a normal comment so that I can also assign you to this PR) 🙃

@xFrednet xFrednet assigned xFrednet and unassigned camsteffen May 27, 2022
@bors
Copy link
Contributor

bors commented May 31, 2022

☔ The latest upstream changes (presumably #8918) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented May 31, 2022

☔ The latest upstream changes (presumably #8916) made this pull request unmergeable. Please resolve the merge conflicts.

@giraffate
Copy link
Contributor

Could you do a rebase, not merge commit? We follow no merge-commit policy.
https://github.com/rust-lang/rust-clippy/blob/master/doc/basics.md#pr

@merelymyself
Copy link
Author

@giraffate , does this work?

Copy link
Member

@dswij dswij left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the PR, and welcome!

The basic idea for the lint looks good to me 👍 .
I left some suggestions and questions.

tests/ui/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
@merelymyself merelymyself marked this pull request as draft June 1, 2022 15:40
@merelymyself merelymyself marked this pull request as ready for review June 3, 2022 07:00
@merelymyself
Copy link
Author

Hi, @dswij. Made some changes, could you take another look? Thanks!

@bors
Copy link
Contributor

bors commented Jun 3, 2022

☔ The latest upstream changes (presumably #8831) made this pull request unmergeable. Please resolve the merge conflicts.

tests/ui/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
tests/ui/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
@xFrednet xFrednet removed their assignment Jun 7, 2022
@merelymyself
Copy link
Author

Thanks for the patience and advice, @dswij. Could you take another look?

If there's a situation where a path like 'foo{}/bar' shows up, instead of offering a suggestion, a note is offered instead now.

Copy link
Member

@dswij dswij left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for all the changes!

I think we can just not emit the lint for foo{}/bar. I'd imagine someone uses it like this, which is legit

let prefix = "some-prefixes";
let _ Path::new(format!("./{prefix}.csv"));

Note that the suggestion is also wrong right now when the variable in join() has a path separator:

let x = "/bar";
let y = Path::new("/foo").join(x); // y = "bar"

clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
PATH_FROM_FORMAT,
expr.span,
"`format!(..)` used to form `PathBuf`",
"consider using `Path::new()` and `.join()` to make it OS-agnostic and improve code readability",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thinking about this, for long paths, .join() might actually be annoying. Maybe we can only suggest when the path is pretty short. Need some opinion on this, WDYT? @merelymyself @xFrednet

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't really mind either way, but I feel that having consistency is slightly more important. Plus, I don't really see long paths that often in Rust projects (or is that just confirmation bias?)

clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
tests/ui/path_from_format.rs Outdated Show resolved Hide resolved
tests/ui/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/path_from_format.rs Outdated Show resolved Hide resolved
@bors
Copy link
Contributor

bors commented Jun 15, 2022

☔ The latest upstream changes (presumably #8964) made this pull request unmergeable. Please resolve the merge conflicts.

@bors
Copy link
Contributor

bors commented Oct 16, 2022

☔ The latest upstream changes (presumably #9658) made this pull request unmergeable. Please resolve the merge conflicts.

@merelymyself
Copy link
Author

Hi, @dswij ! Sorry to disturb, but do you mind taking a look soon?

@bors
Copy link
Contributor

bors commented Oct 20, 2022

☔ The latest upstream changes (presumably #9670) made this pull request unmergeable. Please resolve the merge conflicts.

@xFrednet
Copy link
Member

xFrednet commented Jan 7, 2023

Hey @dswij, this is a ping from triage, could you review this PR? If you don't have the time, feel free to pass it to me.

@merelymyself Would you mind rebasing the branch on master? IDK, what changes have been made to src/docs.rs in the meantime, but I hope that the rebase will go smoothly. You're welcome to reach out, if you need assistance :)

@dswij
Copy link
Member

dswij commented Jan 7, 2023

@xFrednet Thanks for taking time to look at this. I'll pass this to you if you don't mind :)

r? @xFrednet

@merelymyself Sorry I missed the pings, I've been distracted with other stuff and somehow didn't notice the ping :\

@rustbot rustbot assigned xFrednet and unassigned dswij Jan 7, 2023
Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The basic structure and idea is already good. Though, while reading though the documentation, I found examples, that suggested a different way. I'll add a comment to the original issue and ask the author :)

@rustbot author

Comment on lines +21 to +22
/// `.join()` introduces additional allocations that are not present when `PathBuf::push` is
/// used instead.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looking at this, I think it would be better to suggest PathBuf directly. Even if that might require additional modifications by the user. PathBuf is intended for modifications as this one AFAIK :)

Though, in that case we should have the applicability be less than machine applicable

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, to clarify, you mean you want to do some or all of the following?

  1. Replace .join() with .push()
  2. Replace the Path::new with PathBuf::from
  3. Instead of suggesting a replacement, just flag it out to the user

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, if my comment wasn't clear. I mean a combination of the first two. So suggest PathBuf::from() and then add segments using push(). The thing is, that this probably change the type of the buffer and require further adjustments by the user. Therefore, we should display the suggestion, but not make it machine applicable.

Does this make sense, or should I try to describe it better? :)

Copy link
Author

@merelymyself merelymyself Jan 21, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm looking at the docs for PathBuf now, and I just realised that there might be a recommended solution for situations like this 😵‍💫.

let var = "path";

pathbuf = ["/", var, "filename.txt"].iter().collect::<PathBuf>();

Functionally equivalent to

let var = "path";

pathbuf = PathBuf::from(format!("/{var}/filename.txt"));

Will you be ok with this? Given it should still be machine applicable but I don't think it will have the same problems as before.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have to be careful when using the array as all the values have to be the same type.

clippy_lints/src/paths_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/paths_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/paths_from_format.rs Outdated Show resolved Hide resolved
clippy_lints/src/paths_from_format.rs Show resolved Hide resolved
@rustbot rustbot added S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties labels Jan 9, 2023
@bors
Copy link
Contributor

bors commented Jan 19, 2023

☔ The latest upstream changes (presumably #10206) made this pull request unmergeable. Please resolve the merge conflicts.

Copy link
Member

@xFrednet xFrednet left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey, thank you for your patience, the review sadly took a bit longer. You're welcome to ask if you have any questions :)

PATHS_FROM_FORMAT,
expr.span,
"`format!(..)` used to form `PathBuf`",
"consider using `Path::new()` and `.join()` to make it OS-agnostic and improve code readability",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would remove the second part, as some users might not consider this more readable. The OS-agnostic part is also the main point, IMO.

if_chain! {
if let ExprKind::Call(_, [arg, ..]) = expr.kind;
if let ty = cx.typeck_results().expr_ty(expr);
if is_type_diagnostic_item(cx, ty, sym::PathBuf);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we maybe also check for calls to Path::new?

impl<'tcx> LateLintPass<'tcx> for PathsFromFormat {
fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
if_chain! {
if let ExprKind::Call(_, [arg, ..]) = expr.kind;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right now, this lint only checks for function calls, where the output is a PathBuf and the first argument is a format macro. The lint logic should also check the first value of ExprKind::Call to ensure that it's a path to a function called new or other related function names.

The logic should also contain a check if the code originated from a macro. I believe the check should be as simple as !expr.span.from_expansion()

.iter()
.map(rustc_span::Symbol::as_str)
.collect();
let mut applicability = Applicability::MachineApplicable;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the applicability is explicitly set with the lint emission, you can remove this value and all usages of it.

For Sugg::hir_with_applicability you can just use Sugg::hir

Comment on lines +73 to +74
}
else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Formatting nit, as well as the other else cases in the if_chain!

Suggested change
}
else {
} else {

Comment on lines +86 to +89
let _ = write!(sugg, ".join(&{arg})");
}
else {
sugg = format!("{sugg}.join(&{arg})");
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason, why you use two different methods to append text to an existing string?


// In essence, this checks if the format!() used is made for concatenation of the filenames / folder
// names itself. This returns true when it is something like
// `PathBuf::from(format!("/x/folder{}/textfile.txt", folder_number))`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on the comment in the related issue, I would actually think that such a paht can still be problematic. I'd suggest either, checking if the path starts with //?/ which makes it a verbatim path under windows or (IMO the better approach) add a config value, to allow this. I have the feeling the lint can be very noisy without, but ignoring these cases can also be wrong.

@bors
Copy link
Contributor

bors commented Feb 3, 2023

☔ The latest upstream changes (presumably #10028) made this pull request unmergeable. Please resolve the merge conflicts.

@xFrednet
Copy link
Member

Hey @merelymyself this is a ping from triage. Are you still working on this PR? If you have any questions, you're always welcome to reach out :)

@merelymyself
Copy link
Author

Hi, so sorry. Thanks for all the help so far, but I don't think I'll have much time in the near future to work on this with any level of consistency - again, apologies for any inconvenience caused. I'll close the PR.

@xFrednet xFrednet added S-inactive-closed Status: Closed due to inactivity and removed S-waiting-on-author Status: This is awaiting some action from the author. (Use `@rustbot ready` to update this status) labels Mar 2, 2023
@xFrednet
Copy link
Member

xFrednet commented Mar 2, 2023

It was no inconvenience at all, I hope you still had some fun!

I'll mark this PR as S-inactive-closed it's still a good start for anyone that wants to work on the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-inactive-closed Status: Closed due to inactivity
Projects
None yet
Development

Successfully merging this pull request may close these issues.

10 participants