Skip to content
This repository was archived by the owner on May 4, 2023. It is now read-only.

Commit 3e60e8e

Browse files
committed
Add Rosie related information, and additional formatting n the dev documentation.
1 parent 15a8a05 commit 3e60e8e

File tree

1 file changed

+111
-23
lines changed

1 file changed

+111
-23
lines changed

DEVELOPMENT.md

Lines changed: 111 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,44 @@
11
![build and test workflow](https://github.com/codiga/visualstudio-extension/actions/workflows/main.yml/badge.svg)
22

33
# Development documentation
4+
45
This documentation provides a high level view on the technical components of the extension project.
56

67
# Table of contents
7-
1. [General](#general)
8+
9+
1. [General](#general)
810
2. [Releasing](#releasing)
911
3. [Project structure](#project-structure)
1012
4. [Feature overview](#feature-overview)
11-
1. [Shortcut snippets](#shortcut-snippets)
12-
2. [Inline completion](#inline-completion)
13-
3. [Snippet search](#snippet-search)
14-
4. [Settings](#settings)
13+
1. [Shortcut snippets](#shortcut-snippets)
14+
2. [Inline completion](#inline-completion)
15+
3. [Snippet search](#snippet-search)
16+
4. [Rosie code analysis](#rosie-code-analysis)
17+
5. [Settings](#settings)
1518
5. [Frameworks/Packages](#frameworkspackages)
1619
6. [Testing](#testing)
1720
7. [Links/Help](#linkshelp)
1821

1922
# General
23+
2024
As Visual Studio has a long history, the SDK also has different APIs. The older one is referred to as [Legacy API](https://learn.microsoft.com/en-us/visualstudio/extensibility/internals/legacy-language-service-extensibility?view=vs-2022) and the current one uses the [MEF](https://learn.microsoft.com/en-us/visualstudio/extensibility/managed-extensibility-framework-in-the-editor?view=vs-2022) and async API. Not all APIs were migrated to the new style yet, so we have a mix of both in the extension. For example, the API for inserting snippets is a Legacy API.
25+
2126
## MEF
27+
2228
The Managed Extensibility Framework is working like a dependency injection framework for Visual Studio components. Registering implementations of a type or interface is done via the `[Export]` attribute and receiving already registered components and services is done via `[Import]`. Depending on the context most exported components are instantiated as singletons.
2329

2430
# Releasing
2531

32+
The build and release process is automated via GitHub Actions. The release workflow is defined in [release.yml](.github/workflows/release.yml).
2633

27-
The build and release process is automated via GitHub Actions. The release workflow is defined in [release.yml](.github/workflows/release.yml).
2834
## Versioning
2935

36+
The version of the extension is stored in the manifest file [`src/source.extension.vsixmanifest`](src/Extension/source.extension.vsixmanifest).
37+
The vsix manifest editor in Visual Studio generates the C#-Class [`src/Extension/source.extension.cs`](src/Extension/source.extension.cs) that
38+
is used to version the assemblies. To update the Version of the Extension I recommend doing it in the VSIX-editor.
3039

31-
The version of the extension is stored in the manifest file [`src/source.extension.vsixmanifest`](src/Extension/source.extension.vsixmanifest). The vsix manifest editor in Visual Studio generates the C#-Class [`src/Extension/source.extension.cs`](src/Extension/source.extension.cs) that is used to version the assemblies. To update the Version of the Extension I recommend doing it in the VSIX-editor.
3240
## Releasing a new version to the marketplace
41+
3342
<img align="right" src="images/version.png"/>
3443

3544
To trigger a new release build follow these steps:
@@ -39,14 +48,16 @@ To trigger a new release build follow these steps:
3948

4049
>To further automate this process, we would need to update the manifest file AND the C#-File with the just generated version tag before the extension is compiled in the build step.
4150
42-
4351
# Project structure
52+
4453
The project is divided into three projects:
4554
* [`Extension.csproj`](src/Extension/Extension.csproj) - for the actual extension
4655
* [`GraphQLClient.csproj`](src/GraphQLClient/GraphQLClient.csproj) - for handling the Codiga API
4756
* [`Tests.csproj`](src/Tests/Tests.csproj) - for the unit tests
4857

49-
Visual Studio Extensions still need to target full .NET 4.8 Framework as Visual Studio itself is not migrated to .NET 6 or 7. That means for all libraries and packages we reference in our `Extension.csproj` we can only use [.NET Standard 2.0](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0).
58+
Visual Studio Extensions still need to target full .NET 4.8 Framework as Visual Studio itself is not migrated to .NET 6 or 7.
59+
That means for all libraries and packages we reference in our `Extension.csproj` we can only use
60+
[.NET Standard 2.0](https://learn.microsoft.com/en-us/dotnet/standard/net-standard?tabs=net-standard-2-0).
5061

5162
## Folder structure
5263

@@ -62,20 +73,50 @@ Visual Studio Extensions still need to target full .NET 4.8 Framework as Visual
6273
* `SnippetSearch` - The menu entry and the tool window for the snippet search
6374
* `ExtensionPackage.cs` - registrations for settings dialog and search window
6475
* `.vsixmanifest` - metadata for the extension that will show up in the marketplace
65-
66-
<br>
6776

77+
<br>
6878

6979
# Feature overview
7080

81+
## GraphQL client, queries and mutations
82+
83+
The extension uses a GraphQL client to send queries and mutations to Codiga.
84+
85+
The queries are used to fetch timestamp-, snippet- and ruleset related data from Codiga, while mutations are used to send metrics to Codiga
86+
of the usage of certain functionality, for example when a Rosie fix is applied.
87+
88+
The query files are available under the [`GraphQLClient/Queries`](/src/GraphQLClient/Queries) folder,
89+
and are loaded and provided via [`QueryProvider.cs`](/src/GraphQLClient/QueryProvider.cs).
90+
91+
### User-Agent
92+
93+
The User-Agent header is sent in order to identify the client application the GraphQL requests are sent from.
94+
95+
The `RosieClient` uses a value in the form "<product name> <major version> <minor version>, e.g. *Microsoft Visual Studio Community 2022 17 4*,
96+
while `CodigaClient` uses a simpler one in the form "VisualStudio/<version>, e.g. *"VisualStudio/17.4.33103.184 D17.4"*.
97+
98+
### User fingerprint
99+
100+
In general, the fingerprint is a unique string generated when the plugin is installed.
101+
102+
### Codiga API Token
103+
104+
Having a Codiga account registered, using this token, users can access and use to their private rulesets and rules in the IDE.
105+
106+
The configuration is provided in the Visual Studio settings via [`ExtensionOptions.cs`](/src/Extension/Settings/ExtensionOptions.cs) and the `Extension.Settings` namespace.
107+
71108
## Shortcut snippets
109+
72110
The shortcut snippets feature is triggered by typing `.` in the editor. This is the general workflow:
73111
<img src="images/snippet-workflow.png">
74112
The key part here is that we prevent the normal code completion session from completing the keyword and start an Expansion session instead.
113+
75114
### Triggering
115+
76116
For the completion menu and triggering we use the standard API based on [this example](https://github.com/microsoft/VSSDK-Extensibility-Samples/tree/master/AsyncCompletion).
77117

78118
### Inserting
119+
79120
Snippet insertion sessions are called [*Expansion*](https://learn.microsoft.com/en-us/visualstudio/extensibility/walkthrough-implementing-code-snippets?view=vs-2022&tabs=csharp) on the Visual Studio API. The insertion process is the same for all three features and is done in [`AssistantCompletion/ExpansionClient.cs`](src/Extension/AssistantCompletion/ExpansionClient.cs). We bypass the regular `.snippet` files by calling:
80121
```csharp
81122
public int IVsExpansion.InsertSpecificExpansion (
@@ -86,41 +127,50 @@ public int IVsExpansion.InsertSpecificExpansion (
86127
string pszRelativePath,
87128
out Microsoft.VisualStudio.TextManager.Interop.IVsExpansionSession pSession);
88129
```
89-
See the [documentation](https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.textmanager.interop.ivsexpansion.insertspecificexpansion?view=visualstudiosdk-2022).
130+
See the [documentation](https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.textmanager.interop.ivsexpansion.insertspecificexpansion?view=visualstudiosdk-2022).
90131

91-
This API allows us to insert snippets from in-memory XML using the [Visual Studio snippet XML schema](https://learn.microsoft.com/en-us/visualstudio/ide/code-snippets-schema-reference?view=vs-2022).
92-
We just need to serialize the incoming Codiga Recipes into the required XML format:
132+
This API allows us to insert snippets from in-memory XML using the [Visual Studio snippet XML schema](https://learn.microsoft.com/en-us/visualstudio/ide/code-snippets-schema-reference?view=vs-2022).
133+
We just need to serialize the incoming Codiga Recipes into the required XML format:
93134

94135
<img src="images/serializer-workflow.png">
95-
136+
96137
During the expansion session, we use [`IOleCommandTarget`](https://learn.microsoft.com/en-us/dotnet/api/microsoft.visualstudio.ole.interop.iolecommandtarget?view=visualstudiosdk-2022) to handle incoming keystrokes and commands to pass `Tab` keys to the expansion and enable navigation between the user variables. The snippet usage reporting is also done in this module.
97138

98139
>For more details look at the answer on [this thread](https://learn.microsoft.com/en-us/answers/questions/1018899/visual-studio-extensibility-addinginstalling-snipp.html).
99140
100141
For a detailed explanation on the async completion API, there is a great GitHub issue at [microsoft/vs-editor-api#Async Completion API discussion](https://github.com/microsoft/vs-editor-api/issues/9).
101142

102-
103143
## Inline completion
144+
104145
The inline completion is triggered by starting a line comment on a new line.
146+
105147
### Triggering
148+
106149
To be able to trigger the inline completion we make use of another `IOleCommandTarget` in [`InlineCompletion/InlineCompletionClient.cs`](src/Extension/InlineCompletion/InlineCompletionClient.cs). Where we check if a session should be started based on the typed text of the current line.
150+
107151
### Preview
152+
108153
The preview is done by drawing on the editor Canvas by using [TextAdornments](https://learn.microsoft.com/de-de/archive/blogs/lucian/visual-studio-text-adornment-vsix-using-roslyn) which allows adding WPF controls in relation to editor text lines. The drawing of the instructions and the preview is done in [`InlineCompletionView.cs`](src/Extension/InlineCompletion/InlineCompletionView.cs).
109154
> An approach inserting styled code directly to the editor was dismissed as scrolling through suggestions would add all of those to the undo/redo stack which resulted in a bad UX.
110155
111156
### Inserting
157+
112158
Inserting is handled the same way as with the shortcut snippets using `ExpansionClient.StartExpansion()`.
113159

114160
## Snippet search
115-
The snippet search is implemented using a [ToolWindow](https://learn.microsoft.com/en-us/visualstudio/extensibility/adding-a-tool-window?view=vs-2022). Tool windows are written using WPF and the search window UI is defined in [`SnippetSearch/View/SnippetSearchControl.xaml`](src/Extension/SnippetSearch/View/SnippetSearchControl.xaml). We try to follow [MVVM](https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm) as much as possible, therefore the UI is mostly driven by the Binding on [`SnippetSearchViewModel.cs`](src/Extension/SnippetSearch/View/SnippetSearchViewModel.cs).
161+
162+
The snippet search is implemented using a [ToolWindow](https://learn.microsoft.com/en-us/visualstudio/extensibility/adding-a-tool-window?view=vs-2022). Tool windows are written using WPF and the search window UI is defined in [`SnippetSearch/View/SnippetSearchControl.xaml`](src/Extension/SnippetSearch/View/SnippetSearchControl.xaml). We try to follow [MVVM](https://learn.microsoft.com/en-us/dotnet/architecture/maui/mvvm) as much as possible, therefore the UI is mostly driven by the Binding on [`SnippetSearchViewModel.cs`](src/Extension/SnippetSearch/View/SnippetSearchViewModel.cs).
116163

117164
### Preview
165+
118166
The preview for snippets from the Snippet Search is done by inserting the code in the editor and using a [Classifier](https://learn.microsoft.com/en-us/visualstudio/extensibility/language-service-and-editor-extension-points?view=vs-2022#extend-classification-types-and-classification-formats) to style the span in a way that makes it obvious to users that this is a preview. The classifier is polling the text spans to be classified on changes to the editor. While the preview is active we provide a static span to be used. When the preview ends, it is set to `null`. The whole preview and classification logic is grouped under [`SnippetSearch/Preview`](/src/Extension/SnippetSearch/Preview/).
119167

120168
### Inserting
169+
121170
When inserting the snippet the preview span is replaced by the new Expansion via the [`ExpansionClient`](src/Extension/AssistantCompletion/ExpansionClient.cs).
122171

123172
### Menu item
173+
124174
To be able to bring up the tool window via the menu, two parts are needed:
125175
1. Define the menu item command in a [VS command table](https://learn.microsoft.com/en-us/visualstudio/extensibility/internals/visual-studio-command-table-dot-vsct-files?view=vs-2022) ([`SnippetSearchPackage.vsct`](src/Extension/SnippetSearch/SnippetSearchPackage.vsct))
126176
2. Implement the command that gets fired when clicking the menu item (done in [`SearchWindowMenuCommand.cs`](/src/Extension/SnippetSearch/SearchWindowMenuCommand.cs))
@@ -143,14 +193,22 @@ If what is opened is simply a folder, and not an actual solution, the `codiga.ym
143193
Here comes in [`RosieRulesCache`](/src/Extension/Rosie/RosieRulesCache.cs) which provides a periodic background thread for polling the contents of this config file,
144194
and looking for rule changes on Codiga Hub, as well as the caches the received rules per language.
145195

196+
The cache is initialized when the tagging is first invoked in an editor. (See **Tagging** section below)
197+
198+
The periodic update is executed in every 10 seconds, and updates the cache if either the `codiga.yml` file has changed,
199+
or the configured rulesets (or underlying rules) have changed on Codiga Hub.
200+
201+
### Rosie client
202+
146203
The rules are retrieved via [`RosieClient`](/src/Extension/Rosie/RosieClient.cs), and this is where `RosieRulesCache` is initialized before sending the first
147204
request to the Rosie server. This way, it is initialized only when code analysis is actually needed.
148205

149206
For response/request (de)serialization, you can find the model classes in the `Extension.Rosie.Model` namespace.
150207

151208
### Adding new rule AST types
152209

153-
You can add new constants and mappings for the new types in [`RosieRuleAstTypes`](/src/Extension/Rosie/Model/RosieRuleAstTypes.cs).
210+
- Add new constants into the `ElementCheckedEnumeration` in [`schema.graphql`](/src/GraphQLClient/schema.graphql).
211+
- Add new constants and mappings for the new types in [`RosieRuleAstTypes`](/src/Extension/Rosie/Model/RosieRuleAstTypes.cs).
154212

155213
### Adding support for new Rosie languages
156214

@@ -159,6 +217,10 @@ and [`RosieLanguageSupport.GetRosieLanguage`](/src/Extension/Rosie/RosieLanguage
159217

160218
If a language needs special treatment on the caching part, make sure to update at least [`RosieRulesCache.GetCachedLanguageTypeOf`](/src/Extension/Rosie/RosieRulesCache).
161219

220+
If default ruleset suggestions are also needed for the language, then:
221+
- create a new `Default*RulesetConfig` constant in [`CodigaRulesetConfigs`](/src/Extension/Rosie/CodigaRulesetConfigs.cs)
222+
and hook it into `CreateCodigaConfigFile(LanguageEnumeration, SVsServiceProvider)` in `CodigaConfigFileUtil`.
223+
162224
### Tagging
163225

164226
#### Tagging in general in Visual Studio extensions
@@ -238,20 +300,48 @@ There are three lightbulb actions (quick fixes) available for each violation:
238300
<br>
239301

240302
## Settings
303+
241304
The settings dialog is also divided into the settings model and the options dialog that shows up in the VS settings.
242-
The definition and registration of the Codiga settings are done in [`Settings/ExtensionOptions.cs`](src/Extension/Settings/ExtensionOptions.cs). These settings are stored in the Windows registry and can be accessed via a singleton instance `CodigaOptions.Instance`. The UI for the settings is defined in [`OptionsPage.xaml`](src/Extension/Settings/OptionsPage.xaml). For the simple settings dialog, the minimal logic is done in the [code-behind](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8) file [`OptionsPage.xaml.cs`](src/Extension/Settings/OptionsPage.xaml.cs).
305+
The definition and registration of the Codiga settings are done in [`Settings/ExtensionOptions.cs`](src/Extension/Settings/ExtensionOptions.cs).
306+
307+
These settings are stored in the Windows registry and can be accessed via a singleton instance `CodigaOptions.Instance`.
308+
309+
The UI for the settings is defined in [`OptionsPage.xaml`](src/Extension/Settings/OptionsPage.xaml).
310+
For the simple settings dialog, the minimal logic is done in the
311+
[code-behind](https://learn.microsoft.com/en-us/dotnet/desktop/wpf/advanced/code-behind-and-xaml-in-wpf?view=netframeworkdesktop-4.8) file [`OptionsPage.xaml.cs`](src/Extension/Settings/OptionsPage.xaml.cs).
243312

244313
# Frameworks/Packages
314+
245315
List of used third-party frameworks and packages:
246316

247317
| Library | Purpose |
248318
|----------------------------------------------------------------------------------------------------|-------------------------------------------|
249319
| [NUnit](https://nunit.org/) | Unit test framework |
250320
| [Moq](https://github.com/Moq) | For mocking in unit tests |
251321
| [GraphQL .NET](https://github.com/graphql-dotnet/graphql-dotnet) | For consuming the Codiga API |
252-
| [Visual Studio Community Toolkit](https://github.com/VsixCommunity/Community.VisualStudio.Toolkit) | For easier development against the VS SDK |
322+
| [Visual Studio Community Toolkit](https://github.com/VsixCommunity/Community.VisualStudio.Toolkit) | For easier development against the VS SDK |
323+
324+
## Environments
325+
326+
In case testing on different environments is necessary, you can use the following endpoints:
327+
328+
| Environment | Codiga | Rosie |
329+
|-------------|---------------------------------------|--------------------------------------------|
330+
| Production | https://api.codiga.io/graphql | https://analysis.codiga.io/analyze |
331+
| Staging | https://api-staging.codiga.io/graphql | https://analysis-staging.codiga.io/analyze |
253332

254333
# Testing
334+
335+
## Rosie
336+
337+
Rosie related features are test via unit testing, with some mock types when it comes to tagging.
338+
339+
Due to UI and threading related limitations, the `TextBuffer` is replaced with a mock implementation that uses simple string manipulation under the hood.
340+
This makes is possible to test the tagging in a simpler way, and test the lightbulb actions in a "visual" way, being able to compare the before and after states
341+
of the document easily.
342+
343+
## Extras
344+
255345
Some general overview of features and edge cases beyond the defined extension main features that should be tested with Visual Studio:
256346

257347
| Scenario | Expected |
@@ -261,12 +351,10 @@ Some general overview of features and edge cases beyond the defined extension ma
261351
| Changing the font settings under Tools -> Options -> Environment -> Fonts and Colors | Should also affect the inline completion and snippet search preview. |
262352

263353
# Links/Help
354+
264355
Some helpful links:
265356
* [Community examples](https://github.com/VsixCommunity/Samples)
266357
* [Official example repo](https://github.com/microsoft/VSSDK-Extensibility-Samples)
267358
* [VSIX Cookbook](https://www.vsixcookbook.com/)
268359
* [Gitter community](https://gitter.im/Microsoft/extendvs)
269360
* [Visual Studio YT channel with tutorials](https://www.youtube.com/playlist?list=PLReL099Y5nRdG2n1PrY_tbCsUznoYvqkS)
270-
271-
272-

0 commit comments

Comments
 (0)