Skip to content

Fix recursive path handling for workspace/didChangeWatchedFiles #1047

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

Merged
merged 1 commit into from
Aug 19, 2020

Conversation

dradtke
Copy link
Contributor

@dradtke dradtke commented Jun 5, 2020

Problem

LanguageClient-neovim currently fails to register filesystem notifications for paths resembling those requested by eclipse.jdt.ls:

"watchers": [
  {"globPattern":"**/*.java"},
  {"globPattern":"**/pom.xml"},
  {"globPattern":"**/*.gradle"},
  {"globPattern":"**/gradle.properties"},
  {"globPattern":"**/.project"},
  {"globPattern":"**/.classpath"},
  {"globPattern":"**/.settings/*.prefs"},
  {"globPattern":"**/src/**"}
]

Because none of the requested paths end with **, the plugin attempts to register them all as non-recursive file watches, which fails because no file named e.g. **/*.java exists.

Solution

This PR proposes a possible fix, but it's a very blunt one, and I'm open to feedback on how to make it more targeted. Specifically, if a glob pattern contains ** anywhere, it chops off it and everything after it (defaulting to . if it occurs at the beginning of the string, as seen above) and requests a recursive watch; otherwise, it adds a non-recursive file watch.

As is, the 8 watchers requested above all end up adding a recursive . watch, which is inefficient. A better solution would be to register recursive watchers on . that can still filter events by the rest of the path following **/, but I don't know where that would be implemented.

@martskins
Copy link
Collaborator

martskins commented Jun 18, 2020

I think a better approach would be to use glob, which is in fact part of the dependencies already. With something like this:

    for entry in glob::glob_with(fw.glob_pattern.as_str(), MatchOptions::default()).unwrap() {
        // set watcher for entry.unwrap().display()
    }

glob_with will return a list of paths that match those patterns, and I think it should be able to handle all of the paths in your use case.

This will avoid adding watchers for the same file more than once and also adding watchers for files that the server is not interested (as I understand it, your current implementation would for example watch any extension, not only java, when given the pattern **/*.java).

Just a side note, keep in mind that there's #1054 too, which doesn't address this issue in particular but it also involves the watcher logic.

@dradtke dradtke force-pushed the fix-recursive-notify branch from edfa6a2 to 196508f Compare June 24, 2020 13:21
@dradtke
Copy link
Contributor Author

dradtke commented Jun 24, 2020

Thanks for the tip, that definitely looks like a better solution. I just pushed an update that uses glob::glob() (the default options seem fine), so hopefully that results in better performance.

Comment on lines 2683 to 2736
let mode = match path.is_dir() {
true => notify::RecursiveMode::Recursive,
false => notify::RecursiveMode::NonRecursive,
};
Copy link
Collaborator

@martskins martskins Jun 24, 2020

Choose a reason for hiding this comment

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

Clippy will complain about this, can we change it to

let mode = if path.is_dir() {
    notify::RecursiveMode::Recursive
} else {
    notify::RecursiveMode::NonRecursive
};

instead?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Just pushed an update to change it to use if/else.

@martskins
Copy link
Collaborator

martskins commented Jun 24, 2020

Oh and also, PRs should target the dev branch now, so please change the target of this PR to that branch.

@dradtke dradtke changed the base branch from next to dev June 24, 2020 20:21
@martskins
Copy link
Collaborator

@dradtke note that you'll need to rebase this to dev, as it has some merge conflicts now (the code base has drastically changed in the last few days 😄 ). Happy to lend a hand if you need it though.

@dradtke dradtke force-pushed the fix-recursive-notify branch from 3b57de8 to 26694f8 Compare June 26, 2020 19:26
@dradtke
Copy link
Contributor Author

dradtke commented Jun 26, 2020

Just finished rebasing everything on dev and the diff looks pretty clean. 🧼

@dradtke
Copy link
Contributor Author

dradtke commented Jul 17, 2020

@martskins Any other feedback? It'd be nice to have this PR merged in.

@martskins
Copy link
Collaborator

Looks good to me, but it'd be nice for @autozimu to take a look, as I'm not sure I've used this feature enough to test it.

This commit attempts to fix filesystem notifications for recursive paths
that also specify an extension, such as "**/*.java".
@dradtke dradtke force-pushed the fix-recursive-notify branch from 26694f8 to 8393467 Compare July 20, 2020 20:09
@dradtke
Copy link
Contributor Author

dradtke commented Aug 17, 2020

@autozimu Any thoughts on getting this PR merged in?

@autozimu autozimu merged commit a98835f into autozimu:dev Aug 19, 2020
@autozimu
Copy link
Owner

Thanks for the contribution!

@dradtke dradtke deleted the fix-recursive-notify branch August 19, 2020 15:32
jez pushed a commit to jez/LanguageClient-neovim that referenced this pull request Feb 26, 2021
This commit attempts to fix filesystem notifications for recursive paths
that also specify an extension, such as "**/*.java".
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants