LSP-based IDE support plan #1077
Replies: 25 comments 69 replies
|
This is a well thought out plan. A few thoughts : To my understanding, there is no support in the LSP for commenting/uncommenting. Please also document when we should tackle the creation of a hybrid VS extension so that we can include the templates. Should we also include an aspirational statement about whether extension code not related to the LSP should be ported out of VSSDK to VS.Extensibility? What appetite is there to include changes/improvements to the binding discovery process (such as code-gen bindings)? |
|
Sounds like a good plan. Does that mean that the community has decided that this approach provides a good enough interaction/support as a reqnroll plugin in order to go ahead with this? Or should we still evaluate per feature how well it scores and whether it passes as good, good enough, or sub par and look for ways to mitigate any sub par user experiences? A couple of remarks:
Phase 3:
For now the uncommented routine just relies on ctrl+z but I can of course also toggle when a |
|
Any thoughts or preferences on how the server should be packaged/distributed? Would we publish this as a nuget package or kept interna as a git submodule? |
|
I've noticed that the POC is declaring server capabilities globally (during init) and those would (?) apply for both .feature and .cs files. I fear a risk that our LSP would not play well with other LSPs and/or native C# support provided by the IDEs. Let's take care to include some form of experience testing to confirm proper cooperative behaviors. |
|
I will grant that the following is not a high priority item for the first implementation, but I am intrigued by the idea that we precompute the mapping between pickle steps and bindings during the compilation phase. The result would be an artifact that could be used by the LSP to provide Definition and References (especially to external assemblies). But such an artifact could also be used by other tooling such as reports on binding usage (or non-usage). |
|
Another idea to consider is to refactor the code within Reqnroll so that the |
|
We will need to give some thought on telemetry. Do we need to plan a step to normalize the set of monitored events (and data structures) from all three clients that will consume the LSP server? The LSP standard includes a |
|
Here is a proposed structure for the projects that will make up the Visual Studio extension. graph TD
CT["Analytics<br/>(harvested from existing VS Extension)<br/>netstandard2.0"]
subgraph Common ["Common"]
Config[Reqnroll Configuration<br/>netstandard2.0]
end
subgraph LSPHost ["Reqnroll Language Server"]
LSP[LspServerProject<br/>net8<br/>LSP server logic]
Connector["Binding Engine<br/>Reqnroll.dll<br/>run-time varies"]
LSP -.->|"Out-of-proc"| Connector
end
subgraph VisualStudioExtension["Solution: Reqnroll.Plugin.VisualStudio.sln"]
EP["ExtensionProject<br/>VSIX manifest<br/>VSSDK+Extensibility<br/>(net481)"]
subgraph Classic ["Classic VSSDK"]
PTP["ProjectTemplate Project<br/>net481<br/>.vstemplate"]
ITP["ItemTemplate Project<br/>net481<br/>.vstemplate"]
WP[WizardsProject<br/>net481<br/>IWizard impl]
end
subgraph Modern ["VisualStudio.Extensibility"]
Editing["EditingProject<br/>(net8-windows)<br/>LanguageServerProvider<br/>CodeLensProvider"]
end
EP -.->|"Assets"| PTP
EP -.->|"Assets"| ITP
EP -.->|"Assets"| WP
EP -.->|"Out-of-proc"| Editing
end
EP -.->|consumes shared lib| CT
WP -.->|consumes shared lib| CT
Editing -.->|consumes shared lib| CT
Editing -.->|"Out-of-proc"| LSP
VisualStudioExtension-.->|"consumes shared lib"|Common
classDef shared fill:#e1f5fe
classDef classic fill:#fff3e0
classDef modern fill:#f3e5f5
classDef vsix fill:#e8f5e8
classDef hostedreqnroll fill:#e8eaf6
class Common,CT,Config shared
class EP,PTP,ITP,WP classic
class Editing,LSP modern
class VSIX vsix
class Connector hostedreqnroll
|
|
Regarding gherkin document formatting, the existing VisualStudio extension supports two ways of configuring a few settings - in the reqnroll.config file and in the .editorconfig file. The extension merges these settings together (the former provides a global set, the .editorconfig provide overrides at a folder level). Do we want to support these in the new extensions? (We might consider dropping the support for reqnroll.config settings in favor of the .editorconfig approach) What approach should be taken to feed these settings to the formatting service that will run inside the LSP? Is reading these settings a responsibility of the LSP or of the IDE Extension? The LSP message |
|
Scope questions for you @gasparnagy:
|
|
User experience question related to binding discovery - With the LSP we have the opportunity to use the Roslyn parser to discover bindings in project c# source without requiring a compilation cycle. But we also will continue to rely on Reqnroll to perform reflection-based discovery of external assemblies not in the current project. Do we want to attempt this? |
|
I'm experimenting with extracting the Feature file parsing and tagging out of the existing VS Extension. |
|
Re: The VisualStudio extension - would you like this release to behave as an upgrade of the existing VS Extension? (Use the same identifying GUID, name, etc) or be an entirely different product? |
|
Cucumber has an LSP implementation. How closely would we like to match their handling of semantic tagging? In their handling of semantic tag mapping they place a semantic tag on the mediaType assigned to a docString (if it exists) (such as ```xml) Secondly, should we match their pre-existing tag mapping? Their mapping is: export const semanticTokenTypes: SemanticTokenTypes[] = [
SemanticTokenTypes.keyword, // Feature, Scenario, Given etc
SemanticTokenTypes.parameter, // step parameters
SemanticTokenTypes.string, // DocString content and ``` delimiter, table cells (except example table header rows)
SemanticTokenTypes.type, // @tags and DocString ```type
SemanticTokenTypes.variable, // step <placeholder>
SemanticTokenTypes.property, // examples table header row
SemanticTokenTypes.comment, // # commentsFrom the comments in the code, this seems mostly driven by what VSCode easily supports. |
|
I would like to suggest a few new/changed features that should be possible with Diagnostics and CodeLens:
|
|
I'm noticing in the Reqnroll.VisualStudio projects the use of C# attributes such as Do we wish to continue to use them? Is there an update/upgrade that we should consider using? |
|
After some experimentation on my own and reading through @ThomasHeijtink's POC, I've drafted the attached design document. My intent is to confirm the scope, approach, non-functional requirements, and open issues. I apologize in advance for the length. But please review and provide any feedback you have. |
|
I have a working prototype, with tests, for Visual Studio, that implements Features F1, F2, F3, and F4 of the design plan (updated) I previously posted. The prototype:
I will keep working through the plan and documenting findings by updating the plan. The handling of semantic tokens for VisualStudio was quite challenging as the support for it within its built-in LSP client and VS.Extensibility is just not mature. Comments of course are welcome. |
|
While attempting to implement Presume you have a feature file: Feat.feature in Project A. Project A also has a set of step bindings that map to that feature and it binds without error. You create Project B and link in the feature file Feat.feature from Project A. Project B has its own set of bindings. If those bindings in B differ from those in A it will not be obvious in the editor. When the IDE opens a file it provides the LSP server with the file-path. It does not indicate which project context this editing operation is within. Both Projects A and B will see the file as having a file-path from within's Project A's folder structure. This differs from our current VS extension as the display of binding coloring is sensitive to the project from which the feature file has been opened. My apologies if that description is convoluted and hard to follow. |
|
Per feedback from @Code-Grump the design doc has been restructured into 4 separate documents: |
|
I have a feature complete implementation (VS only at this point) here The following features are implemented:
The largest hurdle to overcome has been the mismatch between the .net project system and the LSP server's limited concept of file ownership. To overcome that, I've defined several custom request methods and notifications which are used by the VS extension code to send information to the LSP server about which documents belong to a project (and changes in that status). I have one undiagnosed issue that occurs at startup in that when opening an existing solution, if that solution had open files in the editor during its last session those will be reopened. The reopening occurs before the LSP gets spun up so those editors don't get LSP support. Simply clicking on them, or navigating away and back again causes the LSP to launch. Also, as the LSP is spun up lazily by VS and if there are binding classes open for editing they don't get LSP support until a feature file is opened. The solution also includes a set performance validation tests. These provide both raw function invocation response time tests as well as a simulated editing session (with debounce cancels, etc). The test can be run with the LSP running either in-proc or out-of-proc. Of course, I welcome feedback from anyone that would like to take it for a spin. |
|
@gasparnagy There is a feature in the existing VS Extension to support SpecSync - specially formatted tags were rendered by the extension as clickable URL links. Do we need to support this feature in the new extension? Across all three IDEs or just VisualStudio? |
|
Packaging question:
We could simply build/deploy the LSP server as a .net10 exe (cross-platform, but requires the user to have the .net10 run-time installed). |
|
I've included now a largely complete VSCode extension.
|
|
Rider implementation is now substantially complete. All three extensions (for Visual Studio, VSCode, and Rider) are in the reqnroll/Reqnroll.IdeSupport repo. The README and CONTRIBUTING docs provide instructions on how to build and launch each. Documentation is drafted and is located in the docs/site folder. It is authored using the same frameworks as the main docs.reqnroll.net site. Open that folder in VSCode and follow the instructions in the README for how to build the documentation. If you have any questions or problems, please open an issue in the Reqnroll.IdeSupport repo |

Uh oh!
There was an error while loading. Please reload this page.
This discussion board can be used to have a plan to an LSP-based IDE support based on the proof of concept (PoC) of @ThomasHeijtink: https://github.com/ThomasHeijtink/Reqnroll.Plugin
All of the below is just suggestions, feel free to comment or suggest changes.
Overall goals
Implementation plan
I suggest making the implementation in phases: once we are done with a phase, we can make a review and move on to the next phase only after we are happy with the approach. With this we can avoid to produce a massive amount of code that gets stuck in review for forever.
The suggested phase arrangement could be:
Phase 1: Basic syntax coloring
We should start with an "empty" LSP server and the shells for VS, VSCode and Rider, that provides syntax coloring for Gherkin files using the Gherkin parser. The default language configuration should be read from
reqnroll.json.Related specs:
Related codes (consider to reuse):
With this phase we can verify:
Phase 2: Binding discovery
Import existing binding discovery method from VS ext (processing compiled test assemblies with connectors after build), extend it with a code-based discovery approach and integrate it with core features like: showing undefined steps, define step and go to step definition
Related specs:
Related codes (consider to reuse):
With this phase we can verify:
Phase 3: Editor improvements
Extend editor support with additional missing features:
Phase 4: Navigation improvements
Extend with additional missing features:
All reactions