Skip to content

(GH-879) Add filtering for CodeLens and References #877

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

Conversation

glennsarti
Copy link
Contributor

@glennsarti glennsarti commented Mar 8, 2019

Fixes #879

Code sites

LanguageSevice.cs : HandleDefinitionRequestAsync (DefinitionRequest Handler)
LanguageSevice.cs : GetDefinitionOfSymbolAsync
- Calls EnumeratePSFiles AFTER it parses currently loaded files

LanguageSevice.cs : HandleReferencesRequestAsync (ReferencesRequest Handler)
LanguageSevice.cs : FindReferencesOfSymbolAsync
- Calls EnumeratePSFiles

This is used in the CodeLensFeature, PesterCodeLensProvider and ReferencesCodeLensProvider

ReferencesCodeLensProvider.cs : ResolveCodeLensAsync
LanguageSevice.cs : FindReferencesOfSymbolAsync
- Calls EnumeratePSFiles

Not used

LanguageSevice.cs : HandleWorkspaceSymbolRequestAsync (WorkspaceSymbolRequest Handler)
- This is weird. It only looks for symbols in the workspace OPENED files, not ALL files
in the workspace. Seems like an oversight here.

As per ba1c40e this is known broken.


Previously there were no tests for the Workspace.EnumeratePSFiles method. This
commit adds tests for EnumeratePSFiles method using a set of static fixture
test files.

Note that the behaviour of EnumeratePSFiles changes depending on the .Net
Framework edition


Previously the Workspace.EnumeratePSFiles method could only filter files
based on file extension (*.ps1, *.psm1, *.psd1). However editor settings tend
to use file glob patterns, but Editor Services did not have a library that could
parse them.

This commit:

  • Updates Editor Services to use the Microsoft.Extensions.FileSystemGlobbing
    library

  • Updated the build process to include the new FileSystemGlobbing DLL

  • The FileSystemGlobbing library uses an abstract file system to search, not
    an actual System.IO.FileSystem object. So to implement the same error handling
    and maximum depth recursion, a WorkspaceFileSystemWrapperFactory is used to
    create the Directory and File objects needed for the globbing library

    The WorkspaceFileSystemWrapperFactory can filter on:

    • Maximum recursion depth
    • Reparse points (Note that these aren't strictly Symlinks on windows. There
      are many other types of filesystem items which are reparse points
    • File system extension
    • Gracefully ignores any file access errors
  • The EnumeratePSFiles has two method signatures. One with no arguments which
    uses the Workspace object's default values and another where all arguments
    must be specified when enumerating the files

  • Adds tests for the EnumeratePSFiles method to ensure that it filters on glob
    and recursion depth.


Previously the EnumeratePSFiles method was modified to be able to use globbing
patterns to filter workspace files. This commit

  • Modifies the LanguageServerSettings class to capture the 'files' and 'search'
    Settings in order to determine the correct list of glob patterns to use when
    searching. Currently the 'files.exclude' and 'search.exclude' are merged
    together to generate the list of globs and then set the Workspace settings
    appropriately

  • Uses the 'search.followSymlinks' setting to determine whether to ignore
    reparse points

Note that the LanguageClient must be configured to send these settings during
the didChangeConfiguration events otherwise it will default to include
everything.


Work in Progress

  • Use a globbing library
  • Enforce a maxdepth rescursion
  • Don't care about errors. Just Carry on!
  • Ignore symlinks (Partial. reparse points are too generic BUT they're Windows only so 🤷‍♂️...)
  • Inject files.exclude
  • More tests to ensure depth and pattern searching are legit
  • Remove redundant code
  • Address TODOs
  • Investigate the ReferencesCodeLensProvider call sites

@glennsarti glennsarti requested a review from rjmholt as a code owner March 8, 2019 04:08
@glennsarti glennsarti force-pushed the modify_codelens_and_references branch 2 times, most recently from 454b6f1 to 46fe7d4 Compare March 10, 2019 06:06
@glennsarti
Copy link
Contributor Author

glennsarti commented Mar 10, 2019

Looks like I may need to issue workspace/configuration requests to get files.exclude information as it's not within the "usual" powershell scope.

TODO - Do I get a DidChangeConfiguration Notification when I change files.exclude? Yes, BUT the changed settings in the API call are for powershell only. Need to issue additional calls to get out-of-extension scope config info.
TODO - What about search.exclude?

https://microsoft.github.io/language-server-protocol/specification#workspace_configuration

@glennsarti
Copy link
Contributor Author

@TylerLeonhardt @rjmholt @rkeithhill

So I've reached a bit of an impasse. The EnumeratePSFiles method can now take include and exclude globs etc. however getting the globs from the Language Client is a little curious.

So far I see a couple of options

  1. The Language Server sends a request to client to request the current configuration
    https://microsoft.github.io/language-server-protocol/specification#workspace_configuration

This could be ok for VSCode, but PSES should be editor agnostic therefore it could be 'files.exclude' on VSCode and 'exclude.files' of Atom (or something else). The advantage for this is that it's a Lang. Server. only change so it doesn't require any client changes.

  1. Pass the exclude glob on the command when starting PSES

It would work, but if the user changes it, it will require PSES to restart. Not a great UX

  1. The Language Server will depend on the Language Client to send the configuration using a custom notification/request

This would make the client responsible for updating the server, which may be ok?. It does mean that until the server receives the client message it will use the "defaults"

Any thoughts on what would be the best way to proceed?

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Mar 11, 2019

That's a very good question...

Quick question... does number 1 only happen at startup and when values are changed?

I like number 1 personally... because we might be able to make it a powershell extension specific config like:

powershell.codelens.references.exclude

which could somehow inherit from files.exclude (maybe?)

@glennsarti
Copy link
Contributor Author

In my testing, VSCode will send a DidChangeConfiguration notification for any settings change, but it will only send the language specific settings in the payload (in our case powershell).

My thinking was to send a workspace/configuration request whenever I receive a DidChangeConfiguration notification, kind of like an out-of-band request. However the configuration settings I request are just text strings and like I said, my not be consistent across editors.

As per your comment:

I like number 1 personally... because we might be able to make it a powershell extension specific config like:

powershell.codelens.references.exclude

Because that settings is within the language "namespace" it will appear in the DidChangeConfiguration` notification so there's no need to request more information.

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Mar 13, 2019

@glennsarti can listen for files.exclude changes on the client side?

vscode.workspace.onDidChangeConfiguration(evt => {
   if (evt.affectsConfiguration('files.exclude')) {
     console.log('configuration updated');
     console.log(vscode.workspace.getConfiguration(undefined, null).get('files.exclude'));
   }
});

Then maybe we update our powershell.codelens.references.exclude from there

@glennsarti
Copy link
Contributor Author

Then maybe we update our powershell.codelens.references.exclude from there

That's the hard bit. Do you change the settings in the user's settings? workspace settings? per language settings?

There is an update method in WorkspaceConfiguration From the docs and what I know, there is no "in process" view where an extension could inject volatile settings. There is an inspect method which may be useful.

This is kinda why I was leaning towards making the language client send a notification and be as "dumb" as possible eg.

  PowerShellLanguageClientExtraSettings : {
    'filesExclude': [ 'glob1', 'glob2'],
    'searchExclude': [ 'glob1', 'glob2'],
  }

Then let the Language Server decide when and what to do with it e.g.
It could smash together filesExclude and searchExclude and powershell.codelens.references.exclude to generate a full list.

Side note - This doesn't just affect codelens either, also affects Peek and Goto Definitions and Workspace Symbols. Perhaps powershell.excludeWorkspaceFiles = ['glob1', 'glob2']

@glennsarti
Copy link
Contributor Author

From @TylerLeonhardt


A.. simpler-to-implement option that doesn’t fix everything is having a separate setting:
powershell.files.excludes

and the default value of the setting is files.excludes

but naturally the user would need to be educated to include what’s in their files.excludes if they make changes to powershell.files.excludes

@glennsarti
Copy link
Contributor Author

OOo...super interesting...You can also call commands

https://code.visualstudio.com/docs/editor/variables-reference#_command-variables

@TylerLeonhardt
Copy link
Member

TylerLeonhardt commented Mar 13, 2019

Right so the default would be the value of files.exclude...

I think the UX is that, you would see a box in the settings pane that gives you the default value (rather than starting from an empty box)...

So they would just tack on to the list the things they want to ignore.

This means that if they change files.exclude in the future, those changes wouldn't be in there since they specified a value for our setting.

This... Might be the way to go.

@glennsarti
Copy link
Contributor Author

impasse surmounted. Language Client can send other settings on the OnDidConfigurationChange notification

@glennsarti glennsarti force-pushed the modify_codelens_and_references branch from 1dbd530 to c179f45 Compare March 17, 2019 13:36
@glennsarti glennsarti changed the title {WIP}(GH-1039) Add filtering for CodeLens and References {WIP}(GH-879) Add filtering for CodeLens and References Mar 17, 2019
@glennsarti glennsarti force-pushed the modify_codelens_and_references branch from c179f45 to c1eaf1b Compare March 17, 2019 14:02
@glennsarti
Copy link
Contributor Author

Bouncing the PR due to the flaky debounce tests

Starting test execution, please wait...
ERROR: [xUnit.net 00:00:01.9798911]     Microsoft.PowerShell.EditorServices.Test.Protocol.Server.OutputDebouncerTests.OutputDebouncerAggregatesOutputEvents [FAIL]
At C:\projects\powershelleditorservices\PowerShellEditorServices.build.ps1:379 char:16
+ ...      exec { & $script:dotnetExe test -f $script:TestRuntime.Core (Dot ...
+                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
At C:\projects\powershelleditorservices\PowerShellEditorServices.build.ps1:371 char:1

@glennsarti glennsarti closed this Mar 17, 2019
@glennsarti glennsarti reopened this Mar 17, 2019
@glennsarti
Copy link
Contributor Author

Look at the code lens call sites for FindReferencesOfSymbolAsync they all seem legit and ok. Will cleanup the PR and then it's ready for merge.

@glennsarti glennsarti force-pushed the modify_codelens_and_references branch 2 times, most recently from cedbd6a to 2c56c44 Compare April 1, 2019 13:54
@glennsarti glennsarti changed the title {WIP}(GH-879) Add filtering for CodeLens and References (GH-879) Add filtering for CodeLens and References Apr 1, 2019
@PowerShell PowerShell deleted a comment May 2, 2019
@PowerShell PowerShell deleted a comment May 2, 2019
@PowerShell PowerShell deleted a comment May 2, 2019
@PowerShell PowerShell deleted a comment May 2, 2019
Copy link
Member

@TylerLeonhardt TylerLeonhardt left a comment

Choose a reason for hiding this comment

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

LGTM (+nits) looking forward to getting this in, @glennsarti!

Copy link
Contributor

@rjmholt rjmholt left a comment

Choose a reason for hiding this comment

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

Looks really good! Thanks @glennsarti!

@glennsarti glennsarti force-pushed the modify_codelens_and_references branch from 8e237c3 to 6ebfa77 Compare May 4, 2019 20:37
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
glennsarti added 3 commits May 4, 2019 13:48
Previously the Workspace.EnumeratePSFiles method could only filter files
based on file extension (*.ps1, *.psm1, *.psd1).  However editor settings tend
to use file glob patterns, but Editor Services did not have a library that could
parse them.

This commit:
* Updates Editor Services to use the Microsoft.Extensions.FileSystemGlobbing
  library
* Updated the build process to include the new FileSystemGlobbing DLL
* The FileSystemGlobbing library uses an abstract file system to search, not
  an actual System.IO.FileSystem object. So to implement the same error handling
  and maximum depth recursion, a WorkspaceFileSystemWrapperFactory is used to
  create the Directory and File objects needed for the globbing library

  The WorkspaceFileSystemWrapperFactory can filter on:
  - Maximum recursion depth
  - Reparse points (Note that these aren't strictly Symlinks on windows.  There
    are many other types of filesystem items which are reparse points
  - File system extension
  - Gracefully ignores any file access errors

* The EnumeratePSFiles has two method signatures.  One with no arguments which
  uses the Workspace object's default values and another where all arguments
  must be specified when enumerating the files

* Adds tests for the EnumeratePSFiles method to ensure that it filters on glob
  and recursion depth.
…sions

Previously the EnumeratePSFiles method was modified to be able to use globbing
patterns to filter workspace files. This commit

* Modifies the LanguageServerSettings class to capture the 'files' and 'search'
  Settings in order to determine the correct list of glob patterns to use when
  searching.  Currently the 'files.exclude' and 'search.exclude' are merged
  together to generate the list of globs and then set the Workspace settings
  appropriately
* Uses the 'search.followSymlinks' setting to determine whether to ignore
  reparse points

Note that the LanguageClient must be configured to send these settings during
the didChangeConfiguration events otherwise it will default to include
everything.
Previously the paths emitted by `EnumeratePSFiles` were normalised to use the
directory path separator appropriate for the platform.  In particular on Windows
the paths emitted by the Microsoft.Extensions.FileSystemGlobbing library
contained both forward and backward slashes.  However on inspection this is not
required as all the paths are converted to URIs when communicating over LSP, so
the normalisation is no longer required.

This commit removes the normalisation and updates the tests to reflect the new
paths.
@glennsarti glennsarti force-pushed the modify_codelens_and_references branch from 6ebfa77 to 19b2703 Compare May 4, 2019 20:49
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@PowerShell PowerShell deleted a comment May 4, 2019
@glennsarti
Copy link
Contributor Author

@rjmholt @TylerLeonhardt Nits and changes addressed.

@TylerLeonhardt
Copy link
Member

@SeeminglyScience did you want to give this one more look since you requested changes a while back? Otherwise, we can merge.

@TylerLeonhardt TylerLeonhardt merged commit f370883 into PowerShell:master May 11, 2019
@TylerLeonhardt
Copy link
Member

Awesome work Glenn :)

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.

Codelens shows references to files/folders excluded using "files.exclude" setting
4 participants