├── .gitignore
├── images
├── info
├── Features
│ ├── img
│ │ ├── nguid_macro.png
│ │ ├── template_editor.png
│ │ └── Features_navigation.png
│ ├── Actions
│ │ └── img
│ │ │ ├── rich_text.png
│ │ │ ├── fix_in_scope.png
│ │ │ └── context_action.png
│ └── Tools
│ │ └── img
│ │ └── code_cleanup_dialog.png
├── basics
│ └── img
│ │ └── run-configurations.png
├── PSI
│ ├── References
│ │ └── img
│ │ │ └── mvc_ctrl_click.png
│ └── img
│ │ ├── iexpressiontype_hierarchy.png
│ │ └── ideclaredelement_hierarchy.png
├── Features__Code_Inspections__Sample.png
├── HowTo
│ ├── AnalyzeCode
│ │ └── img
│ │ │ └── analyze-code.png
│ ├── CreateContextAction
│ │ └── img
│ │ │ ├── hummer.png
│ │ │ └── context-action.png
│ ├── NavigateCode
│ │ └── img
│ │ │ ├── psi-example.png
│ │ │ ├── add-navigate-to-action.png
│ │ │ └── project-model-example.png
│ ├── CreateQuickFix
│ │ └── img
│ │ │ └── create-quick-fix.png
│ ├── IntegrateWithReSharper
│ │ └── img
│ │ │ ├── actions.png
│ │ │ ├── daemons.png
│ │ │ ├── options.png
│ │ │ ├── code-cleanup.png
│ │ │ ├── generate-menu.png
│ │ │ ├── quick-fixes.png
│ │ │ ├── refactorings.png
│ │ │ ├── tool-windows.png
│ │ │ ├── code-completion.png
│ │ │ ├── live-templates.png
│ │ │ └── IntegrateWithReSharper_navigation.png
│ └── AddSettingsToOptions
│ │ └── img
│ │ └── setting-resharper-options.png
├── Platform
│ ├── Zones
│ │ └── img
│ │ │ └── options_features.png
│ └── VisualStudio
│ │ └── img
│ │ ├── relocate_to_per_user.png
│ │ └── relocate_to_custom_hive.png
├── Platform__Icons__Themed_Icon_Viewer.png
└── sdkdocs-template
│ ├── images
│ ├── main-sprite.png
│ └── main-sprite@2x.png
│ ├── webhelp
│ ├── jetbrains.png
│ ├── mstile-70x70.png
│ ├── mstile-144x144.png
│ ├── mstile-150x150.png
│ ├── mstile-310x150.png
│ ├── mstile-310x310.png
│ ├── apple-touch-icon-57x57.png
│ ├── apple-touch-icon-60x60.png
│ ├── apple-touch-icon-72x72.png
│ ├── apple-touch-icon-114x114.png
│ ├── apple-touch-icon-120x120.png
│ ├── apple-touch-icon-144x144.png
│ ├── apple-touch-icon-152x152.png
│ ├── apple-touch-icon-180x180.png
│ └── apple-mask-icon.svg
│ └── rakelib
│ └── build_pdf
│ └── kotlin-logo.png
├── topics
├── info
├── Platform
│ ├── Zones
│ │ ├── Licensing.md
│ │ ├── Zones_Troubleshooting.md
│ │ ├── Implementation.md
│ │ ├── Zones_HowTo.md
│ │ └── FeaturesProducts.md
│ ├── Lifetime
│ │ ├── Lifetime_ComponentModel.md
│ │ ├── Advanced.md
│ │ ├── Lifetime_Usage.md
│ │ └── LifetimeDefinition.md
│ ├── Lifetime.md
│ ├── TextControl.md
│ ├── Platform_Zones.md
│ └── Shell
│ │ └── ToolWindows.md
├── _CODE_OF_CONDUCT.md
├── basics
│ ├── basics.md
│ ├── getting_started
│ │ ├── debugging_plugin.md
│ │ └── running_plugin.md
│ ├── getting_started.md
│ ├── types_of_plugins.md
│ └── plugin_required_experience.md
├── HowTo
│ ├── NavigateCode
│ │ ├── NavigateToParticularTreeNode.md
│ │ ├── UseManualNavigation.md
│ │ ├── AddYourNavigationActionToNavigateToMenu.md
│ │ └── GetTreeNodeByReference.md
│ ├── HowTo_HowTo.md
│ ├── RunActionsFromCode.md
│ ├── WorkWithColorThemes.md
│ ├── WorkWithSignals.md
│ ├── CreateMenuItemsUsingActions.md
│ ├── CreateQuickFix
│ │ └── CreateQuickFix.md
│ ├── ObtainComponentsInRuntime.md
│ ├── CreateContextAction
│ │ └── CreateContextAction.md
│ └── WorkWithLifetime.md
├── PSI
│ ├── References
│ │ ├── CodeCompletion.md
│ │ └── IReferenceProvider.md
│ ├── NavigatingSyntaxTrees.md
│ ├── Reference
│ │ └── Xml
│ │ │ └── Navigators.md
│ ├── DeclaredElements.md
│ ├── TypeSystems2.md
│ ├── Caching.md
│ ├── References.md
│ ├── SyntaxTrees.md
│ ├── SyntaxTrees
│ │ └── ManualNavigation.md
│ ├── Generating
│ │ └── Code.md
│ └── PSI_Overview.md
├── Intro
│ ├── content_updates.md
│ ├── welcome.md
│ ├── getting_help.md
│ ├── key_topics.md
│ ├── about.md
│ └── ReSharperPlatform.md
├── _CONTRIBUTING.md
├── Features
│ ├── QuickDoc
│ │ ├── QuickDoc_Overview.md
│ │ ├── ImplementingPresenter.md
│ │ └── ImplementingProvider.md
│ ├── LiveTemplates.md
│ ├── Analysis.md
│ └── Refactoring.md
├── CustomLanguages
│ ├── Parsing
│ │ ├── Parsing_Lexing.md
│ │ ├── Lexing
│ │ │ ├── LexerFactories.md
│ │ │ ├── LexerUtil.md
│ │ │ ├── CachingLexers.md
│ │ │ └── Lexing_Testing.md
│ │ ├── NodeTypes.md
│ │ ├── Parsing.md
│ │ └── NodeTypes
│ │ │ └── CompositeNodeTypes.md
│ ├── InjectedPsi.md
│ ├── Registration.md
│ ├── HtmlLike.md
│ ├── HtmlLike
│ │ └── ExtendingHtml.md
│ └── Registration
│ │ ├── PsiLanguageDefinition.md
│ │ ├── Registration_PerLanguageComponents.md
│ │ └── Registration_Testing.md
├── _README.md
├── testing
│ ├── TemporarySettings.md
│ ├── TestComponents.md
│ └── TestEnvironment.md
├── Products
│ └── InspectCode.md
└── appendix
│ └── open-source-plugins.md
├── codeSnippets
└── info
├── cfg
├── build-script.xml
├── platforms.xml
└── buildprofiles.xml
├── v.list
├── project.ihp
├── CONTRIBUTING.md
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea
2 |
--------------------------------------------------------------------------------
/images/info:
--------------------------------------------------------------------------------
1 | Store your images here
--------------------------------------------------------------------------------
/topics/info:
--------------------------------------------------------------------------------
1 | Store your code snippets here
--------------------------------------------------------------------------------
/codeSnippets/info:
--------------------------------------------------------------------------------
1 | Store your topics here. Their filenames must be unique.
--------------------------------------------------------------------------------
/topics/Platform/Zones/Licensing.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Licensing)
2 |
3 | **TODO** TBD
4 |
--------------------------------------------------------------------------------
/images/Features/img/nguid_macro.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/img/nguid_macro.png
--------------------------------------------------------------------------------
/images/Features/img/template_editor.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/img/template_editor.png
--------------------------------------------------------------------------------
/images/Features/Actions/img/rich_text.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/Actions/img/rich_text.png
--------------------------------------------------------------------------------
/images/basics/img/run-configurations.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/basics/img/run-configurations.png
--------------------------------------------------------------------------------
/images/Features/Actions/img/fix_in_scope.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/Actions/img/fix_in_scope.png
--------------------------------------------------------------------------------
/images/Features/img/Features_navigation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/img/Features_navigation.png
--------------------------------------------------------------------------------
/images/PSI/References/img/mvc_ctrl_click.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/PSI/References/img/mvc_ctrl_click.png
--------------------------------------------------------------------------------
/images/PSI/img/iexpressiontype_hierarchy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/PSI/img/iexpressiontype_hierarchy.png
--------------------------------------------------------------------------------
/images/Features/Actions/img/context_action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/Actions/img/context_action.png
--------------------------------------------------------------------------------
/images/Features__Code_Inspections__Sample.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features__Code_Inspections__Sample.png
--------------------------------------------------------------------------------
/images/HowTo/AnalyzeCode/img/analyze-code.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/AnalyzeCode/img/analyze-code.png
--------------------------------------------------------------------------------
/images/HowTo/CreateContextAction/img/hummer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/CreateContextAction/img/hummer.png
--------------------------------------------------------------------------------
/images/HowTo/NavigateCode/img/psi-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/NavigateCode/img/psi-example.png
--------------------------------------------------------------------------------
/images/PSI/img/ideclaredelement_hierarchy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/PSI/img/ideclaredelement_hierarchy.png
--------------------------------------------------------------------------------
/images/Platform/Zones/img/options_features.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Platform/Zones/img/options_features.png
--------------------------------------------------------------------------------
/images/Platform__Icons__Themed_Icon_Viewer.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Platform__Icons__Themed_Icon_Viewer.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/images/main-sprite.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/images/main-sprite.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/jetbrains.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/jetbrains.png
--------------------------------------------------------------------------------
/images/Features/Tools/img/code_cleanup_dialog.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Features/Tools/img/code_cleanup_dialog.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/images/main-sprite@2x.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/images/main-sprite@2x.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/mstile-70x70.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/mstile-70x70.png
--------------------------------------------------------------------------------
/images/HowTo/CreateQuickFix/img/create-quick-fix.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/CreateQuickFix/img/create-quick-fix.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/actions.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/actions.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/daemons.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/daemons.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/options.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/mstile-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/mstile-144x144.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/mstile-150x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/mstile-150x150.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/mstile-310x150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/mstile-310x150.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/mstile-310x310.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/mstile-310x310.png
--------------------------------------------------------------------------------
/images/HowTo/CreateContextAction/img/context-action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/CreateContextAction/img/context-action.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/code-cleanup.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/code-cleanup.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/generate-menu.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/generate-menu.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/quick-fixes.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/quick-fixes.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/refactorings.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/refactorings.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/tool-windows.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/tool-windows.png
--------------------------------------------------------------------------------
/images/HowTo/NavigateCode/img/add-navigate-to-action.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/NavigateCode/img/add-navigate-to-action.png
--------------------------------------------------------------------------------
/images/HowTo/NavigateCode/img/project-model-example.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/NavigateCode/img/project-model-example.png
--------------------------------------------------------------------------------
/images/Platform/VisualStudio/img/relocate_to_per_user.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Platform/VisualStudio/img/relocate_to_per_user.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/rakelib/build_pdf/kotlin-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/rakelib/build_pdf/kotlin-logo.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/code-completion.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/code-completion.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/live-templates.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/live-templates.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-57x57.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-57x57.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-60x60.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-60x60.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-72x72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-72x72.png
--------------------------------------------------------------------------------
/images/Platform/VisualStudio/img/relocate_to_custom_hive.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/Platform/VisualStudio/img/relocate_to_custom_hive.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-114x114.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-114x114.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-120x120.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-120x120.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-144x144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-144x144.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-152x152.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-152x152.png
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-touch-icon-180x180.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/sdkdocs-template/webhelp/apple-touch-icon-180x180.png
--------------------------------------------------------------------------------
/images/HowTo/AddSettingsToOptions/img/setting-resharper-options.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/AddSettingsToOptions/img/setting-resharper-options.png
--------------------------------------------------------------------------------
/images/HowTo/IntegrateWithReSharper/img/IntegrateWithReSharper_navigation.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JetBrains/resharper-devguide/HEAD/images/HowTo/IntegrateWithReSharper/img/IntegrateWithReSharper_navigation.png
--------------------------------------------------------------------------------
/cfg/build-script.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/topics/Platform/Zones/Zones_Troubleshooting.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Troubleshooting)
2 |
3 | **TODO** TBD
4 |
5 | ## Inspections
6 |
7 | ReSharper ships with several inspections to help ensure correct zone registration.
8 |
9 | * `RedundantDependencyChecker` will highlight a class that
10 |
11 | Also, `MarkersCompletionProvider` will remove any zone definitions from `IRequireZone` that aren't valid. Or something
12 |
13 | ## Diagrams
14 |
--------------------------------------------------------------------------------
/topics/_CODE_OF_CONDUCT.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Code of Conduct)
2 |
3 |
4 |
5 | This project and the corresponding community is governed by the [JetBrains Open Source and Community Code of Conduct](https://confluence.jetbrains.com/display/ALL/JetBrains+Open+Source+and+Community+Code+of+Conduct). Please make sure you read it.
6 |
--------------------------------------------------------------------------------
/topics/basics/basics.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Quick Start Guide)
2 |
3 |
4 |
5 | This section covers the basics of working with the ReSharper Platform.
6 | It will familiarize you with the working environment, project structure, and frequently used API components.
7 |
8 | * [](plugin_alternatives.md)
9 | * [](plugin_required_experience.md)
10 | * [](types_of_plugins.md)
11 |
--------------------------------------------------------------------------------
/v.list:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/project.ihp:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
12 |
13 |
--------------------------------------------------------------------------------
/topics/basics/getting_started/debugging_plugin.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Creating A Plugin)
2 |
3 |
4 |
5 | Depending on your environment (Windows or Unix) and product of choice (ReSharper or Rider), you can debug your plugin through different approaches.
6 |
7 | | Product | Process to Debug |
8 | |-----------|---------------------|
9 | | Rider | `Rider.Backend.exe` |
10 | | ReSharper | `devenv.exe` |
11 |
--------------------------------------------------------------------------------
/cfg/platforms.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | +
5 |
6 | keymap-%currentId%.xml
7 | ctrl:Ctrl;control:Ctrl;alt:Alt;shift:Shift;command:⌘;meta:⌘
8 | \
9 |
10 |
11 | +
12 |
13 | keymap-%currentId%.xml
14 | ctrl:^;control:Control;alt:⌥;shift:⇧;command:⌘;meta:⌘
15 | /
16 |
17 |
--------------------------------------------------------------------------------
/images/sdkdocs-template/webhelp/apple-mask-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/topics/HowTo/NavigateCode/NavigateToParticularTreeNode.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Navigate to a Particular Tree Node)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 |
6 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
7 | * [NodeUnderCaretDetector.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/NodeUnderCaretDetector.cs)
8 |
9 | In case you have already obtained your navigation target, e.g., an `ITreeNode` instance, you can use its `NavigateToTreeNode()` method to navigate to it:
10 |
11 | ```csharp
12 | ITreeNode node = ... ;
13 | node.NavigateToTreeNode(true);
14 | ```
15 |
16 | Other PSI syntax tree classes may also provide methods for navigation, e.g. `IDeclaredElement`:
17 |
18 | ```csharp
19 | IDeclaredElement element = ... ;
20 | element.Navigate(true);
21 | ```
22 |
--------------------------------------------------------------------------------
/topics/Platform/Lifetime/Lifetime_ComponentModel.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Component Lifetime)
2 |
3 | The simplest way to get a `Lifetime` instance is to let the Component Model inject it into your constructor:
4 |
5 | ```csharp
6 | [ShellComponent]
7 | public class MyComponent
8 | {
9 | public MyComponent(Lifetime lifetime)
10 | {
11 | // ...
12 | }
13 | }
14 | ```
15 |
16 | The Component Model will create a new `Lifetime` instance for each component, and is responsible for terminating it. The `Lifetime` is terminated when the appropriate component container is disposed.
17 |
18 | For example, the `Lifetime` for a component decorated with `[ShellComponent]` is terminated when the shell itself is terminated, normally when Visual Studio closes. A component decorated with `[SolutionComponent]` will have its `Lifetime` terminated when the currently open solution closes.
19 |
--------------------------------------------------------------------------------
/topics/PSI/References/CodeCompletion.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Code Completion)
2 |
3 | Code completion is handled by ReSharper, as long as the reference also implements the `ICompleteableReference` interface. This interface inherits from `IReference` and defines just one method:
4 |
5 | ```csharp
6 | public interface ICompleteableReference : IReference
7 | {
8 | ISymbolTable GetCompletionSymbolTable();
9 | }
10 | ```
11 |
12 | This method should return a symbol table of candidates. Each candidate will be added to the code completion list. The implementation for this is usually very straightforward:
13 |
14 | ```csharp
15 | public ISymbolTable GetCompletionSymbolTable()
16 | {
17 | return GetReferenceSymbolTable(false);
18 | }
19 | ```
20 |
21 | We simply return the symbol table from `IReference.GetReferenceSymbolTable` by passing `false` for `useReferenceName`. This is already our list of candidates, so we don't need to do any further processing.
22 |
--------------------------------------------------------------------------------
/topics/Intro/content_updates.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Content Updates)
2 |
3 |
4 |
5 | See [GitHub Changelog](https://github.com/JetBrains/resharper-devguide/commits/master) ([RSS](https://github.com/JetBrains/resharper-devguide/commits/master.atom)) for a detailed changelog.
6 |
7 | > [Subscribe to Marketplace Developer News](https://jb.gg/mp-updates) to receive news and announcements.
8 | >
9 | {type="tip"}
10 |
11 | ## 2023
12 |
13 | ### March 2023
14 |
15 | Additions
16 | :
17 | - Add [](Features__Code_Inspections.md) section.
18 | - Add [](Platform__Icons.md) section.
19 |
20 | ## 2022
21 |
22 | ### September 2022
23 |
24 | Additions
25 | :
26 | - Add [](creating_plugin.md) section.
27 | - Add [](running_plugin.md) section.
28 | - Add [](types_of_plugins.md) section.
29 | - Add [](plugin_required_experience.md) section.
30 | - Add [](plugin_alternatives.md) section.
31 |
--------------------------------------------------------------------------------
/topics/_CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Contributing to the ReSharper Platform SDK)
2 |
3 |
4 |
5 | This document describes our contribution guidelines for the open-source ReSharper Platform SDK documentation and sample code. Before you begin contributing content to the SDK, please read this page thoroughly as well as the [Code of Conduct](_CODE_OF_CONDUCT.md) and [License](https://github.com/JetBrains/resharper-devguide/blob/master/LICENSE.txt) documents.
6 |
7 | ## Creating ReSharper Platform SDK Content
8 |
9 | Content contributions to the ReSharper Platform SDK are welcome.
10 |
11 | Please download or clone the open-source SDK project from [GitHub](https://github.com/JetBrains/resharper-devguide), make additions or changes, and submit a pull request.
12 |
13 | > Currently, building the site locally is not possible.
14 | >
15 | {type="note"}
16 |
--------------------------------------------------------------------------------
/cfg/buildprofiles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | true
5 | https://www.jetbrains.com/help
6 |
7 | jetbrains
8 | true
9 | true
10 | true
11 | true
12 | https://forms-service.jetbrains.com/feedback
13 | webmaster@jetbrains.com
14 | true
15 | https://www.jetbrains.com/search/json/
16 | false
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/topics/basics/getting_started.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Developing A Plugin)
2 |
3 |
4 |
5 | This documentation section will help you get started with developing ReSharper Platform plugins.
6 | You can use either [JetBrains Rider](https://www.jetbrains.com/rider/download) or [Microsoft Visual Studio](https://visualstudio.microsoft.com/downloads/) (with or without [ReSharper](https://www.jetbrains.com/resharper/download/)) as your IDE (it is highly recommended to use the latest available version).
7 | Please refer to the [Rider Web Help](https://www.jetbrains.com/help/rider) or [ReSharper Web Help](https://www.jetbrains.com/help/resharper) to become more familiar with the products.
8 |
9 | * [](creating_plugin.md)
10 | * [](running_plugin.md)
11 |
12 | > In some cases, implementing an actual ReSharper Platform plugin might not be necessary, as [alternative solutions](plugin_alternatives.md) exist.
13 | >
14 | {type="tip"}
15 |
--------------------------------------------------------------------------------
/topics/Features/QuickDoc/QuickDoc_Overview.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: QuickDoc)
2 |
3 | The QuickDoc feature displays a popup window with details of the code element at the current text caret position. What gets displayed depends on what that code element is.
4 |
5 | For example, a C# QuickDoc window will show the element name and type, with hyperlinks to navigate to any type definitions and description from XML documentation.
6 |
7 | A CSS QuickDoc window will show the expected values for the property, with hyperlinks to the definitions of the value units, and a "read more" link to see the W3C website's documentation.
8 |
9 |
10 |
11 | ReSharper ships with full support for C# and VB, compiled CLR types, JavaScript, CSS, XML and HTML out of the box, but it is possible to extend QuickDoc to provide documentation for languages or code elements not supported by default.
12 |
13 | ## Read more
14 |
15 | 1. Implement your own support, by implementing [IQuickDocProvider](ImplementingProvider.md) and [IQuickDocPresenter](ImplementingPresenter.md), using the [helper classes](HelperClasses.md)
16 | 2. [Extend the existing providers](ExistingProviders.md)
17 | 3. [Test QuickDoc providers](QuickDoc_Testing.md)
18 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/Parsing_Lexing.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Lexing)
2 |
3 | [Lexical analysis](https://en.wikipedia.org/wiki/Lexical_analysis) (or "lexing") is the process of converting a text buffer into a sequence of tokens which uniquely identify the building blocks of a custom language. For example, a lexer can convert the C# expression `age = 42;` into the following stream of tokens:
4 |
5 | ```text
6 | IDENTIFIER
7 | WHITESPACE
8 | EQUALS
9 | WHITESPACE
10 | INTEGER_LITERAL
11 | SEMI_COLON
12 | ```
13 |
14 | A parser can then analyse this stream of tokens, looking for known patterns, and build a parse tree that identifies an assignment operation, with an identifier and an constant expression.
15 |
16 | This section looks at how ReSharper expects to be able to create a lexer via a [lexer factory](LexerFactories.md), and the lexer itself must [implement the `ILexer` interface](ImplementingLexers.md), and use [text buffers](TextBuffers.md) to access the text block to analyse. This section also takes a look at how to [use the CsLex SDK tool to tokenise a custom language](CsLex.md).
17 |
18 | Finally, this section takes a look at a couple of useful features ReSharper uses while parsing - [lexer utility methods](LexerUtil.md), [filtering lexers](FilteringLexers.md), and [caching lexers](CachingLexers.md).
19 |
--------------------------------------------------------------------------------
/topics/HowTo/HowTo_HowTo.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: How To)
2 |
3 | This **How To** is a brief introduction into ReSharper plugin development. This is a set of examples each of those answers a particular question, like, _"how can I register an action?"_ or _"how can I navigate to a class?"_ We intentionally use the question-answer "stackoverflow" style, so you could quickly get an answer without going into details.
4 |
5 | The examples are very basic and do not provide any extended information about the SDK. For more details, you should refer to other chapters of this guide. In addition, it is always worth to take a look at how a particular feature is implemented in ReSharper. For this purpose, you can decompile ReSharper using dotPeek and use it as a big "reference".
6 |
7 | DISCLAIMER! Please note that all examples of this **How To** are written for ReSharper 2017.1. This means that if your ReSharper version differs from 2017.1, they might not work (ReSharper plugins are NOT backward-compatible!)
8 |
9 | ## Sample solution
10 | Note that almost each section in this chapter is preceded with a list of **Examples**. The list contains links to the examples code on github. All examples are a part of the [sample ReSharper plugin](https://github.com/JetBrains/sample-resharper-plugin). Use this plugin as a reference to this **How To**.
11 |
--------------------------------------------------------------------------------
/topics/PSI/NavigatingSyntaxTrees.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Navigating syntax trees)
2 |
3 | Every node in the syntax tree implements `ITreeNode`, as well as interfaces that better reflect the node's type and purpose, such as `IComment` or `IMethodDeclaration`. The `ITreeNode` interface includes members pertinent to navigating and processing the tree. These members are shown below (other members removed for brevity):
4 |
5 | ```csharp
6 | public interface ITreeNode
7 | {
8 | ITreeNode Parent { get; }
9 | ITreeNode FirstChild { get; }
10 | ITreeNode LastChild { get; }
11 | ITreeNode NextSibling { get; }
12 | ITreeNode PrevSibling { get; }
13 |
14 | // [...snip...]
15 | }
16 | ```
17 |
18 | There are several ways of navigating the tree.
19 |
20 | * [Manually walking the tree](ManualNavigation.md), using the interface members shown above. This is the least recommended, requiring boilerplate tree walking code that is time consuming and easy to get wrong.
21 | * Use the `TreeNodeExtensions` helper methods to manually walk the tree.
22 | * Use [strongly typed navigation](StronglyTypedNavigation.md), using accessors on derived `ITreeNode` implementations, and the strongly typed "navigator" classes.
23 | * Process the tree using the visitor pattern or the `IRecursiveElementProcessor` set of classes.
24 | * Finding child or parent nodes of a specific type.
25 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing
2 |
3 | In order to build the site locally, you will need Ruby installed (the site is based on [Jekyll](http://jekyllrb.com)). The steps to get the site built are:
4 |
5 | 1. Install Ruby
6 | 2. Install Bundler - `gem install bundler`
7 | 3. Clone this repo
8 | 4. Initialise and clone the sub-modules - `git submodule init` and `git submodule update`
9 | 5. Download dependencies (gems) - `rake bootstrap`
10 | 6. Build and preview the site with `rake preview`
11 |
12 | This starts Jekyll running the site at `http://localhost:4001/help/resharper/sdk/`
13 |
14 | ## Notes on style
15 |
16 | ### Titles
17 |
18 | * Title case for page headings, both in the page and in the `_SUMMARY.md` file.
19 | * Sentence case for sub headings in pages
20 |
21 | ### Terms
22 |
23 | The following terms are used to refer to standard well known features in the product. They are not normally capitalised, unless otherwise shown.
24 |
25 | * Alt+Enter, mono space (should wrap in `Alt+Enter`?)
26 | * Context action
27 | * Quick-fix
28 | * Code cleanup
29 | * plugin
30 |
31 | ### Code examples
32 |
33 | * Indent of 2. Be conservative with space
34 | * Long lines will scroll horizontally, so don't wrap unnecessarily. However, don't add really long lines either.
35 | * Allow blank lines for clarity
36 | * Comment if necessary, but not for everything
37 |
--------------------------------------------------------------------------------
/topics/HowTo/RunActionsFromCode.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Run Actions from Code)
2 |
3 | **What you should know beforehand:**
4 | * [Component model](ObtainComponentsInRuntime.md)
5 | * [Lifetime](WorkWithLifetime.md)
6 | * Shell locks
7 |
8 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
9 | * [RunActionCommand.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/Actions/RunActionCommand.cs)
10 |
11 | Running an action is done via the `ActionManager component`. Synchronously:
12 |
13 | ```csharp
14 | var actionManager = Shell.Instance.GetComponent();
15 | actionManager.ExecuteAction();
16 | ```
17 |
18 | Or asynchronously. In this case, you have to pass a lifetime as well (if the lifetime is terminated before the action is executed, the action is removed from the queue):
19 |
20 | ```csharp
21 | actionManager.ExecuteActionAsync(_lifetime);
22 | ```
23 |
24 | To have more options on how to execute the action (synchronously or asynchronously with various types of locks), you may decide to wrap a synchronous `ExecuteAction` call with one of the `ShellLocks` methods:
25 |
26 | ```csharp
27 | var shellLocks = Shell.Instance.GetComponent();
28 | shellLocks.ExecuteOrQueue(_lifetime, "ExecuteSampleAction", () =>
29 | {
30 | actionManager.ExecuteAction();
31 | });
32 | ```
33 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/Lexing/LexerFactories.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Lexer Factories)
2 |
3 | ReSharper requires a custom language to implement `ILexerFactory`, which is exposed via `IProjectFileLanguageService.GetMixedLexerFactory` and the `LanguageService.GetPrimaryLexerFactory` abstract method.
4 |
5 | The lexer factory is assigned to the `IFile` root node of the PSI tree, via the `IFileImpl` interface, which exposes implementation details rather than PSI tree information. This is made available so that various parts of ReSharper can easily create a fresh lexer on a new buffer.
6 |
7 | ```csharp
8 | public interface ILexerFactory
9 | {
10 | ILexer CreateLexer(IBuffer buffer);
11 | }
12 | ```
13 |
14 | This class is usually trivial to implement, simply returning a new instance of a class that implements the `ILexer` interface.
15 |
16 | > The `LanguageService.GetPrimaryLexerFactory` method should be implemented by creating a new instance of this class, and typically, the `IProjectFileLanguageService.GetMixedLexerFactory` will just call `GetPrimaryLexerFactory`.
17 | >
18 | > However, if the custom language hosts "secondary" PSI trees (such as HTML, which can also contain CSS and JavaScript), the `IProjectFileLanguageService` should inherit form `MixedProjectLanguageService`, which provides an implementation of `GetMixedLexerFactory` that returns an instance of `MixedLexerFactory` using the lexer factory returned from `GetPrimaryLexerFactory`.
19 | >
20 | {type="note"}
21 |
22 | The `IBuffer` interface is an abstraction of a text based buffer that a lexer uses to get the contents of the file (persistent or in-memory). See the guide on [Text Buffers](TextBuffers.md) for more details.
23 |
--------------------------------------------------------------------------------
/topics/basics/types_of_plugins.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Plugin Types)
2 |
3 |
4 |
5 | Products based on the ReSharper Platform can be modified and adjusted for custom purposes by adding plugins.
6 | All downloadable plugins are available from the [JetBrains Marketplace](https://plugins.jetbrains.com/).
7 |
8 | The most common types of plugins include:
9 |
10 | * Library support
11 | * Tool integration
12 | * Inspections and quick-fixes
13 | * Context Actions
14 |
15 | > In some cases, implementing an actual ReSharper Platform plugin might not be necessary, as [alternative solutions](plugin_alternatives.md) exist.
16 | >
17 | {type="tip"}
18 |
19 | ## Library Support
20 |
21 | Library support provides improved code insights, which usually cannot be expressed through the compiler and its type-system, that includes:
22 |
23 | * Code completion
24 | * Code inspections and quick-fixes
25 | * Reference providers
26 |
27 | ## Tool Integration
28 |
29 | Tool integration makes it possible to manipulate third-party tools and components directly from the IDE without switching contexts, that implies:
30 |
31 | * Implementation of additional actions
32 | * Related UI components
33 | * Access to external resources
34 |
35 | ## Custom Language Support
36 |
37 | Custom language support provides basic functionality for working with a particular programming language, that includes:
38 |
39 | * File type recognition
40 | * Lexical analysis
41 | * Syntax highlighting
42 | * Formatting
43 | * Code completion
44 | * Code inspections and quick-fixes
45 | * Context Actions
46 | * Navigation
47 |
48 | Plugins can also augment existing (bundled) custom languages, e.g., by providing additional inspections, quick-fixes, or any other features.
49 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/Lexing/LexerUtil.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Lexer Utility Methods)
2 |
3 | The `LexerUtil` class provides a number of utility and extension functions for lexing and parsing. Of particular interest are the `LookaheadToken` methods, `GetTokenLength` and `GetCurrTokenText`:
4 |
5 | ```csharp
6 | public static class LexerUtil
7 | {
8 | // Look ahead to the k'th token and return it, the roll back to the current position
9 | static public TokenNodeType LookaheadToken(this ILexer lexer, int k);
10 | static public TokenNodeType LookaheadToken(this ILexer lexer, int k);
11 | // Look ahead, but skip the given node type
12 | static public TokenNodeType LookaheadTokenSkipping(this ILexer lexer, int k, TokenNodeType nodeTypeToSkip);
13 |
14 | // Get the length of the text of the current token
15 | public static int GetTokenLength(this ILexer lexer);
16 |
17 | // Get the text of the current token, with or without quotes
18 | public static string GetCurrTokenText(this ILexer lexer);
19 | public static string GetQuotedTokenText(this ILexer lexer, char quote);
20 | public static string GetQuotedTokenText(this ILexer lexer, char openQuote, char closeQuote);
21 |
22 | // Compare the current token text against the given string. Functionally equivalent
23 | public static bool CompareTokenText(ILexer lexer, string str, bool caseSensitive = true);
24 | public static bool CompareBufferText(ILexer lexer, string str, bool caseSensitive = true);
25 |
26 | // Return a lazy enumerable of TokenNodeType by calling lexer.Advance
27 | public static IEnumerable Tokens(this ILexer lexer);
28 |
29 | // Advance lexer while the current token is the same as the skip token(s)
30 | public static int AdvanceWhile(this TLexer lexer, TokenNodeType skipToken);
31 | public static int AdvanceWhile(this TLexer lexer, NodeTypeSet skipTokens);
32 | }
33 | ```
34 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | [](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
2 |
3 | Welcome to the developer guide for the [ReSharper Platform](Intro/ReSharperPlatform.md). This is the primary source of documentation for developing extensions for the ReSharper Platform that ships as part of ReSharper.
4 |
5 | To view the guide, please visit: [https://www.jetbrains.com/help/resharper/sdk/](https://www.jetbrains.com/help/resharper/sdk/)
6 |
7 | ## Getting Started
8 |
9 | * [**The ReSharper Platform**](Intro/ReSharperPlatform.md)
10 | * [**About this Guide**](Intro/about.md)
11 | * [**Key Topics**](Intro/key_topics.md)
12 | * [**Getting Help**](Intro/getting_help.md)
13 |
14 | ## Open Source
15 |
16 | This guide is Open Source, licensed under Apache 2.0. The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/resharper-devguide). Please feel free to [raise issues](https://github.com/JetBrains/resharper-devguide/issues) or create pull requests to address incorrect or missing content. Please see the [CONTRIBUTING](CONTRIBUTING.md) page for details on how to build locally.
17 |
18 | The guide is very much a work in progress (the ReSharper Platform has a very large feature set and API surface), and is by no means a complete reference of the API. The table of contents provides a non-exhaustive list of available features, and shows missing content by greying out the page. Issues are a great way of prioritising what documentation needs to be addressed first. Please let us know what we should focus on!
19 |
20 | ## Previous versions
21 |
22 | This guide intends to target the current version of ReSharper, and does not maintain documentation for working with previous versions of the ReSharper Platform. However, large parts of the architecture and implementation are very stable, and the documentation may also apply to previous versions.
23 |
--------------------------------------------------------------------------------
/topics/_README.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: ReSharper DevGuide)
2 |
3 | [](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
4 |
5 | Welcome to the developer guide for the [ReSharper Platform](ReSharperPlatform.md). This is the primary source of documentation for developing extensions for the ReSharper Platform that ships as part of ReSharper.
6 |
7 | To view the guide, please visit: [https://www.jetbrains.com/help/resharper/sdk/](https://www.jetbrains.com/help/resharper/sdk/)
8 |
9 | ## Getting Started
10 |
11 | * [**The ReSharper Platform**](ReSharperPlatform.md)
12 | * [**About this Guide**](About.md)
13 | * [**Key Topics**](KeyTopics.md)
14 | * [**Getting Help**](getting-help.md)
15 |
16 | ## Open Source
17 |
18 | This guide is Open Source, licensed under Apache 2.0. The source (as Markdown) is [hosted on GitHub](https://github.com/JetBrains/resharper-devguide). Please feel free to [raise issues](https://github.com/JetBrains/resharper-devguide/issues) or create pull requests to address incorrect or missing content. Please see the [CONTRIBUTING]() page for details on how to build locally.
19 |
20 | The guide is very much a work in progress (the ReSharper Platform has a very large feature set and API surface), and is by no means a complete reference of the API. The table of contents provides a non-exhaustive list of available features, and shows missing content by greying out the page. Issues are a great way of prioritising what documentation needs to be addressed first. Please let us know what we should focus on!
21 |
22 | ## Previous versions
23 |
24 | This guide intends to target the current version of ReSharper, and does not maintain documentation for working with previous versions of the ReSharper Platform. However, large parts of the architecture and implementation are very stable, and the documentation may also apply to previous versions.
25 |
--------------------------------------------------------------------------------
/topics/basics/plugin_required_experience.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Required Experience)
2 |
3 |
4 |
5 | The ReSharper Platform is based on .NET, implemented mostly in [C#](https://docs.microsoft.com/en-us/dotnet/csharp/). In addition, Rider plugins run as a JVM application, mainly implemented in Java and Kotlin.
6 | At this time, it's not possible to develop plugins for the ReSharper Platform in non-.NET languages.
7 | Developing a plugin for the ReSharper Platform requires knowledge and experience with the following technologies and concepts:
8 | - [.NET](https://dotnet.microsoft.com/en-us/), [C#](https://docs.microsoft.com/en-us/dotnet/csharp/), and its standard and 3rd-party libraries (ReSharper and Rider)
9 | - Java/Kotlin, and other IntelliJ-relevant technologies, as described in the [IntelliJ SDK documentation](https://plugins.jetbrains.com/docs/intellij/plugin-required-experience.html) (Rider only)
10 | - Experience with ReSharper Platform-based tools (e.g., [ReSharper](https://www.jetbrains.com/resharper/) or [Rider](https://www.jetbrains.com/rider/))
11 |
12 | Please keep in mind that the ReSharper Platform is a large project, and while we are doing our best to cover as many topics as possible, it is not possible to include every feature and use-case in the documentation.
13 | Developing a plugin will sometimes require digging into [sample projects](https://github.com/JetBrains/resharper-rider-plugin/tree/master/samples), analyzing [other open-source plugins](https://jb.gg/ipe), or [getting help](../Intro/getting-help.md) on our tracked platforms.
14 |
15 | [//]: # (TODO)
16 | [//]: # (It's highly recommended to get familiar with the [](explore_api.md) section before you start the plugin implementation.)
17 |
18 | > In some cases, implementing an actual ReSharper Platform plugin might not be necessary, as [alternative solutions](plugin_alternatives.md) exist.
19 | >
20 | {type="tip"}
21 |
--------------------------------------------------------------------------------
/topics/Platform/Lifetime.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Lifetime)
2 |
3 | The `JetBrains.DataFlow.Lifetime` class is used for cleanup code and resource management. `Lifetime` is similar to, but different from `IDisposable`. In fact, you can consider `Lifetime` to be the "dual" of `IDisposable`.
4 |
5 | > This class is used *extensively* throughout the codebase, and it is *highly recommended* that you understand what it is and how it works.
6 | >
7 | {type="note"}
8 |
9 | `IDisposable` is best suited to deterministic cleanup of a limited number of objects in a small scope. That is, it's ideal when you have created one or maybe two objects that need cleanup at a specific point in code; the `using` keyword makes this particularly easy.
10 |
11 | However, when dealing with multiple objects that require cleanup, or that live longer than a single method call, more and more code is required for housekeeping of the `IDisposable` instances, including providing the means to invoke `Dispose`. This pattern can quickly and easily spread to calling code, meaning a lot of extra code is required just to manage resources and cleanup.
12 |
13 | The `Lifetime` class reduces this boilerplate by approaching the issue from the opposite direction. It is responsible for the housekeeping of the clean up tasks. Calling code can register callbacks with the `Lifetime`, and when it's terminated, those callbacks are executed, in reverse order, performing any required cleanup. This way, the housekeeping is moved out of user code.
14 |
15 | Instead of returning an `IDisposable` object that knows how to perform cleanup, and which needs collating and disposing, a method that needs to perform cleanup will accept a `Lifetime` instance, and register a callback that performs the cleanup. Now a single instance is maintaining all of the cleanup code, and there is no resource management housekeeping code in the calling class.
16 |
17 | Furthermore, the `Lifetime` class allows for "nested" `Lifetime` instances, which can either be terminated independently, or when parent `Lifetime` terminates.
18 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/InjectedPsi.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Injected PSI)
2 |
3 | ReSharper 7 introduces a new lightweight mechanism for ‘slicing’ a single physical code file into multiple PSI files corresponding to the languages that are used within that file. This mechanism is called _Injected PSI_. An example of an injected PSI file is a JSON file in a property of an HTML control in a JavaScript Metro app. Since the injected PSI mechanism is still being introduced, other pertinent areas (e.g., JS and CSS in HTML) currently do not use this mechanism.
4 |
5 | ## PSI Types
6 |
7 | As it stands, there are two types of PSI files available right now:
8 |
9 | * Non-injected PSI files - these are primary PSI files and PSI files implemented by the old mechanisms. One language may only have one non-injected PSI file. All C# and VB files are currently non-injected.
10 | * Injected PSI files - these are PSI files for additional languages, implemented by a brand-new mechanism. At the moment, this mechanism is only used in JSON within HTML in JS Metro apps. In future, this mechanism will handle CSS and JS within HTML and would be also used for new features.
11 |
12 | Consequently, API calls to `GetPsiFile()` need to be replaced by corresponding calls that have the extra range parameters. Typically, acquisition of a PSI file requires an additional parameter containing a `DocumentOffset/DocumentRange`. (Alternatively, one can iterate all PSI files, but this may come with a performance cost.) For example:
13 |
14 | ```csharp
15 | var range = new DocumentRange(textControl.Document, textControl.Caret.Offset());
16 | var htmlFile = (IHtmlFile)projectFile.GetPsiFile(range);
17 | ```
18 |
19 | Alternatively, for primary PSI files you can replace these calls to `GetNonInjectedPsiFile()` (this method is contained in the `PsiManagerExtensions` class). You can also use this method for all C# and VB files, even for C# and VB in ASP.NET and Razor, although this is not recommended. For example:
20 |
21 | ```csharp
22 | var file = process.SourceFile.GetNonInjectedPsiFile();
23 | ```
24 |
--------------------------------------------------------------------------------
/topics/PSI/Reference/Xml/Navigators.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Navigators)
2 |
3 |
4 |
5 |
6 |
7 | ## X
8 |
9 | ### XmlAttributeNavigator
10 |
11 |
12 |
13 | ```csharp
14 | public static class XmlAttributeNavigator
15 | {
16 | public static IXmlAttribute GetByAttributeValue(IXmlAttributeValue attributeValue);
17 | }
18 | ```
19 |
20 | * See also: [IXmlAttribute](TreeNodes.md#ixmlattribute), [IXmlAttributeValue](TreeNodes.md#ixmlattributevalue)
21 |
22 |
23 |
24 | Navigate up the tree to an instance of `IXmlAttribute`, given an `IXmlAttributeValue`. Returns `null` if it can't find the `IXmlAttribute`.
25 |
26 | ### XmlTagContainerNavigator
27 |
28 |
29 |
30 | ```csharp
31 | public static class XmlTagContainerNavigator
32 | {
33 | public static IXmlTagContainer GetByTag(IXmlTag tag);
34 | }
35 | ```
36 |
37 | * See also: [IXmlTag](TreeNodes.md#ixmltag), [IXmlTagContainer](TreeNodes.md#ixmltagcontainer)
38 |
39 |
40 |
41 | Navigate up the tree to an instance of `IXmlTagContainerNavigator` given an `IXmlTag`. Returns `null` if it can't find the `IXmlTagContainer`.
42 |
43 | ### XmlTagNavigator
44 |
45 |
46 |
47 | ```csharp
48 | public static class XmlTagNavigator
49 | {
50 | public static IXmlTag GetByAttribute(IXmlAttribute attribute);
51 | public static IXmlTag GetByTag(IXmlTag tag);
52 | public static IXmlTag GetByTagFooter(IXmlTagFooter footer);
53 | public static IXmlTag GetByTagHeader(IXmlTagHeader header);
54 | }
55 | ```
56 |
57 | * See also: [IXmlAttribute](TreeNodes.md#ixmlattribute), [IXmlTag](TreeNodes.md#ixmltag), [IXmlTagFooter](TreeNodes.md#ixmltagfooter), [IXmlTagHeader](TreeNodes.md#ixmltagheader)
58 |
59 |
60 |
61 | Navigate up the tree to an instance of `IXmlTag`, given an instance of `IXmlAttribute`, `IXmlTag`, `IXmlTagFooter` or `IXmlTagHeader`. Returns `null` if it can't find the `IXmlTag`.
62 |
--------------------------------------------------------------------------------
/topics/Platform/Zones/Implementation.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Implementation)
2 |
3 | When the application first starts up, the Component Model creates a collection of all of the types in the application that are marked with an attribute deriving from `PartAttribute` (known as "parts"). The shell and solution containers are created by filtering this collection based on the type of the part attribute, i.e. `[ShellComponent]` or `[SolutionComponent]`. Zones are implemented by a similar filter.
4 |
5 | This filter is given a list of available zones for the application, based on installed products, the host environment and user preferences (e.g. whether the zone has been disabled). When evaluating a component, the filter will look to see what zones it belongs to. If all of that component's zones are available, it is allowed through the filter. If any zones are not available, the component is filtered out, and does not get loaded by the application.
6 |
7 | For example, if one of the initial active zones when the application starts is `IProjectModelZone`, then any component marked as belonging to that zone will be loaded. In contrast, if a component is marked with both `IProjectModelZone` and `IUnitTestingZone`, the component will not be loaded, because the `IUnitTestingZone` zone definition isn't a currently active zone. This allows features to be shipped and installed, but not available.
8 |
9 | Similarly, zones can be licensed, so a zone may be installed, but unavailable due to an expired (or trial) license.
10 |
11 | Furthermore, zones are hierarchical, and can have dependencies. For example, the "ILanguageCSharpZone" depends on the "IClrPsiLanguageZone" and all of its dependencies:
12 |
13 | ```csharp
14 | ILanguageCSharpZone
15 | - IClrPsiLanguageZone
16 | - IPsiAssemblyFileLoaderImplZone
17 | - IPsiLanguageZone
18 | - PsiFeaturesImplZone
19 | - ITextControlsZone
20 | - IProjectModelZone
21 | - IDocumentModelZone
22 | ```
23 |
24 | When code is marked as belonging to the "ILanguageCSharpZone", it is automatically marked as also belonging to all of that zone's dependencies. All of these zones must be active before any of these components are added to the Component Model.
25 |
--------------------------------------------------------------------------------
/topics/Features/LiveTemplates.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Live Templates)
2 |
3 | ReSharper's Live Templates provide dynamic text expansion. While in the text editor, if you type a Live Template shortcut, or select it from a Code Completion list, the template will be expanded to a code snippet, with editable and linked "hotspots".
4 |
5 | Hotspots are like fields within the code snippet. You can tab between editable hotspots, and type over the suggested value. Any linked hotspots will update as you type. One of the advantages Live Templates have over the similar Visual Studio snippets feature is that an editable hotspot can contain a **macro** that can execute .NET code, such as to display code completion lists, or transform the value you've typed.
6 |
7 | For example, ReSharper includes macros that invoke Basic, Smart or Type completion, display code completion lists for a comma separated list, provide suggestions for variable names, the name of the current file, namespace or class, and so on. It can also provide more interesting, dynamic usages, for example, the "nguid" template defines a single hotspot that is set up to use the "New GUID" macro. When invoked, the template expands and evaluates the hotspot, which causes the new GUID macro to create a new GUID and provide a completion list with various different string representations of the GUID. Similarly, a macro could take the value typed by the user and convert it, perhaps making it all uppercase, or all lowercase, or so on.
8 |
9 | 
10 |
11 | Macros are easily added to the Live Template itself - simply create a variable in the text using the form `$value$`. The variable can be editable or not, and can be associated with a macro by clicking the link in the editor and choosing the macro from the list. Some items in the list are displayed with some or all of the text displayed in bold. These macros can be parameterised as part of the template definition, such as by providing a list of items to complete, the format to use for a string value, an associated type name and so on. The value is entered in the template editor.
12 |
13 | 
14 |
--------------------------------------------------------------------------------
/topics/Intro/welcome.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: ReSharper Platform SDK)
2 |
3 |
4 |
5 | [](https://confluence.jetbrains.com/display/ALL/JetBrains+on+GitHub)
6 | [](https://plugins.jetbrains.com/slack)
7 | [](https://twitter.com/resharper/)
8 | [](https://twitter.com/JetBrainsRider/)
9 |
10 | Welcome to the ReSharper Platform SDK - the primary source of documentation for extending .NET related products including ReSharper and JetBrains Rider.
11 |
12 |
51 |
52 | Please see [Getting Help](getting_help.md) if you encounter bugs in this guide or require help with missing content.
53 |
54 | ## Contribute
55 |
56 | This guide is Open Source and licensed under Apache 2.0.
57 | [Contributions](_CONTRIBUTING.md) are very welcome.
58 |
--------------------------------------------------------------------------------
/topics/HowTo/WorkWithColorThemes.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Work with Color Themes)
2 |
3 | **What you should know beforehand:**
4 | * [Lifetime](WorkWithLifetime.md)
5 | * [IProperty](WorkWithIProperty.md)
6 |
7 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
8 | * [UiThemeViewModel.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/UiThemes/Ui/UiThemeViewModel.cs)
9 | * [UiThemeView.xaml](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/UiThemes/Ui/UiThemeView.xaml)
10 |
11 | Changing user interface colors depending on the selected theme can be automated by means of the `ColorThemeManager` component. For example, we want to change the background and foreground colors of some UI control:
12 |
13 | ```csharp
14 | public class UiThemeViewModel : AAutomation
15 | {
16 | public IProperty BackgroundColor { get; set; }
17 | public IProperty TextColor { get; set; }
18 |
19 | public UiThemeViewModel(Lifetime lifetime, IColorThemeManager colorThemeManager)
20 | {
21 | BackgroundColor = new Property(lifetime, "UiThemeViewModel.BackgroundColor") {Value = new SolidColorBrush()};
22 | TextColor = new Property(lifetime, "UiThemeViewModel.TextColor") {Value = new SolidColorBrush()};
23 |
24 | var bgColor = colorThemeManager.CreateLiveColor(lifetime, ThemeColor.ToolWindowBackground);
25 | bgColor.ForEachValue(lifetime, (lt, color) => { BackgroundColor.Value.Color = color.WpfColor; });
26 |
27 | var txtColor = colorThemeManager.CreateLiveColor(lifetime, ThemeColor.ToolWindowForeground);
28 | txtColor.ForEachValue(lifetime, (lt, color) => { TextColor.Value.Color = color.WpfColor; });
29 | }
30 | }
31 | ```
32 |
33 | ## Notes
34 | * The `CreateLiveColor` method of `ColorThemeManager` returns `IProperty` that is bound to the value of a particular `ThemeColor`.
35 | * The `ForEachValue` method of `IProperty` allows assigning the updated color each time it is changed. The main difference in comparison with the `Advise` method is that `ForEachValue` passes a per-value lifetime (`lt`). It is terminated each time a new value is assigned to the property and allows defining a pair of actions (after-value-comes - before-value-goes) for each new value.
36 |
--------------------------------------------------------------------------------
/topics/basics/getting_started/running_plugin.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Running A Plugin)
2 |
3 |
4 |
5 | A plugin generated from the template can be run through one of the [Run/debug configurations](https://www.jetbrains.com/help/rider/Run_Debug_Configuration.html) or from the command-line on Windows, macOS, and Linux.
6 |
7 | > The included Gradle and PowerShell scripts take care of installing all necessary dependencies, including Gradle Wrappers, Amazon Corretto OpenJDK, and installers for experimental instances of ReSharper and Rider.
8 | >
9 | {type="tip"}
10 |
11 | ## From Run Configurations
12 |
13 | The included [run configurations](https://www.jetbrains.com/help/rider/Run_Debug_Configuration.html) are shortcuts for the aforementioned command-line invocations. Choose one of the following configurations in Rider and click Run or Debug:
14 |
15 | * `Rider (Unix)` – Launches Rider on Unix-systems (macOS/Linux). Automatically compiles the frontend part using IntelliJ SDK.
16 | * `Rider (Windows)` – Launches Rider on Windows. Automatically compiles the frontend part using IntelliJ SDK.
17 | * `VisualStudio` – Launches Visual Studio with ReSharper.
18 |
19 | 
20 |
21 | If your plugin has a frontend part, you will see a `Rider` configuration in IntelliJ IDEA as well that works cross-platform.
22 |
23 | ## From Command-Line
24 |
25 | From the root directory, you can run your plugin inside ReSharper and Rider from the command-line:
26 |
27 |
28 |
29 |
30 |
31 | To launch Rider on Windows, you can run the `gradlew.bat` script as follows:
32 |
33 | ```bash
34 | .\gradlew.bat :runIde
35 | ```
36 |
37 | To launch Rider on macOS or Linux, you can run the `gradlew` script as follows:
38 |
39 | ```bash
40 | ./gradlew :runIde
41 | ```
42 |
43 |
44 |
45 |
46 |
47 | To launch ReSharper in an experimental Visual Studio instance, you can run the `runVisualStudio.ps1` script:
48 |
49 | ```bash
50 | .\runVisualStudio.ps1
51 | ```
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/topics/HowTo/WorkWithSignals.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Work with Signals)
2 |
3 | **What you should know beforehand:**
4 | * [Lifetime](WorkWithLifetime.md)
5 |
6 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
7 | * [SignalEmitter.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/Signals/SignalEmitter.cs)
8 | * [SignalListener.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/Signals/SignalListener.cs)
9 | * [SolutionStateTracker.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/SolutionStateTracker/SolutionStateTracker.cs) - more complex example of using signals
10 |
11 | Signal is a way for a class to provide notifications. Signals are very similar to C# events, nevertheless, there are differences that make them more suitable for use within ReSharper data flow infrastructure.
12 |
13 | ```csharp
14 | public class SignalEmitter
15 | {
16 | public ISignal SomethingHappened { get; }
17 |
18 | public SignalEmitter(Lifetime lifetime)
19 | {
20 | SomethingHappened = new Signal(lifetime, "SignalEmitter.SomethingHappened");
21 | }
22 |
23 | public void MakeItHappen(bool arg)
24 | {
25 | SomethingHappened.Fire(arg);
26 | }
27 |
28 | }
29 |
30 |
31 | public class SignalListener
32 | {
33 | public SignalListener(Lifetime lifetime, SignalEmitter signalEmitter)
34 | {
35 | signalEmitter.SomethingHappened.Advise(lifetime, arg => MessageBox.ShowInfo($"Something happened and it's {arg}"));
36 | }
37 | }
38 | ```
39 |
40 | ## Notes
41 | * Signals must implement the `ISignal` interface.
42 | * To "subscribe" a handler to a signal, use the `Advise` method. A signal allows any number of listeners.
43 | * Unlike C# events, you should not care about "unsubscribing" from a signal to prevent memory leak. When you "subscribe" to a signal via `Advise`, you also pass a lifetime. Once the lifetime is terminated, ReSharper will take care about "unsubscribing" by itself.
44 | * To fire the signal, use the `Fire` method.
45 | * Signals have much in common with [IProperty](WorkWithIProperty.md).
46 | * Signals are perfectly suited for MVC concept when an event should be fired by a view.
47 | * In simple cases, when you need a signal only for notification purposes (with no payload), you can use the `ISimpleSignal` interface.
48 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/NodeTypes.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Node Types)
2 |
3 | Each node in a given PSI tree implements `ITreeNode`, which has a property called `NodeType` that identifies the type of the node. The value is a singleton instance that derives from the abstract base class `NodeType`. Leaf elements in the tree have a node type that further derives from the `TokenNodeType` abstract base class, while interior tree elements derive from `CompositeNodeType`.
4 |
5 | The `NodeType` class is the abstract base class for all node types:
6 |
7 | ```csharp
8 | public abstract class NodeType
9 | {
10 | private readonly string myString;
11 | private readonly int myIndex;
12 | protected NodeType myBaseNodeType;
13 |
14 | // "index" must be the unique identifier of the NodeType inside language
15 | protected NodeType(string s, int index)
16 | {
17 | myString = s;
18 | myIndex = index;
19 | }
20 |
21 | public NodeType BaseNodeType
22 | {
23 | get { return myBaseNodeType; }
24 | }
25 |
26 | internal int Index
27 | {
28 | get { return myIndex; }
29 | }
30 |
31 | public override string ToString() { return myString; }
32 | }
33 | ```
34 |
35 | The `Index` property is an integer that uniquely identifies the node type within the language. It is used by the language's implementation of `ILanguageCacheProvider`, to allow caching and retrieving a node type, and identifying it by the index.
36 |
37 | The string value passed to the constructor is only used for diagnostic purposes and testing. The value can be anything, but should be unique enough to identify the node type. For example, given a node type that has a static representation, such as the `&&` operator or the `return` keyword, C# uses `ANDAND` and `RETURN_KEYWORD`. For nodes types that don't have a static representation, such as identifiers, C# doesn't use the changeable representation, but will use a static value such as `IDENTIFIER` or `NEW_LINE`, etc.
38 |
39 | The `BaseNodeType` property is rarely used, but allows one node type to be treated like another node type. It's only used in JavaScript's WinRT support, where a WinRT expression can be treated either as a WinRT expression, or a plain JavaScript expression. For the majority of uses, it can be ignored.
40 |
41 | See the sections on [Token Node Types](TokenNodeTypes.md), [Composite Node Types](CompositeNodeTypes.md) and [Creating Node Types](CreatingNodeTypes.md).
42 |
--------------------------------------------------------------------------------
/topics/Intro/getting_help.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Getting Help)
2 |
3 | ## Problems with the guide
4 |
5 | If you’re having problems with the guide itself, such as missing, incorrect, or confusing content, please [raise an issue on GitHub](https://github.com/JetBrains/resharper-devguide/issues).
6 | If the problem is easily solved, you can also submit a [Pull Request](_CONTRIBUTING.md).
7 |
8 | If you want to report (smaller) issues for a _specific_ page, you can also use Was this page helpful feedback form on the bottom of each page by providing more details after clicking the No button. Please try to be as specific as possible and provide your e-mail address for further questions and getting notified of updates.
9 |
10 | If you just want to share feedback on the guide, again, [raise an issue](https://github.com/JetBrains/resharper-devguide/issues), even if it’s for a discussion, ideas on improvements or suggestions.
11 |
12 | > Please don't use the **RSRP** or **RIDER** YouTrack project for plugin requests - it's intended for the products itself, and you'll get a better response using one of the methods below.
13 | >
14 | {type="note"}
15 |
16 | ## Problems with Code
17 |
18 | For problems related to code, rather than the content of the guide, you have several options:
19 |
20 | * **[JetBrains Platform Slack](https://plugins.jetbrains.com/slack/)** – The **#resharper-platform** channel is a great place to ask questions, with answers coming from both JetBrains team members and members of the community.
21 | * **[StackOverflow](http://stackoverflow.com)** – We monitor the [`resharper`](http://stackoverflow.com/questions/tagged/resharper), [`resharper-plugins`](http://stackoverflow.com/questions/tagged/resharper-plugins) and [`resharper-sdk`](http://stackoverflow.com/questions/tagged/resharper-sdk) tags. Make sure to tag the question, or it won't get seen!
22 | * **[Email support](mailto:resharper-plugins@jetbrains.com)** – You can contact us directly, although we would prefer one of the options above, if possible, as the answers are shared with the community.
23 |
24 | Of course, all issues will be used to try and improve this guide.
25 |
26 | ## Problems with Products
27 |
28 | If you have a problem with a ReSharper Platform-based product, such as ReSharper or JetBrains Rider, please raise an issue on [YouTrack](https://youtrack.jetbrains.com), assigning it to the correct project for the product.
29 |
--------------------------------------------------------------------------------
/topics/HowTo/CreateMenuItemsUsingActions.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Create Menu Items Using Actions)
2 |
3 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
4 | * [SampleAction.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/Actions/SampleAction.cs)
5 |
6 | If you want to expose your feature in a menu or a toolbar, you should use actions. Action is a unit of work (implemented as a special class) that is associated with a particular menu or toolbar item. Note that you can assign a Visual Studio shortcut to an action. [Learn more about actions](Actions.md).
7 |
8 | Let's create a simple action that shows a message box being triggered.
9 | ```csharp
10 | public abstract class SampleAction : IExecutableAction
11 | {
12 | public bool Update(IDataContext context, ActionPresentation presentation, DelegateUpdate nextUpdate)
13 | {
14 | return true; // function result indicates whether the menu item is enabled or disabled
15 | }
16 |
17 | public void Execute(IDataContext context, DelegateExecute nextExecute)
18 | {
19 | RunAction(context, nextExecute);
20 | }
21 |
22 | protected abstract void RunAction(IDataContext context, DelegateExecute nextExecute);
23 | }
24 |
25 | [Action("ActionShowMessageBox", "Show message box", Id = 543210)]
26 | public class ActionShowMessageBox : SampleAction, IInsertLast
27 | {
28 | protected override void RunAction(IDataContext context, DelegateExecute nextExecute)
29 | {
30 | var solution = context.GetData(JetBrains.ProjectModel.DataContext.ProjectModelDataConstants.SOLUTION);
31 | MessageBox.ShowInfo(solution?.SolutionFile != null
32 | ? $"{solution.SolutionFile?.Name} solution is opened"
33 | : "No solution is opened");
34 | }
35 | }
36 | ```
37 |
38 | ## Notes
39 | * Actions must implement `IExecutableAction`.
40 | * `Update` returns `bool` value that indicates whether the menu item is enabled or disabled.
41 | * `Execute` runs the action.
42 | * Actions are marked with the special `Action` attribute, which defines action name, text that is shown in a menu and action `Id`. Note that `Id` must be unique!
43 | * Use the `IDataContext` object passed to the action to obtain any context data, e.g. [project model](NavigateCode.md#project-model-basics) data.
44 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Registration.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Registering a Custom Language)
2 |
3 | Before a custom language can be recognised and parsed by ReSharper, it must first be registered. There are several classes that need to be registered:
4 |
5 | * [Project Model file type](ProjectFileType.md)
6 | * [PSI language definition](PsiLanguageDefinition.md)
7 | * [Project Model language service](ProjectFileLanguageService.md)
8 | * [PSI language service](PsiLanguageService.md)
9 |
10 | If the custom language is the primary language of a file, the [file type needs to be registered with the Project Model](ProjectFileType.md). This registration maps file extensions to the file type, and tells ReSharper that a specific file is a "known file". This file type is also used to provide [file type specific components](Registration_PerLanguageComponents.md), such as the project file language service that can be used to retrieve the PSI implementation for that language. The file type is represented by an instance of `ProjectFileType`, specifically a subclass of `KnownProjectFileType`.
11 |
12 | A custom language can be the primary language of a file, or it can be secondary, such as C# "islands" in a `.aspx` page, or injected, for example, into a C# string literal that contains a regular expression. If the language is secondary or injected, the custom language doesn't need a project file type.
13 |
14 | [Registering a PSI language definition](PsiLanguageDefinition.md) tells the PSI about the language. Every node in the PSI abstract syntax tree returns this language type from `ITreeNode.Language`. The language type is represented by a derived instance of `PsiLanguageType`, specifically a subclass of `KnownLanguage`. The language type is also used to provide [language specific components](Registration_PerLanguageComponents.md), such as the language service that provides access to the lexer and parser.
15 |
16 | If a file doesn't have a Project Model file type, or a PSI language mapping, it will be represented by `UnknownProjectFileType` and `UnknownLanguage`, respectively.
17 |
18 | Once the file type and language definitions are registered, a [Project Model language service](ProjectFileLanguageService.md) is required to act as a bridge between the Project Model and the PSI, to allow mapping between a file extension and the project file type. Finally, a [PSI language service](PsiLanguageService.md) provides access to the lexer and parser, so that the PSI tree can be built.
19 |
--------------------------------------------------------------------------------
/topics/Features/Analysis.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Analysis)
2 |
3 | ReSharper analyses your code on-the-fly, as you type. It has several modes of analysis, but the output is always the same - a list of "highlights". ReSharper supports several types of highlights - some of them change the colour of existing text, while others draw new content onto the editor, such as wavy underlines.
4 |
5 | ReSharper supports:
6 |
7 | * **Squigglies** - error, warning and suggestion wavy underlines. Also, hints are shown as a short series of dots underlining the start of an identifier.
8 | * **Identifiers** - ReSharper can change the colour of identifiers based on their semantics, such as parameter, field or variable. It can also use a bold font, e.g. for mutable variables.
9 | * **Colour highlighting** - a solid underline underneath usages of colours in C# and CSS, indicating what colour is specified by the given constant parameters.
10 | * **Gutter icons** - ReSharper can show an icon in the selection gutter of the text editor, to indicate e.g. overridden methods or recursive method calls. These gutter icons are another form of highlight, and can include bulb items in the same way that Quick Fixes and Context Actions are displayed when the user clicks the icon, or uses Alt+Enter on that line.
11 | * **Custom highlights** - analysis can add custom highlights, with a number of different effects, such as a solid colour underline, which can indicate additional functionality. For example, ASP.NET MVC support highlights string literals as MVC actions with a solid underline, indicating it can be clicked on for navigation. Similarly, the HeapView plugin uses a solid underline to indicate code that causes memory allocations. Other effects include changing the text background, text itself, outlines, underlines and gutter icons.
12 |
13 | Typically, extensions are most interested in the "squigglies" - adding analysis to add warning or suggestion highlights to the editor. ReSharper provides several ways of doing this, such as "daemon stages" and Element Problem Analysers. These highlights can be static, or configurable. A static highlight is hard coded to be a certain severity, such as a compiler error, while configurable highlights can have their default severity changed by the user. These highlights need to be registered with ReSharper, in the form of assembly attributes.
14 |
15 | ReSharper also supports suppressing these inspections with specially formatted comments.
16 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/HtmlLike.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: HTML-Like languages)
2 |
3 | ReSharper supports HTML files, but it also supports HTML-like languages, such as Razor (`.cshtml`) or WebForms (`.aspx`) files. These files contain HTML, but also contain other elements, such as custom tags, or new syntax. Rather than force each language to reimplement HTML parsing, ReSharper provides support that a language can build on, reusing existing and augmenting the existing HTML parsing infrastructure.
4 |
5 | For example, a WebForms `.aspx` file can look like this, with custom `<%` and `%>` delimiters marking the ASP.NET specific syntax, and the `asp:` prefixed tags extending the HTML:
6 |
7 | ```html
8 | <%@ Page Title="Home Page" Langauge="C#" MasterPageFile="~/Site.Master" %>
9 |
10 |
11 |
<%: Title %>
12 |
13 |
14 |
15 |
16 |
17 | ```
18 |
19 | And a Razor `.cshtml` file uses the `@` symbol to delimit C# card that will be executed as the page runs. This C# can even contain HTML blocks.
20 |
21 | ```html
22 |
@ViewBag.Header
23 |
24 | @foreach (var person in Model.People) {
25 |
26 |
<%: person.Name %>
27 |
<%: person.Country %>
28 |
29 | }
30 |
31 | ```
32 |
33 | More languages and language features are also supported. For example, there is also support for the MVC flavour of Razor, which includes `@Model` markup. There is also support for Angular 2+ (including Angular 4) which augments standard HTML files to add tokens for Angular interpolation expressions. And there is also support for parsing HTML and HTML-like languages inside C# and JavaScript string literals.
34 |
35 | ReSharper provides the following:
36 |
37 | * Language registration - `HtmlLanguageService` to act as a base class for the [PSI Language Service](PsiLanguageDefinition.md).
38 | * [Lexing](HtmlLike_Lexing.md) - `HtmlCompoundLexer` and `HtmlCompoundIncrementalLexer` which interleaves lexing the custom parts of the language with standard HTML.
39 | * Parsing - `IWebTreeBuilder` and the `WebTreeBuilder` base class to parse the mix of custom and traditional HTML syntax. HTML-like languages use custom written parsers rather than parsers generated with `PsiGen` and `.psi` files. This also means that the PSI element types are also generated by hand - the syntax of HTML and its derived languages is small and regular enough that this is possible.
40 |
--------------------------------------------------------------------------------
/topics/Platform/Lifetime/Advanced.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Advanced Lifetime Management)
2 |
3 | Lifetime instances can be combined in very powerful ways.
4 |
5 | ## Intersection
6 |
7 | The `Lifetimes.CreateIntersection2` method creates a `LifetimeDefinition` that is the *intersection* of a number of other `Lifetime`s passed in to the method. This means it will terminate when any one of the original `Lifetime` instances terminate. Of course, a `Lifetime` can only be terminated once, so nothing will happen when subsequent `Lifetime` instances terminate. The newly created intersection `LifetimeDefinition` can also be terminated independently, and when it is terminated, it doesn't affect any of the original `Lifetime` instances.
8 |
9 | This is useful as a companion to `Lifetimes.Define`, which creates a `LifetimeDefinition` tied to a "parent" `Lifetime`. When the parent terminates, the child terminates, or the child can be terminated independently. `CreateIntersection2` creates a new `LifetimeDefinition` tied to a collection of "parent" `Lifetime` instances. When any of them terminate, the child terminates, or the child can be terminated independently.
10 |
11 | > The `CreateIntersection2` method will eventually replace the `CreateIntersection` method, which is currently marked as obsolete.
12 | >
13 | > `CreateIntersection` has the same implementation as `CreateIntersection2`, but returns a `Lifetime`, while `CreateIntersection2` returns a `LifetimeDefinition`, which gives more control over the resulting `Lifetime`.
14 | >
15 | {type="note"}
16 |
17 | ## Synchronising Multiple Lifetimes
18 |
19 | `Lifetimes.Synchronize` takes a collection of `LifetimeDefinition` and terminates them all when any one of them terminates.
20 |
21 | ## Sequential Lifetimes
22 |
23 | The `SequentialLifetimes` class simplifies using consecutive, non-overlapping `Lifetime` instances, ensuring one is terminated before the next is created.
24 |
25 | It maintains a private `LifetimeDefinition`, nested under a parent `Lifetime` provided in the constructor. When you call `Next` or `DefineNext`, the current `LifetimeDefinition` (if any) is terminated, a new one is created and stored, and the action you passed in is called, with the new `Lifetime`. (The action passed to `DefineNext` also takes the `LifetimeDefinition`). You can also terminate the current `LifetimeDefinition` explicitly by calling `TerminateCurrent`.
26 |
27 | This removes the need for boilerplate management of a single `LifetimeDefinition` that needs to be created and terminated multiple times.
28 |
--------------------------------------------------------------------------------
/topics/testing/TemporarySettings.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Temporary Settings in Tests)
2 |
3 | The ReSharper test environment will use default values for settings. If your test needs particular values in the settings, you need to set them yourself in the test, and they should be reset at the end of the test. This is important because ReSharper will try to reuse the current project and solution for future tests.
4 |
5 | The `BaseTest` class provides two methods to help with this:
6 |
7 | ```csharp
8 | public class BaseTest : BaseTestNoShell
9 | {
10 | public void ExecuteWithinSettingsTransaction( Action action);
11 | public ChangeSettingsTemporarilyCore ChangeSettingsTemporarily(Lifetime lifetime);
12 |
13 | // […snip…]
14 | }
15 | ```
16 |
17 | Normally, you would use the `ExecuteWithinSettingsTransaction` method. This takes an action that receives an instance of `IContextBoundSettingsStore`, and your code will use this settings store to temporarily change the settings. Once the action is complete, the changes to the settings are automatically undone.
18 |
19 | ```csharp
20 | [Test]
21 | public void MyTest()
22 | {
23 | ExecuteWithinSettingsTransaction(store => {
24 |
25 | // Update settings
26 | store.SetValue((CSharpLanguageProjectSettings s) => {
27 | s.LanguageLevel = CSharpLanguageLevel.CSharp50
28 | });
29 |
30 | // Do test
31 | // […snip…]
32 | });
33 | }
34 | ```
35 |
36 | ## Advanced Usage
37 |
38 | The `ChangeSettingsTemporarily` method does all of the work. It creates an instance of `ChangeSettingsTemporarilyCore` using the `Lifetime` you pass in. It creates a new in-memory settings layer with a very high priority, which means it overrides all other layers (project, solution, global), and any writes against the settings store will go to this temporary layer. The layer is created with the given `Lifetime` instance, and when the `Lifetime` terminates, the layer is automatically removed and cleaned up. Should you need it, you can get access to the layer's storage from the returned instance of `ChangeSettingsTemporarilyCore`.
39 |
40 | The `ExecuteWithinSettingsTransaction` method makes this an easier API to consume. It creates a new `Lifetime` instance, calls `ChangeSettingsTemporarily` and then gets a bound settings store accessor which it uses in a call to the passed in action. Once the action completes, the `Lifetime` is terminated, which cleans up the store accessor, and the instance of `ChangeSettingsTemporarilyCore`, and therefore removes the temporary settings layer.
41 |
--------------------------------------------------------------------------------
/topics/Products/InspectCode.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: InspectCode Plugins)
2 |
3 | This page contains documentation on developing plugins for [InspectCode](http://confluence.jetbrains.com/display/NETCOM/Introducing+InspectCode), part of [ReSharper Command Line Tools](http://confluence.jetbrains.com/display/NETCOM/Introducing+ReSharper+Command+Line+Tools).
4 |
5 | InspectCode does not currently have a standalone SDK, however, it is compatible with ReSharper extensions, and will load them at runtime, if you pass the ID of the extension to the `/extension` command line argument (multiple arguments are accepted).
6 |
7 | When implementing a plugin that you wish to use with InspectCode, care must be taken not to rely on any components or interfaces that rely on Visual Studio integration - InspectCode runs as a standalone command line application, outside of Visual Studio. Any components you create in the extension that requires a Visual Studio component should pass the `ProgramConfigurations.VS_ADDIN` argument to `ShellComponentAttribute` or `SolutionComponentAttribute`.
8 |
9 | If you wish to create an extension that only targets InspectCode, the extension package should take a dependency on `"InspectCode"`, rather than `"ReSharper"`. In this way, InspectCode will load the extension, but ReSharper won't.
10 |
11 | Currently, the only extension point for InspectCode that isn't part of ReSharper is to create a custom Issue logger.
12 |
13 | * Create a standard ReSharper plugin, using the NuGet packages (target .NET 4.0)
14 | * Add additional reference to `JetBrains.CommandLine.InspectCode.Unattended.dll` library from CLT distribution.
15 | * Implement your own logic for `IInspectCodeConsumer`
16 |
17 | ```csharp
18 | public class IssueLogger : IInspectCodeConsumer
19 | {
20 | void IDisposable.Dispose() { }
21 |
22 | public void Consume(IIssue issue)
23 | {
24 | Console.WriteLine("{0}({1}) {2}", issue.File, issue.Range, issue.Message);
25 | }
26 | }
27 | ```
28 |
29 | * Implement `IInspectCodeConsumerFactory` factory to return a new instance of your consumer
30 |
31 | ```csharp
32 | [SolutionComponent]
33 | public class IssueLoggerFactory : IInspectCodeConsumerFactory
34 | {
35 | public IInspectCodeConsumer CreateConsumer(IEnumerable inspectScope, FileSystemPath outputFile = null)
36 | {
37 | return new IssueLogger();
38 | }
39 | }
40 | ```
41 |
42 | * Start InspectCode with following parameters
43 |
44 | ```
45 | inspectcode ... /Plugin=path-to-custom-logger-dll
46 | ```
47 |
--------------------------------------------------------------------------------
/topics/HowTo/NavigateCode/UseManualNavigation.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Use Manual Navigation)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 | * ShellLocks
6 |
7 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
8 | * [PsiExtensionMethods.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/PsiExtensionMethods.cs)
9 | * [NodeUnderCaretDetector.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/NodeUnderCaretDetector.cs)
10 |
11 | In some cases it might be useful to manually navigate the syntax tree (relatively to a particular tree node). For this purpose, any tree node has a number of properties and methods, like:
12 | * `Parent`: returns a parent tree node;
13 | * `Children`: returns `IEnumerable` with children nodes;
14 | * `NextSibling`, `PrevSibling`: next and previous sibling tree nodes;
15 | * lots of them.
16 |
17 | For example, let's create an `ITreeNode` extension method that walks up the syntax tree and finds (if there are any) a parent tree node of a particular type:
18 |
19 | ```csharp
20 | [CanBeNull]
21 | public static T GetParentOfType(this ITreeNode node) where T : class, ITreeNode
22 | {
23 | while (node != null)
24 | {
25 | var typedNode = node as T;
26 | if (typedNode != null)
27 | return typedNode;
28 |
29 | node = node.Parent;
30 | }
31 | return null;
32 | }
33 | ```
34 |
35 | For example, we can use it to navigate to the method declaration while standing anywhere inside a method:
36 |
37 | ```csharp
38 | private IShellLocks _shellLocks;
39 | private NodeUnderCaretNavigator _navigator;
40 |
41 | ...
42 |
43 | public void NavigateToParentMethod()
44 | {
45 | _shellLocks.ExecuteOrQueueReadLock(_lifetime, "NavigateToParent", () =>
46 | {
47 | var node = _navigator.GetTreeNodeUnderCaret;
48 | var parentMethod = node.GetParentOfType();
49 | parentMethod?.NavigateToTreeNode(true);
50 | });
51 | }
52 | ```
53 |
54 | ## Notes
55 | * We use the `GetTreeNodeUnderCaret()` method of the `NodeUnderCaretNavigator` class shown in [Get a Tree Node Under Caret](GetTreeNodeUnderCaret.md).
56 | * Note that to prevent conflicts with user input during the navigation, we must obtain the read lock before calculating the node under the caret. This is done by means of the special method of the `IShellLocks` interface: `_shellLocks.QueueReadLock(...)`.
57 |
--------------------------------------------------------------------------------
/topics/PSI/DeclaredElements.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Declared Elements)
2 |
3 | Declared elements are the backbone of ReSharper's semantic model, and provide a language-agnostic entry point into the semantic model of the codebase. While an AST provides a high-fidelity model of a code file, it is a representation only of the syntax - the typed text. It does little to help with the semantic view of the underlying code. For example, a definition of a C# class may be split across multiple files by using the `partial` keyword. Retrieving all type members from the AST now requires processing multiple ASTs, and the existing AST gives no indication of the location of the other part of the file. Similarly, if a C# class derives from the class `Foo`, the AST gives no indication which class `Foo` - what namespace does it belong to? A semantic model provides all of this information, for example, applying the type resolution rules to the `using` statements at the top of the file.
4 |
5 | At its simplest level, a declared element is "something that has declarations". This can be a CLR class declaration, or a method declaration, or something not even related to code - HTML elements, CSS classes and even colours and file system paths.
6 |
7 | All declared elements implement interfaces that derive from the language agnostic `IDeclaredElement` interface. For example, CLR types are represented with the `ITypeElement` interface, which provides methods and properties for getting at the declared elements for the target type's methods, properties, constructors and so on. Since a type's members are also represented as declared elements, it is (almost) possible to use declared elements to model an entire codebase. There are however, some scenarios that declared elements can't model, and these are documented in the [Type System](TypeSystem.md) section.
8 |
9 | The `IDeclaredElement` interface provides the `GetDeclarations` method that returns one or more `IDeclaration` instances. The `IDeclaration` interface derives from `ITreeNode` and is defined by the PSI for multiple languages to use for the declarations found in source code. For example, C#'s `IClassDeclaration` tree node inherits from `IDeclaration`, allowing a language agnostic way of working with tree nodes that are also declarations. This links a declared element to its declaration in source, allowing code that has a method declaration to walk the AST of that declaration to look at the method body.
10 |
11 | Similarly, the `IDeclaration` interface provides a `DeclaredElement` property, which allows code to get to a declared element, given a declaration node in the AST.
12 |
--------------------------------------------------------------------------------
/topics/Platform/TextControl.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: TextControl)
2 |
3 | Though for the most part plug-ins work by manipulating the AST, it is sometimes necessary to interact with the underlying text control. One typical example of this is when deploying _highlightings_ - those wavy lines that are used to underline code that needs to be corrected.
4 |
5 | Interaction with the text control is done via the _TextControl abstraction_. This abstraction, represented by an `ITextControl` and related interfaces, abstracts away the physical text editing control by putting a View on top of this. There are currently two varieties of such a view: one supporting Visual Studio and another supporting dotPeek.
6 |
7 | ## ITextControl
8 |
9 | The `ITextControl` interface is a view for editing an `IDocument`. It contains, among other things, information about the position of the caret and selection, the text control’s scrolling parameters, and of course exposes an `IDocument`, i.e. the document that the text control supplies.
10 |
11 | In case you want to show code-related UI elements, the text control also provides an interface for coordinate conversion. There is also an `IsPositionInTextView()` method which can tell you whether a particular text control position is in the view area of the text control. You have probably see this in action in terms of bulb actions and blue pop-up windows that only show up in relation to the code that’s currently visible on screen.
12 |
13 | ## TextRange and Offsets
14 |
15 | The `TextRange` type is used to store information about a _range_, i.e. a selection of characters starting and ending at particular positions (offsets). Direct textual manipulation of a document typically happens by way of either `TextRange` parameters or integer offsets. For example, you can use `IDocument.DeleteText` to delete text at the specified `TextRange`.
16 |
17 | In certain cases, the document itself exposes information about offsets. For example, if you want to get a `TextRange` for a whole line, you would construct a `TextRange` from the values provided by `IDocument.GetLineStartOffset()` and `IDocument.GetLineEndOffsetNoLineBreak()`. Both of these methods take the line number as a parameter.
18 |
19 | `TextRange` contains a number of utility methods for working with ranges such as, e.g., creating an intersection of two ranges. Some of these methods are also mirrored in the API of the `DocumentRange` type (see below).
20 |
21 | ## DocumentRange
22 |
23 | The `DocumentRange` type is simply a container for the `TextRange` as well as the document it relates to. This type is used in, e.g., the construction of highlightings.
24 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/HtmlLike/ExtendingHtml.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Extended HTML Parsing)
2 |
3 | Custom HTML-like languages can modify the lexing of standard HTML by providing an alternative HTML lexer to the constructor of `HtmlCompoundLexer` (typically a new instance of `HtmlLexerFactory` is passed).
4 |
5 | However, it is not currently possible to extend the lexing/parsing of standard HTML files, or the standard HTML portions of custom files such as WebForms or Razor, from third party code. An example of this would be to add support for custom templates inside the language, such as Angular's interpolation expressions:
6 |
7 | ```html
8 |
9 | ```
10 |
11 | This kind of syntax can be supported by third party code using existing extension mechanisms. For example, if the syntax is simple enough, this could be implemented by [References](References.md) and [Daemon](Analysis.md) support for highlighters. If the expression is more complex, it can also be implemented by using [Injected PSI](InjectedPsi.md), although this is not very efficient, as the content of the nodes are converted to and from strings on modification. There are also limitations on nested injections. It is best to only use injected PSI for small ranges.
12 |
13 | ## Angular expressions
14 |
15 | ReSharper's support for Angular expressions is currently implemented differently, to work around these limitations. The implementation of `HtmlProjectFileLanguageService` returns `HtmlLanguage` by default, but returns `Angular2HtmlLanguage` when Angular support is enabled.
16 |
17 | This means that HTML files are treated as "Angular HTML" files, and are now associated with the `Angular2HtmlLanguage` PSI language type. It also means that the per-language components for HTML files are resolved using `Angular2HtmlLanguage` instead of `HtmlLanguage`. One implication of this is that the lexer factory registered for HTML files becomes `Angular2HtmlLexerFactory` instead of `HtmlLexerFactory`. This new lexer factory creates a lexer that is derived from `HtmlRawLexerGenerated`, and parses standard HTML, but also handles expressions that are wrapped in braces.
18 |
19 | This does not affect compound lexers - typically, they pass in a new instance of `HtmlLexerFactory`. To get Angular support in a custom HTML-like language, pass in an instance of `Angular2HtmlLexerFactory`.
20 |
21 | In order to match ReSharper behaviour, the custom language should check to see if Angular support is enabled, by taking in an instance of the `AngularIsEnabledProvider` shell component, and comparing the `GlobalAngularLevel` to `AngularLevel.None`.
22 |
--------------------------------------------------------------------------------
/topics/Platform/Zones/Zones_HowTo.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: How to Define a Zone Marker)
2 |
3 | When creating an extension, it is important to get the right dependencies for a `ZoneMarker`. Zones are used to be able to correctly load a product in the correct host. If the zone marker is incorrect, either the components in that namespace are not loaded and the extension is not available, or the extension is loaded when it shouldn't be, and can cause errors in hosts as expected dependencies are not available.
4 |
5 | ReSharper ships with diagnostics to help create accurate zone markers. **Unfortunately**, the diagnostics currently only work when all zones are defined in source (i.e. when you're building the ReSharper solution). When building an extension that references the ReSharper Platform via assembly references (i.e. through the SDK), the diagnostics **do not work**. An updated version of the diagnostics is being worked on, and will be available as a separate, SDK tools extension shortly.
6 |
7 | (The diagnostics check the zone of each component used in the project, e.g. type usages in component constructors. If the zone isn't explicitly or implicitly required by the current zone marker, the type is highlighted, and a quick fix is available to add the required zone to the zone marker.)
8 |
9 | Without diagnostics, it is very hard to work out what zones should be required. If you wish to use a component in your code, you need to discover which zone definitions it requires, and include those in your zone marker. This is done by finding the `ZoneMarker` class, and requiring the same zone definitions. This can be done by hand, by finding zone marker classes that live in the same namespace or higher as those used in your `using` statements, but this is tedious and prone to error.
10 |
11 | A temporary solution is to use an [empty zone marker](Zones_Usage.md#empty-zone-marker). This is usually reserved for infrastructure code that has no real dependencies and should always run. However, as calculating the proper requirements is currently prohibitive, it should be used (TEMPORARILY) for extensions.
12 |
13 | > This guidance is TEMPORARY! It is STRENUOUSLY RECOMMENDED to provide accurate and minimal zone information, in order that your extension is correctly loaded into the appropriate hosts, and does not cause issues for other hosts.
14 | >
15 | > Without proper dependency information, extensions CAN and WILL FAIL. E.g. an extension intended to extend ReSharper will cause problems when run in a host with only dotCover installed.
16 | >
17 | > This guidance will be updated when the appropriate tooling is available to help calculate the correct requirements for zone markers.
18 |
--------------------------------------------------------------------------------
/topics/PSI/TypeSystems2.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Type systems)
2 |
3 | The `IDeclaredElement` interfaces provide a semantic view of something that has a declaration, but that doesn't necessarily allow for modelling *usages* of the element. Specifically, if we take a look at CLR types, a declared element is a declaration of a type, such as a class, but it can't represent all usages of the type, such as in an array, pointer or closed generic type. The `ITypeElement` interface can provide a semantic view of the declaration of `Foo` or `Bar`, but it can't represent `Foo[]` or `Bar`.
4 |
5 | Declared elements need to be able to model these usage scenarios to provide information about base classes, method signatures, etc. In order to do so, the derived declared elements (such as `ITypeElement`) use an additional interface hierarchy to represent this "type system" information. This hierarchy is language specific, like the derived declared elements that use them. For CLR types, it's the `IType` hierarchy, for JavaScript, it's `IJavaScriptType`.
6 |
7 | This `IType` is additional information rather than a replacement for the declared element's semantic view. While the `IType` can return a symbol table of all type members, it doesn't provide accessors in the same way that `ITypeElement` does. However, it is possible to get back to the declared element. If the type implements `IDeclaredType`, the `GetTypeElement` method will return the `ITypeElement`, which gives the full semantic view of the type.
8 |
9 | Arrays and pointers are both defined in terms of another instance of `IType`, allowing for recursively declaring types, such as multi-dimensional arrays, or arrays of generic types. The derived interfaces, such as a `IArrayType` allow getting the element type (such as `int` in `int[]`), and in the case of arrays, the array's rank.
10 |
11 | Generic types are internally represented by a declared element and an instance of `ISubstitution`, which describes how the generic type parameters are substituted. (Non generic types are represented in the same manner, but use the Null Object Pattern and use an instance of `EmptySubstitution`)
12 |
13 | It's also possible to get the underlying declared type via the `IType.GetScalarType` method, which returns the element type for arrays, and will downcast to `IDeclaredType` for other types.
14 |
15 | Types are retrieved from a declared element - such as a base type, or member type signature. Alternatively, types can be created using the `TypeFactory.CreateType` methods, passing in a fully qualified type name and any type parameters, or an `IDeclaredElement` and an instance of `ISubstitution`. Some frequently used types are also available from the `PredefinedType` class.
16 |
--------------------------------------------------------------------------------
/topics/HowTo/NavigateCode/AddYourNavigationActionToNavigateToMenu.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Add a Navigation Action to the 'Navigate to' Menu)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 |
6 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
7 | * [NavigateToCtorProvider.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/NavigateToCtorProvider.cs)
8 |
9 | If you want your navigation to appear in ReSharper's **Navigate To** menu ([context navigation](NavigateCode.md)), you should create an action that implements the `INavigateFromHereProvider` interface.
10 |
11 | 
12 |
13 | For example, let's create a context-dependent navigation that navigates to a class constructor. The initial caret position can be anywhere inside that class.
14 |
15 | ```csharp
16 | [ContextNavigationProvider]
17 | public class NavigateToCtorProvider : INavigateFromHereProvider
18 | {
19 | public IEnumerable CreateWorkflow(IDataContext dataContext)
20 | {
21 | var node = dataContext.GetSelectedTreeNode();
22 | var typeDeclaration = node?.GetParentOfType();
23 | var constructor = typeDeclaration?.ConstructorDeclarations.FirstNotNull();
24 |
25 | if (constructor != null)
26 | {
27 | yield return new ContextNavigation("Constructor", null, NavigationActionGroup.Other, () =>
28 | {
29 | constructor.NavigateToTreeNode(true);
30 | });
31 | }
32 | }
33 | }
34 | ```
35 |
36 | ## Notes
37 |
38 | * The class must implement the `INavigateFromHereProvider` interface and be marked with the `ContextNavigationProvider` attribute.
39 | * `GetSelectedTreeNode()` method of `IDataContext` return the tree node under the current caret position.
40 | * We use the `GetParentOfType` method from [Use Manual Navigation](UseManualNavigation.md) to obtain the `IClassDeclaration` node.
41 | * The `IClassDeclaration` class provides the `ConstructorDeclarations` property that returns an enumerable with class constructors.
42 | * A created instance of the `ContextNavigation` class describes the navigation feature:
43 | * `"Constructor"`: the name of the item that appears in the **Navigate to** context menu.
44 | * `null`: action ID.
45 | * `NavigationGroup.Other`: defines the location in the **Navigate to** menu where the action should be placed.
46 | * The last one argument is the action that is run once the **Constructor** item is selected in the **Navigate to** menu.
47 | * Note that ReSharper automatically decides whether to display the item in the menu or not.
48 |
--------------------------------------------------------------------------------
/topics/HowTo/CreateQuickFix/CreateQuickFix.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Create a Quick-Fix)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 | * [Code analyzer](AnalyzeCodeOnTheFly.md)
6 |
7 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
8 | * [CorrectBadWordQuickFix.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/QuickFix/CorrectBadWordQuickFix.cs)
9 |
10 | The main difference between a context action and a quick-fix is that the latter appears only in response to a highlighting. Thus, quick-fixes are used to fix a problem that was found and highlighted by a particular code analyzer.
11 |
12 | 
13 |
14 | For example, let's create a simple quick-fix that reacts to the warning provided by the analyzer from [Analyze Code on the Fly](AnalyzeCodeOnTheFly.md) and suggests to replace the "Crap" word occurrence with "BadWord".
15 |
16 | ```csharp
17 | [QuickFix]
18 | public class CorrectBadWordQuickFix : QuickFixBase
19 | {
20 | private readonly IVariableDeclaration _variableDeclaration;
21 |
22 | public CorrectBadWordQuickFix([NotNull] BadWordNamingWarning warning)
23 | {
24 | _variableDeclaration = warning.VariableDeclaration;
25 | }
26 |
27 |
28 | protected override Action ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
29 | {
30 | return textControl =>
31 | {
32 | var newText = Regex.Replace(_variableDeclaration.DeclaredName, "crap", "BadWord", RegexOptions.IgnoreCase);
33 |
34 | RenameRefactoringService.Rename(solution,
35 | new RenameDataProvider((IDeclaredElement) _variableDeclaration, newText), textControl);
36 | };
37 | }
38 |
39 | public override string Text => "Replace the bad word";
40 |
41 | public override bool IsAvailable(IUserDataHolder cache)
42 | {
43 | return _variableDeclaration.IsValid();
44 | }
45 | }
46 | ```
47 |
48 | ## Notes
49 | * The easiest way to create a quick-fix is to inherit from the `QuickFixBase` class.
50 | * The quick-fix class must be marked with the `QuickFix` attribute.
51 | * The `BadWordNamingWarning` warning highlighting object passed to the constructor is used to obtain a particular code element that should be fixed (the code element that is highlighted by a particular highlighting).
52 | * The `Text` property defines the text that will be shown in the actions list.
53 | * `IsAvailable` is used to check whether the quick-fix action is available for the current caret position.
54 | * `ExecutePsiTransaction` returns the action that is executed when the quick-fix is selected.
55 | * Note that we use `RenameRefactoringService` to change variable's name. The service performs seamless renaming of a variable everywhere in the code.
56 |
--------------------------------------------------------------------------------
/topics/PSI/References/IReferenceProvider.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Managing reference providers)
2 |
3 | To build a reference provider, you implement `IReferenceProviderFactory`, `IReferenceFactory` and `IReference`. It is very easy to get these mixed up with the `ReferenceProviderFactory` class and the `IReferenceProvider` interface, however, they serve different purposes. `ReferenceProviderFactory` and `IReferenceProvider` are facades that manage the responsibility of delegating and aggregating the creation of custom references to multiple custom reference providers.
4 |
5 | The `ReferenceProviderFactory` class hides the complexity of maintaining a large collection of custom reference providers. It is a `[PsiComponent]` that maintains an `IViewable`. It has one public method:
6 |
7 | ```csharp
8 | public class ReferenceProviderFactory
9 | {
10 | public IReferenceProvider Create(IPsiSourceFile sourceFile, IFile file);
11 | }
12 | ```
13 |
14 | This method iterates over the collection of custom reference providers and calls `IReferenceProviderFactory.CreateFactory` on each, maintaining a list of the returned `IReferenceFactory` instances. It then returns a custom instance of `IReferenceProvider` that is based on this list of custom reference factories.
15 |
16 | The `IReferenceProvider` interface is very similar to the `IReferenceFactory` interface:
17 |
18 | ```csharp
19 | public interface IReferenceProvider
20 | {
21 | ReferenceCollection GetReferences(ITreeNode element, ICollection names);
22 | bool ContainsReference(ITreeNode element, IReference reference);
23 | }
24 |
25 | public interface IReferenceFactory
26 | {
27 | IReference[] GetReferences(ITreeNode element, IReference[] oldReferences);
28 | bool HasReference(ITreeNode element, ICollection names);
29 | }
30 | ```
31 |
32 | `IReferenceProvider` also acts as a façade, this time over the collection of `IReferenceFactory` instances, and in fact has a slightly different signature, more aimed at consuming references than creating them.
33 |
34 | It is responsible for caching the references, and keeping them up to date when the PSI changes. If there is no data cached, or it is not up to date, it calls each of the `IReferenceFactory.GetReferences` implementations in turn, passing in the old references, if applicable. The returned new references are then cached and returned on demand. It will short circuit the cache update when possible by calling `IReferenceFactory.HasReferences`. If no reference factory has references here, the cache isn't consulted or updated. It also includes an optimisation that restores the previously known references if the current PSI transaction is rolled back.
35 |
36 | There should be no reason to use `ReferenceProviderFactory` or `IReferenceProvider` directly, and is documented to prevent confusion between similarly named classes and interfaces.
37 |
--------------------------------------------------------------------------------
/topics/Platform/Lifetime/Lifetime_Usage.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Usage)
2 |
3 | The `Lifetime` class looks like this:
4 |
5 | ```csharp
6 | public class Lifetime
7 | {
8 | public Lifetime AddAction(Action f);
9 | public Lifetime AddBracket(Action fOpening, Action fClosing);
10 | public Lifetime AddDispose(IDisposable item);
11 | public Lifetime AddRef(object o);
12 | public bool IsTerminated { get; }
13 | }
14 | ```
15 |
16 | Your code receives a `Lifetime` instance, and registers its cleanup callback using `AddAction`. It then doesn't need to do anything else. When the `Lifetime` is terminated, the callback is called, and the action is performed. Actions are called in reverse order to how they were added. If an exception is thrown by an action, it is logged, and the next action is called.
17 |
18 | ```csharp
19 | public void MyMethod(Lifetime lifetime)
20 | {
21 | lifetime.AddAction(() => { /* Do cleanup */ });
22 | }
23 | ```
24 |
25 | * The `AddBracket` method accepts two callbacks. The first, `fOpening`, is called immediately, and the second, `fClosing` is registered to run when the `Lifetime` is terminated. This way, the methods form a "bracket" around the duration of the `Lifetime` object.
26 |
27 | * There is also a bridge between `IDisposable` and `Lifetime`. The `AddDispose` method simply registers a callback that will call `Dispose` on the given `IDisposable`.
28 |
29 | * The `AddRef` method keeps a given object alive (i.e. it won't be garbage collected) until the `Lifetime` is terminated.
30 |
31 | * You can check to see if a `Lifetime` has been terminated by calling the `IsTerminated` property. Note that you can't terminate a `Lifetime` directly.
32 |
33 | ## Extension methods
34 |
35 | Generally speaking, especially when writing plugins, you are more likely to pass a `Lifetime` to a method than to directly add your own cleanup callbacks. When consuming services, adding items or registering callbacks, passing in a `Lifetime` will allow that service or object to add the cleanup, removal or un-registration code for you. You should generally favour method overloads that take a `Lifetime` over those that don't.
36 |
37 | For example, the `JetBrains.Util.CollectionUtil` class provides several extension methods for `ICollection`. These methods simply call `Lifetime.AddBracket` to immediately add the item, and will remove the item when the `Lifetime` is terminated. This means the items only exist in the collection for the duration of the `Lifetime`.
38 |
39 | Similarly, the `Threading` subsystem's `JetDispatcher` class, which can be used to dispatch actions to the main thread has an overload to the `BeginInvoke` method which take a `Lifetime`. This queues the given action to execute on the main thread, at some point in the near future. If you terminate the `Lifetime`, the action is (effectively) removed from the queue, and the action isn't executed. This is an easy way to prevent race conditions.
40 |
--------------------------------------------------------------------------------
/topics/testing/TestComponents.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Test Components)
2 |
3 | > This topic assumes familiarity with the concept and usage of both the [Component Model](Platform_ComponentModel.md) and [Zones](Platform_Zones.md) topics.
4 | >
5 | {type="warning"}
6 |
7 | When starting the [test environment](TestEnvironment.md), the [Component Model](Platform_ComponentModel.md) will scan all of the assemblies in the output folder, including the ReSharper platform and product assemblies, as well as the plugin and its test assemblies. It will use the currently activated [Zones](Testing_Zones.md) to filter the components, and instantiate only those that are in active zones.
8 |
9 | For the majority of components, this will be very similar to the normal ReSharper startup process. The test environment will likely be started with a zone definition that activates the standard testing zone definition `PsiFeaturesTestZone`, which in turn activates most of the zone definitions necessary for normal ReSharper functionality (e.g. C# and JS support, daemon, navigation, unit testing, etc.).
10 |
11 | This process will also load any components that are defined in the plugin. Normal component zone usage applies, so a plugin's components will only be created if those components live in a namespace that has a [Zone Marker](Zones_Usage.md#zone-markers) that in turn requires zones that are currently active. For example, the plugin could define components that live in a zone that requires the `IUnitTestingZone`. As long as the `IUnitTestingZone` is active, the plugin's components will also be active.
12 |
13 | Since the test assembly is also scanned for components, it is possible to create components that are only loaded while testing. This can be very useful to provide services to tests, or to augment or override existing components in the main product. For example, it might be useful to replace an existing component that would hit the disk, or a database or web service in order to return a default, well known response. Existing components can be replaced, either by inheriting from that component, or by implementing the `IHideImplementation` interface. See the guide section on [overriding and replacing components](ContainersPartsCatalogues.md#overriding-and-replacing-components) for more details. If the component is one of many implementations of the same interface, and that type of component supports priority between components, it might be possible to override undesired behaviour by also implementing the interface and returning a higher priority.
14 |
15 | In order for test components to be active, they need to live in a namespace (or below a namespace) that is marked with a [Zone Marker](Zones_Usage.md#zone-markers) that requires an active zone definition. For example:
16 |
17 | ```csharp
18 | namespace MyPlugin
19 | {
20 | [ZoneMarker]
21 | public class ZoneMarker : IRequire
22 | {
23 | }
24 |
25 | [ShellComponent]
26 | public class MyTestComponent
27 | {
28 | // ...
29 | }
30 | }
31 | ```
32 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Registration/PsiLanguageDefinition.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Registering a PSI Language)
2 |
3 | Once a custom language's [file type has been registered with the Project Model](ProjectFileType.md), the language definition needs to be registered with the PSI. If it's not registered with the PSI, ReSharper will not be able to build a PSI tree, and in fact will not consider it registered with the Project Model, either.
4 |
5 | The PSI maintains a hierarchy of supported languages, in a similar manner to how the Project Model maintains a hierarchy of supported file types. The base class is `PsiLanguageType`, and there are again, two directly derived classes - `KnownLanguage` and `UnknownLanguage`. The first is the base class for all known languages, and can be used to mean any and all known PSI languages. The second, `UnknownLanguage`, is a sealed class, and represents a language that the PSI does not support.
6 |
7 | A custom language should create a class that derives from `KnownLanguage`, or a suitable base class (for example, if your language is a subset of HTML, such as a `.aspx` file, you can derive from `HtmlLanguage`). The custom class should provide a programmatic name and a presentable name, and it should be marked with the `[LanguageDefinition(...)]` attribute. For example, C#:
8 |
9 | ```csharp
10 | [LanguageDefinition(Name, Edition = ReSharperEditions.Ids.Csharp)]
11 | public class CSharpLanguage : KnownLanguage
12 | {
13 | // Must be "new" as it overrides a public field in the base
14 | public new const string Name = "CSHARP";
15 |
16 | // May need "new" if inheriting from another language, such as HTML
17 | // This value might be null, if the language has been disabled in Options
18 | [CanBeNull] public static readonly CSharpLanguage Instance;
19 |
20 | private CSharpLanguage() : base(Name, "C#") { }
21 |
22 | protected CSharpLanguage([NotNull] string name) : base(name) { }
23 |
24 | protected CSharpLanguage([NotNull] string name, [NotNull] string presentableName) : base(name, presentableName) { }
25 | }
26 | ```
27 |
28 | The `[LanguageDefinition]` attribute passes in the programmatic name. It also supports an `Edition` property, which is no longer used. This is a legacy feature to allow languages to be disabled based on which edition of the product has been purchased. This functionality has been replaced by [Zones](Platform_Zones.md).
29 |
30 | Each node in the PSI tree exposes its owning language via the `ITreeNode.Language` property, which returns an instance of `PsiLanguageType`.
31 |
32 | Languages are instantiated by the `ILanguages` shell component, which will create the class using the default constructor, and set the static `Instance` field, meaning all language definitions are singletons.
33 |
34 | The `ILanguages` interface also provides the means to retrieve and enumerate all language definitions.
35 |
36 | ```csharp
37 | public interface ILanguages : IViewable
38 | {
39 | IEnumerable All { get; }
40 | PsiLanguageType GetLanguageByName(string languageName);
41 | }
42 | ```
43 |
--------------------------------------------------------------------------------
/topics/PSI/Caching.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Caches)
2 |
3 | ReSharper makes heavy use of caching in order to store all the information required to provide a semantic view of a codebase. The caches are calculated on solution load, stored to disk, and reloaded when the solution is subsequently loaded. Any time a file changes, the cache is notified, and can rescan the file and update its details.
4 |
5 | The PSI implements the infrastructure for building and maintaining a cache, and provides a number of different caches, such as `ISymbolCache` - a symbol cache for looking up CLR `ITypeElement` declared elements, and `IWordIndex`, which is an index of words and the files they are used in (one use of this is reverse lookup of references).
6 |
7 | The cache infrastructure is extensible, and other parts of the architecture create their own caches on top of this infrastructure. For example, the To Do Explorer maintains a cache that initially scans all files for to-do items, and keeps the list of items up to date as files change.
8 |
9 | Caches are very useful for cross-file analysis, amongst other things. Normal analysis is performed in the context of a single file, and is called very frequently as the file is edited. It should therefore be as fast as possible, and not try to scan other files.
10 |
11 | For example, imagine a scenario where an analyser is trying to ensure uniqueness of assembly level attributes. When a file is changed, the analyser can look in that file for the required attribute, but it would be very bad for performance if it would also try to scan all other files in the project for the same attribute. Instead, a cache can be implemented to initially scan for all attribute instances, and used by the analyser to look up potential duplicates.
12 |
13 | The PSI caches can be retrieved by using `IPsiServices`, which provides direct access to `ISymbolCache` via `IPsiServices.Symbols`, or `IWordIndex` via `IPsiServices.WordIndex`. Other caches can be injected directly into a class constructor.
14 |
15 | A similar service is the `IPersistentIndexManager`, which is an extensible, persistent cache that is not related to file contents. For example, the unit test runner uses a persistent index to store results for each test. A persistent index is a disk backed key-value store (implemented on [LevelDB](http://en.wikipedia.org/wiki/LevelDB) although this is an implementation detail) that automatically manages what data is in memory or flushed to disk. The interface is a simple dictionary-like lookup.
16 |
17 | Finally, the PSI maintains a set of in-memory caches. These are lightweight, transient caches that aren't persisted and are invalidated when any abstract syntax tree changes. They are intended to temporarily cache the result of operations that might occur again. Generally speaking, these caches are not intended for consumption from extensions, as they are used by other parts of the code. However, the cache can be retrieved either by injecting the component into a class constructor or by using `IPsiServices.Caches.GetPsiCache` where `T` is the required cache, which implements `IPsiCache`, such as `InternalsVisibleToCache`.
18 |
--------------------------------------------------------------------------------
/topics/Platform/Zones/FeaturesProducts.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Features and Products)
2 |
3 | ## Features
4 |
5 | Since all components in the Component Model are now grouped into zones, it is possible to treat a zone as a feature, and allow the user to disable that feature, by removing the zone's components from the Component Model's container. However, not all zones should be features, some zones are clearly implementation details, while others are integral to the product and shouldn't be disabled.
6 |
7 | ReSharper supports this for specific zone definitions. The Features page on the options dialog lists products and features that can be disabled.
8 |
9 | 
10 |
11 | This list is populated by applying the `ZoneDefinitionConfigurableFeatureAttribute` to a zone definition. It takes three settings - the name of the feature, a short description, and a flag to state if the zone definition should be treated as a feature or a product.
12 |
13 | ```csharp
14 | [ZoneDefinition]
15 | [ZoneDefinitionConfigurableFeature("CSS Language", "Support for CSS language in .css and HTML based files", false)]
16 | public interface ILanguageCssZone : IPsiLanguageZone, IRequire
17 | {
18 | }
19 | ```
20 |
21 | These properties are only used by the UI. When the zone is disabled, the zone definition type's short name is saved to settings. If a feature zone has dependents (that is, other zones that depend on the feature zone), those dependent zones (and therefore features) are also disabled. For example, disabling the HTML zone will also disable the CSS zone. The dependent zone definition's short name is also written to settings.
22 |
23 | Disabling a zone requires Visual Studio to be restarted, as all Visual Studio integration requires static registration (e.g. assemblies are registered as MEF exports, and actions are registered as static Visual Studio commands).
24 |
25 | ## Products
26 |
27 | A zone definition can be treated as a product by passing `true` to the `isInProductSection` parameter of `ZoneDefinitionConfigurableFeatureAttribute`. The difference here is purely cosmetic. By setting this parameter to `true`, the options dialog page displays the zone in the "Products" section rather than the "Features" section. The intention of this flag is to allow the hierarchical nature of zones to be used to provide an obvious "off switch" to the user in order to disable all of the features in a product. By disabling a product zone, all dependent zones are also disabled.
28 |
29 | ### Product information
30 |
31 | A product can also expose product information to the ReSharper Platform, by using the `ZoneDefinitionProductAttribute`. It is simply an informational attribute, used to inform the user of the name of the installed product, the company responsible and to provide links to product web pages.
32 |
33 | ```csharp
34 | [ZoneDefinition]
35 | [ZoneDefinitionProduct(CompanyName = "JetBrains", CompanyNameLegal = "JetBrains s.r.o.",
36 | ProductPresentableName = "ReSharper", ProductTechnicalName = "ReSharper", Version = "9.1",
37 | ProductUrl = "http://www.jetbrains.com/resharper",
38 | ProductIcon = typeof(ReSharperUIThemedIcons.ReSharper16x16))]
39 | public class IReSharperProductZone : IZone
40 | {
41 | }
42 | ```
43 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/Parsing.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Parsing)
2 |
3 | Parsing or ["syntactic analysis"](https://en.wikipedia.org/wiki/Parsing) is the process of taking an input stream of tokens and producing a [parse tree](https://en.wikipedia.org/wiki/Parse_tree). This parse tree is used by ReSharper to build a semantic model, with rich information about types, and also used to navigate, analyse and manipulate the code. For example, the unit testing functionality is implemented by walking the parse tree of a file and looking for certain constructs, such as class and method decorations with specific attributes. Similarly, refactoring is the act of rewriting the parse tree, which has the effect of rewriting the underlying text file.
4 |
5 | A parse tree built by a ReSharper language is sometimes known as a **PSI tree**, named for the Program Structure Interface subsystem that is responsible for building and maintaining such trees. It is also commonly referred to as an abstract syntax tree, but it is more correct to call it a concrete parse tree. A concrete parse tree is an accurate model of the syntax in a file, while an abstract syntax tree can be simplified. See [this page for a good description of the differences](http://eli.thegreenplace.net/2009/02/16/abstract-vs-concrete-syntax-trees).
6 |
7 | All nodes in a ReSharper parse tree implement a common set of interfaces - namely `ITreeNode`, with a root node also implementing `IFile`. ReSharper provides common functionality to navigate and manipulate these trees, without requiring any knowledge of the language of the underlying file. The interfaces describe the relationship between the nodes, and also provide useful information and services, such as if a node has outgoing [references](References.md), which are used for Go to Definition, Find Usages and the Rename refactoring.
8 |
9 | A custom language can create a parser that will take a lexer as input. It will analyse the tokens produced by the lexer and return a root `IFile` tree node. This node represents the whole of the file, and will have children that represent the structural and semantic constructs of the file (such as class declarations, method declarations, method bodies, statements, expressions, etc.).
10 |
11 | The parser can be created either by hand, using the PSI's `TreeBuilder` helper classes, or by using the PsiGen SDK tool to generate a parser from a custom `.psi` file format that describes the grammar. When generating a parser, the PsiGen tool will also generate the classes and interfaces that make up the tree. While it is possible to create these classes by hand, it is usually quicker and more accurate to describe a grammar in a `.psi` file and get the tool to generate them, even if the parser is created by hand. Generating a parser by hand is only recommended if the grammar is difficult to implement in the `.psi` file format, or if the grammar is to be reused and extended, by another language. For example, the TypeScript grammar reuses parts of the JavaScript parser, which makes it a good candidate for writing by hand - the generated parser cannot be extended and reused in this manner. Despite having different implementations, both methods will create efficient parsers, which is required, as a parse tree needs to be updated as a user edits the file.
12 |
--------------------------------------------------------------------------------
/topics/Platform/Lifetime/LifetimeDefinition.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Lifetime Management)
2 |
3 | A lifetime is made up of two parts, the `Lifetime` instance, which is passed around and used to register callbacks, and a `LifetimeDefinition` which is used to manage the lifetime.
4 |
5 | ## LifetimeDefinition
6 |
7 | You cannot terminate a `Lifetime` instance; unless you create it, you do not own it, therefore you shouldn't terminate it. Instead, when you create a `Lifetime`, you receive an instance of `LifetimeDefinition`, and this class allows you to terminate the `Lifetime`. Here's what it looks like:
8 |
9 | ```csharp
10 | public class LifetimeDefinition
11 | {
12 | public void Terminate();
13 | public bool IsTerminated { get; }
14 | public Lifetime Lifetime { get; }
15 | }
16 | ```
17 |
18 | It is a very simple class. You can get the `Lifetime` instance it is associated with, and calling `Terminate` will terminate this instance. The `IsTerminated` property will return true if `Terminate` has been called.
19 |
20 | When terminating, the callbacks registered to the `Lifetime` are called in reverse order of registration. That is, most recently registered first. All callbacks are called, even if one throws an exception - the exception is logged, and then ignored (favouring continuing cleanup over exception reporting).
21 |
22 | ## Lifetime Creation
23 |
24 | You can use the `Lifetimes` class to create your own `Lifetime` instances.
25 |
26 | > You should normally let the Component Model [create a `Lifetime` for your component](Lifetime_ComponentModel.md).
27 | >
28 | {type="note"}
29 |
30 | ### Short lived Lifetimes
31 |
32 | If you only need a `Lifetime` for a short period of time, the `Lifetimes.Using(Action f)` method will create a new instance, call your method and then immediately terminate the `Lifetime`. There is also an overload that takes in a `Func` to allow your method to return a value.
33 |
34 | ### Nested Lifetimes
35 |
36 | If you want a longer-lived `Lifetime`, you can call `Lifetimes.Define`:
37 |
38 | ```csharp
39 | Lifetimes.Define(Lifetime lifetime, string id, Action action, ILogger logger);
40 | ```
41 |
42 | This method takes in a `Lifetime` to act as a parent; the new `Lifetime` is a "nested" lifetime. Terminating the parent `Lifetime` will also terminate this new child `Lifetime`. Of course, if the child terminates first, it removes itself from the parent's cleanup.
43 |
44 | > If you don't have a parent `Lifetime` available, you can use `EternalLifetime.Instance`. Generally speaking, `EternalLifetime` should be avoided, as it is never terminated. Items scheduled against `EternalLifetime` will not run, and will not get garbage collected, effectively resulting in a memory leak. The preferred use case for `EternalLifetime` is to act as a parent for another `Lifetime`.
45 | >
46 | {type="note"}
47 |
48 | The `Define` method has a number of optional parameters, firstly an id, which is only used for diagnostic purposes. Secondly, an action that is called as soon as the `LifetimeDefinition` has been created. And finally, an optional instance of `ILogger`. If no logger is passed in, the default logger instance from `Logger.Interface` is used (see the Logging section for more details on logging).
49 |
--------------------------------------------------------------------------------
/topics/HowTo/NavigateCode/GetTreeNodeByReference.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Get a Tree Node by Reference)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 | * ShellLocks
6 |
7 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
8 | * [PsiExtensionMethods.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/PsiExtensionMethods.cs)
9 | * [NodeUnderCaretDetector.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/PsiNavigation/NodeUnderCaretDetector.cs)
10 |
11 | This is useful in case you need to navigate to an element that is referenced by a particular tree node (e.g., from a usage to a declaration).
12 |
13 | So, the task is to obtain the [reference](NavigateCode.md#psi-basics) you need. For example, we want to create a navigation from a particular expression to a declaration (the example is quite useless as it duplicates ReSharper's functionality, nevertheless, it perfectly illustrates the usage of references).
14 |
15 | Let's make this as an extension method for `ITreeNode`:
16 |
17 | ```csharp
18 | [CanBeNull]
19 | public static IEnumerable GetReferencedElements(this ITreeNode node)
20 | {
21 | var result = new List();
22 | var parentExpression = node.GetParentOfType();
23 | if (parentExpression == null) return null;
24 |
25 | var references = parentExpression.GetReferences();
26 |
27 | foreach (var reference in references)
28 | {
29 | var declaredElement = reference.Resolve().DeclaredElement;
30 | if (declaredElement != null)
31 | result.Add(declaredElement);
32 | }
33 |
34 | return result.Count == 0 ? null : result;
35 | }
36 | ```
37 |
38 | Now, it can be used to navigate to the first referenced element of the tree node under the caret (it would be always a declaration):
39 |
40 | ```csharp
41 | private IShellLocks _shellLocks;
42 | private NodeUnderCaretNavigator _navigator;
43 |
44 | // ...
45 |
46 | public void NavigateToFirstReferencedElement()
47 | {
48 | _shellLocks.ExecuteOrQueueReadLock(_lifetime, "NavigateByReference", () =>
49 | {
50 | var node = _navigator.GetTreeNodeUnderCaret();
51 | var referencedElements = node.GetReferencedElements();
52 | var element = referencedElements?.FirstNotNull();
53 | element?.Navigate(true);
54 | });
55 | }
56 | ```
57 |
58 | ## Notes
59 | * We use the `GetTreeNodeUnderCaret()` method of the `NodeUnderCaretNavigator` class shown in [Get a Tree Node Under Caret](GetTreeNodeUnderCaret.md).
60 | * We use the `GetParentOfType` method from [Use Manual Navigation](UseManualNavigation.md) to obtain an [IReferenceExpression](NavigateCode.md#psi-basics) instance.
61 | * The `GetReferences` method returns the list of references.
62 | * The `IReference` interface provides the `Resolve` method that allows getting a declared element from a reference.
63 | * Note that to prevent conflicts with user input during the navigation, we must obtain the read lock before calculating the node under the caret. This is done by means of the special method of the `IShellLocks` interface: `_shellLocks.QueueReadLock(...)`.
64 |
--------------------------------------------------------------------------------
/topics/PSI/References.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: References)
2 |
3 | References are a very powerful mechanism that allow any tree node to link to a declared element. The reference might be from a type name in a variable declaration, and would link to the declared element of that type. ReSharper makes ubiquitous use of references, and enables many of ReSharper's features. For example, Ctrl+Click navigation is simply a matter of following a reference, Find Usages can be performed by listing all incoming references on a declared element, and renaming can be accomplished by renaming a declared element's declaration, and all incoming references.
4 |
5 | Most powerfully, references are language agnostic - they are simply a reference from an `ITreeNode` to an `IDeclaredElement`. This allows for cross-language refactoring, navigation and analysis, e.g. a XAML file can refer to C# code, or web pages refer to JavaScript or CSS classes.
6 |
7 | A reference must be resolved before use, and can return either zero, one or more declared elements. Returning a single element means the reference is resolved successfully. When zero elements are returned, this is an error, and ReSharper will highlight the tree node that owns the reference as an error. This is likely if e.g. the reference is intended to be a method call to a method that hasn't yet been written. Resolving to more than one element typically means an error - perhaps trying to call a method overload without providing enough information as to which overload.
8 |
9 | When resolving, two values are returned for each result or candidate result - a declared element, and a *substitution*. A declared element represents a semantic view of a declaration, and cannot represent all usages. For CLR generic types, to be able to provide full information about the target of a reference, a declared element must be coupled with an instance of `ISubstitution`, which provides information for substituting type parameters for actual types. For example, a reference that targets `List` must return a declared element that represents `List` and a substitution that converts `T` into `string`. For reference targets that don't require substitutions, the `EmptySubstitution` is used.
10 |
11 | References can also provide a symbol table for completion, providing all of the candidate values that are possible at that location. For example, ASP.NET MVC support adds a reference where an MVC action can be used. The generated symbol table returns a list of known actions that are valid at that point.
12 |
13 | References can be defined directly on an `ITreeNode`, and are known as "first class references". These are references that are syntax dependent, rather than semantic. A simple example of a syntactic reference is the reference added to the type usage `Foo` in the expression `Foo f = GetFoo()`. This can be handled purely by looking at the syntax (it's obvious it's a type usage), and so can be handled by the tree node directly, and is a first class reference.
14 |
15 | ReSharper also support reference providers, which can examine the code at a higher level, and provide references based on semantic information. The MVC action sample provided above is a good example, as this requires knowing that a particular string literal argument in a method call should be the name of an MVC action.
16 |
--------------------------------------------------------------------------------
/topics/PSI/SyntaxTrees.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Abstract Syntax Trees)
2 |
3 | An [abstract syntax tree](http://en.wikipedia.org/wiki/Abstract_syntax_tree) (AST) is a data structure used to represent the contents of a file, where each node in the tree denotes a construct in the source code. For example, a node might represent a method declaration, with child nodes that provide information on accessibility, return type, method name, parameters and the method body, which itself has child nodes representing the method instructions and any nested code blocks. Equally, a node might represent whitespace, or a comment, or string literals.
4 |
5 | The PSI defines common base interfaces for creating an AST. These interfaces are shared across all languages that ReSharper supports, providing a common base for sharing information across files and languages. ReSharper provides utility methods for walking and manipulating the tree, including deleting and adding nodes and moving nodes around the tree.
6 |
7 | Each node in the tree implements the `ITreeNode` interface, and the root file node also implements the `IFile` interface. Each supported file type is parsed and an AST is constructed. The AST maps directly to the underlying text buffer, and the PSI is responsible for keeping the two in sync, updating the text buffer when the tree is manipulated, and updating the tree when the text file changes. ReSharper supports error resilient and incremental parsers, meaning a valid AST is generated even if the code is invalid, with special error nodes indicating where the syntax is incorrect, and, whenever possible, will only parse code blocks that have changed, rather than parsing the whole file. For example, when a C# method body changes, only the method body is re-parsed, and not the whole containing file.
8 |
9 | ReSharper's ASTs are based primarily on file contents, but can also work with *secondary* and *injected* ASTs, commonly referred to as secondary and injected PSIs.
10 |
11 | A secondary PSI is a PSI syntax tree built from a secondary file - an in-memory "code-behind" file generated by ReSharper from the primary code file. Areas of the secondary PSI are mapped to the original file. This is how ReSharper handles .aspx and Razor files. It maintains a primary PSI tree of the main file, but also generates an in-memory representation of the file that is generated when the .aspx or Razor template is compiled. (This generated file is referred to by ReSharper as a code-behind file, but shouldn't be confused with ASP.NET code behind files.) A second PSI tree is created for the generated C# file, and the areas of C# in the .aspx or Razor file are mapped to the equivalent areas in the generated file. Because the generated file has full context of the class it belongs to, code completion and navigation are possible, simply by mapping between the areas of the files.
12 |
13 | An injected PSI serves a different purpose. Instead of providing extra context for a whole file, or for "islands" of content within a file, it creates a new AST by parsing the contents of a single node of a host AST. For example, ReSharper 9.0 introduces support for regular expressions by creating an AST for the regular expression represented by a string literal in a C# file. The intent of injected PSIs is to handle the "embedded DSLs" of languages written inside a string literal of another language, such as regular expressions, SQL, or even Angular JS expressions.
14 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Parsing/Lexing/CachingLexers.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Caching Lexers)
2 |
3 | The root node in the PSI parse tree is `IFile`, but the implementation of this interface should also implement `IFileImpl`. This exposes properties and methods that are important for the implementation of `IFile`, one of which is `TokenBuffer`.
4 |
5 | The `TokenBuffer` property is an optional cache of the tokens in a file. If not-`null`, it contains the start and end offset, lexer state and type of all of the tokens in the file. The constructor will take in an `ILexer`, and it will immediately scan the whole file and store the processed tokens.
6 |
7 | The `CachingLexer` class implements `ILexer` on top of a `TokenBuffer`, using the tokens from this cache. Under typical use, this offers little benefit over simply using the lexer directly - a lexer is usually efficiently implemented with a series of [lookup tables](http://www.cs.man.ac.uk/~pjj/cs212/ho/node6.html). The benefit comes with incremental parsing.
8 |
9 | When a user edits a file, the PSI tree needs to be updated. To reduce the impact of this, an incremental parser will only parse the range of the file that has changed, and update the corresponding sub-tree in the PSI. For example, a change inside a C# method body will only re-parse that method body, and not the class definition or other methods in the file.
10 |
11 | Of course, if part of a file has changed and needs to be re-parsed, the underlying tokens need to be re-lexed, too. The `TokenBuffer.Rescan` method will create a new lexer and re-scan the file, returning a new instance of `TokenBuffer` with an updated cache of tokens. An incremental parser will use a `CachedLexer` that uses this `TokenBuffer` to re-parse the affected region.
12 |
13 | The `Rescan` method will try to optimise re-scanning the file and creating a new buffer of tokens. If the underlying lexer implements `IIncrementalLexer`, it will first copy the unchanged tokens at the start of the buffer, and then call `IIncrementalLexer.Start` to restart the lexer at the offset of the change, avoiding processing the unchanged part at the start of the file. This requires passing in the offset and the state of the lexer at that location, as returned by `ILexerEx.LexerStateEx` during the initial build of the token buffer cache, and stored in `TokenBuffer`. This changed section is then copied into the new `TokenBuffer`. The `TokenBuffer` will attempt to re-synchronise with the existing token buffer, and if possible, copy the tail end of the tokens into the new buffer. This means only the changed portion of the file is re-scanned, and the tokens at the start and end of the file are reused.
14 |
15 | > The `IIncrementalLexer` and `ILexerEx` interfaces are somewhat biased towards lexers created with [CsLex](CsLex.md), as the state is a `uint` value, and this is how CsLex maintains its internal state. However, the value could be used to map to another (static) value or used as bit fields to map state, as the `CSharpLexerStatePacker` class does.
16 | >
17 | {type="note"}
18 |
19 | If the underlying lexer does not implement `IIncrementalLexer`, the `Rescan` method will start the lexer from the start of the file, and re-lex the entire file, from the beginning.
20 |
21 | If a parser supports incremental parsing, it should use an instance of `CachingLexer` as its lexer - the `ToCachingLexer` extension method on `ILexer` will create this for you.
22 |
23 | More detail is provided in the section on incremental parsing.
24 |
--------------------------------------------------------------------------------
/topics/appendix/open-source-plugins.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Open-Source Plugins)
2 |
3 | When diving into plugin development, it can be very helpful to use existing plugins for reference. This list is intended to provide some representative projects:
4 |
5 | * [AgentMulder](https://github.com/ERNICommunity/AgentMulder/) – Adds navigation for types registered or resolved via Dependency Injection (DI) containers.
6 | * [Avalonia](https://github.com/ForNeVeR/AvaloniaRider) – Adds support for Avalonia including code completion, syntax highlighting, error analysis, and more.
7 | * [AWS Toolkit](https://github.com/aws/aws-toolkit-jetbrains) – Adds support for AWS resources including developing, viewing, and managing AWS Lambda functions, Amazon RDS/Redshift, Amazon S3, CloudWatch Logs, and more.
8 | * [Azure Toolkit](https://github.com/JetBrains/azure-tools-for-intellij) – Adds support for Azure resources including developing, viewing, and managing Azure Functions, Azure Storage accounts, Azure databases, and more.
9 | * [ConfigureAwaitChecker](https://github.com/aelij/ConfigureAwaitChecker/) – Adds code inspections to adhere to the `ConfigureAwait` pattern.
10 | * [CognitiveComplexity](https://github.com/matkoch/resharper-cognitivecomplexity/) – Shows cognitive complexity of members as Code Vision items and adds warnings when above threshold.
11 | * [CyclomaticComplexity](https://github.com/JetBrains/resharper-cyclomatic-complexity/) – Shows cyclomatic complexity of members as Code Vision items and adds warnings when above threshold.
12 | * [Exceptional](https://github.com/CSharpAnalyzers/ExceptionalReSharper/) – Adds analysis of thrown exceptions and code inspections for missing documentation.
13 | * [F# Support](https://github.com/JetBrains/fsharp-support) – Adds comprehensive support for F# including lexer, syntax highlighting, code completion, refactorings, and more.
14 | * [HeapAllocationsViewer](https://github.com/citizenmatt/resharper-heapview/) – Adds highlightings for various kinds of heap allocations like boxing, delegate,
15 | * [InternalsVisibleTo](https://github.com/hmemcpy/ReSharper.InternalsVisibleTo/) – Adds code completion in `InternalsVisibleTo` attributes
16 | * [PresentationAssistant](https://github.com/JetBrains/resharper-presentation-assistant/) – Shows a large window for pressed shortcuts in ReSharper.
17 | * [SerializationInspections](https://github.com/matkoch/SerializationInspections/) – Adds code inspections to adhere to serialization rules.
18 | * [SpecFlow](https://github.com/SpecFlowOSS/SpecFlow.Rider) – Adds support for SpecFlow including code completion, formatting, and test execution for `feature` and `scenario` files.
19 | * [StyleCop](https://github.com/StyleCop/StyleCop.ReSharper/) – Adds highlighting for StyleCop violations in ReSharper.
20 | * [T4 Support](https://github.com/JetBrains/ForTea) – Adds language support for T4 templates including template execution, code completion, context actions, refactorings, file structure, and more.
21 | * [TestLinker](https://github.com/matkoch/resharper-testlinker) – Adds navigation between production and test code based on naming conventions and attribute references. It also detects derived names during renaming.
22 | * [Unity Support](https://github.com/JetBrains/resharper-unity) – Adds comprehensive support for the Unity game engine including code completion, Code Vision items, YAML parsing, performance analysis, and more.
23 | * [Xao](https://github.com/hmemcpy/ReSharper.Xao/) – Adds navigation between a XAML View and its ViewModel.
24 |
--------------------------------------------------------------------------------
/topics/Platform/Platform_Zones.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Zones)
2 |
3 | Zones provide logical dependency management for features. Code can declare what Zones it requires and exports, enabling tooling to ensure correct layering, packaging and deployment. Features, implemented as Zones, can be independently licensed and disabled. Products can be created by combining Features, and multiple Products can be efficiently installed by sharing overlapping Features.
4 |
5 | ## Background
6 |
7 | Zones were introduced with ReSharper 9.0 to enable a shared binary distribution of products built on the ReSharper platform.
8 |
9 | Previously, ReSharper, dotCover, dotTrace, etc. shared a common codebase as source code. This allowed for standalone installations of the products, even allowing for different versions of the common codebase to be installed together. However, this approach causes increased resource usage when multiple products are installed in Visual Studio. The de-coupling also doesn't solve the problem of co-ordinated release schedules for integration points (e.g. dotCover needs to be updated to integrate with a new version of ReSharper's test runner).
10 |
11 | Clearly, a better strategy is to share a binary implementation of the common codebase. However, this introduces complexity when installing multiple products. Each product requires a different feature set, and it is the intersection of all features from all products that should be installed.
12 |
13 | One approach would be to install the superset of all referenced assemblies, but this can force assembly packaging decisions based on product usage, rather than for architectural reasons. For example, dotCover might require NUnit test discovery, but not the analysis and highlights for test attribute usage. Or the NUnit feature supports both C# and Visual Basic, but the user has only purchased support for C# in ReSharper. These scenarios might force the NUnit support to ship in three (or more!) separate assemblies. Trying to split assemblies based on product feature intersection would produce a combinatorial explosion of smaller assemblies, increasing maintenance costs and runtime overhead.
14 |
15 | Zones are an abstraction designed to manage this complexity by providing logical packaging based on feature sets. A component, such as Code Coverage for Unit Tests depends on the Unit Test Runner Zone being available. As long as the Unit Test Runner Zone is active, the Code Coverage for Unit Tests feature is active, and the unit test runner can now display code coverage. If the Unit Test Runner Zone isn't installed, the Code Coverage for Unit Tests feature isn't activated, and doesn't get loaded. Furthermore, if the Unit Test Runner Zone is installed, but not activated (perhaps it's not licensed), the Code Coverage for Unit Tests feature isn't activated. This is very powerful - the Unit Test Runner Zone can be available on disk, but not available to use (because the owning product isn't installed, or the feature isn't licensed). This provides the logical separation of feature sets from assembly packaging.
16 |
17 | This is implemented on top of the Component Model. Only components that are parts of installed, licensed and active Zones are enabled. Any component that isn't part of a Zone that is installed, licensed and active is not available to the application. This decouples the product from the physical packaging of components into assemblies, and allows decisions on shipping and packaging to be made for architectural and layering reasons, rather than trying to satisfy combinations of product boundaries.
18 |
--------------------------------------------------------------------------------
/topics/HowTo/ObtainComponentsInRuntime.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Obtain Components in Runtime)
2 |
3 | ## Examples
4 | * [SampleSolutionComponent.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/SolutionComponent/SampleSolutionComponent.cs)
5 | * [SolutionStateTracker.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/SolutionStateTracker/SolutionStateTracker.cs)
6 |
7 | ReSharper uses the loosely coupled design. ReSharper's [component model](Platform_ComponentModel.md) provides the ability to live load and unload new components, during runtime.
8 |
9 | Typically, you as a plugin developer should use only shell and solution components:
10 | * **Shell components** have the same lifetime as ReSharper and are marked with the `ShellComponent` attribute.
11 | * **Solution components** have the same lifetime with a solution, thus, they are created once a solution is loaded and terminated once the solution is closed. Solution components should be marked with the `SolutionComponent` attribute.
12 |
13 | So, how could you obtain your own or ReSharper components in runtime? Let's take a look at the most common scenarios.
14 |
15 | ## Constructor injection
16 | The easiest way is to use a constructor injection. All you need is to specify the required component as a constructor argument. ReSharper will care about all the dependencies on its own.
17 |
18 | For example, you have a solution component `MyClass` that should run some action upon creation. To make this happen, it must obtain an `ActionManager` instance.
19 |
20 | ```csharp
21 | [SolutionComponent]
22 | public class MyClass
23 | {
24 | public MyClass(Lifetime lifetime, IActionManager actionManager)
25 | {
26 | actionManager.ExecuteAction());
27 | }
28 | }
29 | ```
30 |
31 | Here `SomeAction` is action's name.
32 |
33 | ## Current context
34 | Sometimes, you can get components from the `IDataContext` objects. This is true, for example, for [actions](CreateMenuItemsUsingActions.md):
35 |
36 | ```csharp
37 | protected override void RunAction(IDataContext context, DelegateExecute nextExecute)
38 | {
39 | var actionManager = context.GetComponent();
40 | ...
41 | }
42 | ```
43 |
44 | ## Shell and solution component
45 | Another way is to get shell components via the `Shell` component - the root API point. This can be helpful, for example, if you want to have some "global" settings and access them from anywhere inside your plugin. To obtain the `Shell` instance, you must use its `Instance` property.
46 |
47 | ```csharp
48 | [ShellComponent]
49 | public class MySettings
50 | {
51 | public bool AutoRefresh { get; set; }
52 |
53 | public MySettings()
54 | {
55 | AutoRefresh = true;
56 | }
57 |
58 | public static MySettings Instance
59 | {
60 | get { return Shell.Instance.GetComponent(); }
61 | }
62 | }
63 | ```
64 |
65 | Thus, you can simply access them from any point of your plugin:
66 |
67 | ```csharp
68 | if (MySettings.Instance.AutoRefresh) ...
69 | ```
70 |
71 | Same is true for solution components. The main difference is that you should have an object that implements the `ISolution` interface (the one that refers to the solution currently opened in Visual Studio):
72 |
73 | ```csharp
74 | public void ObtainSomeSolutionComponent(ISolution solution)
75 | {
76 | var component = solution.GetComponent();
77 | }
78 |
79 | ...
80 |
81 | [SolutionComponent]
82 | public class SomeSolutionComponent {}
83 | ```
84 |
--------------------------------------------------------------------------------
/topics/testing/TestEnvironment.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Test Environment)
2 |
3 | ReSharper tests are functional tests, testing a complete end to end slice of ReSharper functionality, rather than a smaller unit such as a class. This is because it is impractical to try and mock an abstract syntax tree and a semantic model - it is simpler to build a real syntax tree and semantic model and exercise real functionality with the actual data model.
4 |
5 | Under normal operation, ReSharper runs as an extension to Visual Studio, but this is also impractical for testing purposes. When running tests, ReSharper is started and runs as an in-memory test environment.
6 |
7 | To create an in-memory ReSharper instance, ReSharper tests use an [NUnit setup fixture](http://nunit.org/index.php?p=setupFixture&r=2.6.3), which is a fixture class that is run once, before any tests that are in the same namespace or below are run. (E.g. the `Foo.MySetupFixture` setup fixture class is run before any tests in the `Foo` namespace or below, such as `Foo.Bar.MyTests`, are run. See the [NUnit docs for more details on setup fixtures](http://nunit.org/index.php?p=setupFixture&r=2.6.3)). This allows the fixture to set up and tear down any data required for those tests - i.e. the test environment.
8 |
9 | An extension should create a class that derives from `ExtensionTestEnvironmentAssembly` and mark it with the `[SetUpFixture]` attribute. The `TTestEnvironmentZone` type parameter is used by the test environment to decide what parts of the ReSharper platform are initialised, and available during testing. See [Zones](#zones) below for more details.
10 |
11 | > The ReSharper 9.0 SDK did not ship with the `ExtensionTestEnvironmentAssembly` class, and testing on 9.0 is not officially supported. The recommended approach is to upgrade your plugins to 9.1 or later.
12 | >
13 | {type="note"}
14 |
15 | ```csharp
16 | namespace Foo.Tests
17 | {
18 | // See Zones below
19 | [ZoneDefinition]
20 | public interface IMyTestZone : ITestsZone, IRequire
21 | {
22 | }
23 |
24 | [SetUpFixture]
25 | public class TestEnvironment : ExtensionTestEnvironmentAssembly
26 | {
27 | }
28 | }
29 | ```
30 |
31 | This is all that is necessary to create a ReSharper test environment based on the files in the output folder. The ReSharper test environment will scan all of the files in the output folder looking for components to load via the [Component Model](Platform_ComponentModel.md), which means that the plugin does not need to be installed into this in-memory ReSharper instance.
32 |
33 | ## Zones
34 |
35 | Zones are a feature that ReSharper uses to manage shipping multiple products with overlapping assemblies, features and licensing requirements. Essentially, they are used to decide what parts of the application are active. More details on the use of Zones for testing can be found in the [Testing Zones](Testing_Zones.md) section.
36 |
37 | Briefly, an extension should create a test zone definition that states what zones are required in order to run the tests. Typically, the following is sufficient. The use of the `IRequire` states that the test environment needs to run all components that have declared that they are required for testing PSI features, which includes code completion, unit testing, parsing, analysis and so on.
38 |
39 | ```csharp
40 | [ZoneDefinition]
41 | public interface IMyTestZone : ITestsZone, IRequire
42 | {
43 | }
44 |
45 | [SetUpFixture]
46 | public class TestEnvironment : ExtensionTestEnvironmentAssembly
47 | {
48 | }
49 | ```
50 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Registration/Registration_PerLanguageComponents.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Per-Language Components)
2 |
3 | ReSharper is designed to work with multiple languages and file types. It provides features that are cross language, but that require language specific implementations. For example, formatting is a feature that works across all languages, but each language must provide its own formatting rules.
4 |
5 | If these per-language implementations were implemented as shell or solution components, then any consumers would need to retrieve all implementations and filter them appropriately, either by a method on the implemented interface, or some other metadata, such as attributes.
6 |
7 | Per-language components provides this infrastructure, by creating extra component containers, for specific languages. This means there is a component container for all C# language components, or JavaScript components, and so on. These containers chain to the shell component container, so language specific components can consume any other per-language components of the same language, or any shell components. This also means that per-language components have the same lifetime as shell components.
8 |
9 | There are two types of language specific components - project file type specific, and PSI language specific, and each type has their own per-language container.
10 |
11 | ## File type specific components
12 |
13 | File type specific components are specific to a particular [Project Model file type](ProjectFileType.md). They are defined as classes that are marked with the `[ProjectFileType(...)]` attribute. The attribute will take the type of the Project Model's `ProjectFileType` for which this component is intended. For example, a component that needs to be C# specific would be marked with `[ProjectFileType(typeof(CSharpProjectFileType))]`.
14 |
15 | These file type specific components can only be retrieved using the methods on the `IProjectFileTypeServices` shell component, or by injecting into other components specific to the same file type. They can also consume shell components, and the lifetime is the same as shell components.
16 |
17 | Since project file types are hierarchical, a component can be marked with a base class project file type, and still be available when requested from a more specific file type. For example, a component marked with `[ProjectFileType(typeof(HtmlProjectFileType))]` could be returned for a consumer that wants a service for `AspProjectFileType`, since `.aspx` files "inherit" from HTML files. Of course, if there is an implementation of the requested component that is marked for `AspProjectFileType`, the more specific file type implementation is returned.
18 |
19 | ## PSI language specific components
20 |
21 | A PSI language specific component is very similar to a file type component, except the component is not specific to a Project Model file type, but to a [PSI language definition](PsiLanguageDefinition.md). These components are marked with the `[Language(...)]` attribute, where the parameter is the type of the language definition the component is specific to. For example, `[Language(typeof(CSharpLanguage))]`.
22 |
23 | To get a language specific component, the consumer should use the `ILanguageManager` shell component, or inject it into the constructor of another component that is also specific to the same language. Just like file type specific components, language specific components can consume shell components, and this means language specific components have the same lifecycle as a shell component.
24 |
25 | See the section on [per-language components](PSI_PerLanguageComponents.md) in the PSI guide for more details.
26 |
--------------------------------------------------------------------------------
/topics/Features/QuickDoc/ImplementingPresenter.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Implementing IQuickDocPresenter)
2 |
3 | Once a provider has identified an element that it can generate documentation for, it creates an instance of `IQuickDocPresenter`, which is responsible for generating the documentation. It has the following methods:
4 |
5 | ```csharp
6 | public interface IQuickDocPresenter
7 | {
8 | string GetHtml(PsiLanguageType presentationLanguage);
9 | [CanBeNull] string GetId();
10 | [CanBeNull] IQuickDocPresenter Resolve(string id);
11 | void OpenInEditor();
12 | void ReadMore();
13 | }
14 | ```
15 |
16 | The **`GetId`** method returns the ID of the current code element being displayed. This may be an XML Doc Comment ID, a simple ID, or even `null`. It is intended to be used when displaying the name of the code element, or as diagnostics in the case of failure. For example, if `GetHtml` returns null, the ID is used in a message of "no documentation available for {ID}".
17 |
18 | **`Resolve`** will create a new instance of `IQuickDocPresenter` to allow navigation from one code element to another. For example, a C# QuickDoc window for a method can show parameter and return types as hyperlinks. Clicking these will change the content of the QuickDoc view to that of the new type. Typically, this method is very similar to `IQuickDocProvider.Resolve` and some of the default providers actually call a `Resolve` overload on their creating provider. Alternatively, if it's a CLR based language, it can be deferred to an instance of `QuickDocTypeMemberProvider`, which will treat the passed in code element ID as a CLR XML Doc Comment ID. If the presenter doesn't support navigation, or cannot navigate to the item, it can return `null`, in which case, it should not add hyperlinks to the HTML.
19 |
20 | The **`OpenInEditor`** and **`ReadMore`** methods are called in response to the "go to" or "read more" hyperlinks added to the default HTML template. When the user clicks the hyperlink, the current presenter's `Resolve` method is called to find the presenter for the target, and the new presenter's `OpenInEditor` or `ReadMore` method is called. `OpenInEditor` is also called if the user holds down `Ctrl` when clicking a type definition hyperlink.
21 |
22 | `ReadMore` is expected to open further documentation. It can do this with a simple call to `Process.Start`, passing in a URL to spawn the system browser, or using the `HelpSystem` component to display product or MSDN documentation (again extensible by implementing `IShowHelp`).
23 |
24 | The most important method is **`GetHtml`**. The string returned from this method is displayed verbatim in a web browser control. If the current code element doesn't have any documentation, or the documentation cannot be created, this method should return `null`, in which case a fallback message, such as "no documentation available for {ID}" is displayed.
25 |
26 | > It is the responsibility of the `IQuickDocPresenter` to ensure the HTML is properly sanitised before display (see [RSRP-186295](http://youtrack.jetbrains.com/issue/RSRP-186295) for a great reason why!). Using the helper classes mentioned below can help with this, particularly `XmlDocPresenterUtil.EscapeHtmlString`
27 | >
28 | {type="note"}
29 |
30 | ReSharper provides a couple of classes to help build the HTML - **`XmlDocHtmlUtil`** and **`XmlDocHtmlPresenter`**. Typically, the presenter will generate the HTML by calling `XmlDocHtmlPresenter.Run` which in turn calls methods on `XmlDocHtmlUtil`, such as `XmlDocHtmlUtil.BuildHtml`, although the presenter is free to call `XmlDocHtmlUtil` directly, or create the HTML itself. It is, however, recommended to use the helper classes).
31 |
--------------------------------------------------------------------------------
/topics/HowTo/CreateContextAction/CreateContextAction.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Create a Context Action)
2 |
3 | **What you should know beforehand:**
4 | * [PSI](NavigateCode.md#psi-basics)
5 |
6 | **Examples ([?](HowTo_HowTo.md#sample-solution)):**
7 | * [ToLowerCaseContextAction.cs](https://github.com/JetBrains/sample-resharper-plugin/blob/master/SampleReSharperPlugin/src/ContextAction/ToLowerCaseContextAction.cs)
8 |
9 | The purpose of context actions is to quickly introduce a minor change to the code, like changing access modifiers, convert `foreach` to `for`, and so on. When a context action is available for the current caret position, ReSharper displays the "hummer"  action indicator. The list of possible context actions is displayed after a user presses Alt+Enter.
10 |
11 | 
12 |
13 | For example, let's create a very simple context action that will be applicable to variable declarations. If a variable name contains any character in uppercase, the context action will suggest to convert the name to lowercase (of course, from the point of functionality, such action is absolutely useless).
14 |
15 | ```csharp
16 | [ContextAction(Name = "ToLowerCase", Description = "Convert the text to lowercase", Group = "C#", Disabled = false,
17 | Priority = 1)]
18 | public class ToLowerCaseContextAction : ContextActionBase
19 | {
20 | private readonly IVariableDeclaration _nodeUnderCaret;
21 |
22 | public ToLowerCaseContextAction(LanguageIndependentContextActionDataProvider dataProvider)
23 | {
24 | _nodeUnderCaret = dataProvider.GetSelectedElement();
25 | }
26 |
27 |
28 | protected override Action ExecutePsiTransaction(ISolution solution, IProgressIndicator progress)
29 | {
30 | return textControl =>
31 | {
32 | var newText = _nodeUnderCaret.DeclaredName.ToLower();
33 | RenameRefactoringService.Rename(solution,
34 | new RenameDataProvider((IDeclaredElement) _nodeUnderCaret, newText), textControl);
35 | };
36 | }
37 |
38 | public override string Text => "Convert to lowercase";
39 |
40 | public override bool IsAvailable(IUserDataHolder cache)
41 | {
42 | var nodeText = _nodeUnderCaret?.DeclaredName;
43 | var containsUpperCase = nodeText != null && nodeText.Any(char.IsUpper);
44 | return containsUpperCase;
45 | }
46 | }
47 | ```
48 |
49 | ## Notes
50 | * The easiest way to create a context action is to inherit from the `ContextActionBase` class.
51 | * The context action class must be marked with the `ContextAction` attribute:
52 | * `Group` defines the scope of the action (C# files in our case).
53 | * `Disabled` specifies whether the action is disabled by default.
54 | * `Priority` sets the position of the action in the actions list.
55 | * The context data provider `LanguageIndependentContextActionDataProvider` obtained in the constructor provides a super-helpful method `GetSelectedElement` that returns the tree node under the caret. The provider has also methods that allow you to get current offset, selection range and so on.
56 | * The `Text` property defines the text that will be shown in the actions list.
57 | * `IsAvailable` is used to check whether the action is available for the current caret position. If `false`, the action is not shown in the list of possible context actions.
58 | * `ExecutePsiTransaction` returns the action that is executed when the context action is selected.
59 | * Note that we use `RenameRefactoringService` to change variable's name. The service performs seamless renaming of a variable everywhere in the code.
60 |
--------------------------------------------------------------------------------
/topics/Intro/key_topics.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Key Topics)
2 |
3 | The ReSharper Platform is very large, and very capable, and its size can initially be very daunting. This page is intended to list the key topics that a plugin author would be interested in, and provide quick links to the most common extension points.
4 |
5 | ## Essential concepts
6 |
7 | * [Getting Started](getting_started.md) with extensions and plugins.
8 | * [Architectural overview](Architecture_Overview.md) - a brief tour of the different layers of the ReSharper Platform.
9 | * [Lifetime management](Lifetime.md) - discusses the `Lifetime` class, which is key to lifetime management and used throughout the Platform.
10 | * [Component Model](Platform_ComponentModel.md) - ReSharper is very much a component based application. All services and components are exported and must be imported in order to be consumed. This allows for a very loose coupled architecture, and is instrumental to making ReSharper very extensible. To get the most out of it requires some understanding of how the component model works, and how it relates to lifetime management.
11 | * [Zones](Platform_Zones.md) - the ReSharper Platform's shared binary distribution raises issues about shipping mechanisms (i.e. how to ship a component that is used by one product configuration but not another). Zones manage this by partitioning components into logical feature sets. Extension providers **must** understand how this works in order to correctly import and export components.
12 |
13 | ## The code model
14 |
15 | ReSharper's code model is called the PSI - the Program Structure Interface. The key topics here are:
16 |
17 | * [Overview](PSI_Overview.md)
18 | * [Abstract syntax trees](SyntaxTrees.md) - files are parsed and abstract syntax trees are generated, as you type.
19 | * [Declared elements](DeclaredElements.md) - declared elements are the root interfaces for ReSharper's semantic view of the code.
20 | * [References](References.md) - a very powerful mechanism to allow abstract syntax trees to have an outgoing references to a declared element, that is, to link syntax nodes, such as type names, to the semantic item they refer to.
21 | * [Type Systems](TypeSystems2.md) - modelling type usage, based on the semantic view of the code given by declared elements.
22 |
23 | These are the core building blocks of the PSI, although it has more functionality, including caching, searching and control flow analysis. The PSI section has more details.
24 |
25 | ## Common extension points
26 |
27 | ReSharper is extremely extensible. It is a heavily component based application, and is designed to follow the Open Closed Principle to allow for such extensibility. Most features and services can be extended, but some common extension points are:
28 |
29 | * [Daemons and daemon stages](Daemons.md) - code analysis, as you type. Displays "squiggly" warnings in your code.
30 | * [Actions](Actions.md) - menu items, and toolbar items.
31 | * [Quick-Fixes and Context Actions](QuickFixes.md) - extending the Alt+Enter menu.
32 | * [Code Completion](Completion.md) - extend the code completion menus.
33 | * [Reference Providers](ReferenceProviders.md) - apply references from an arbitrary abstract syntax tree node to another code element, such as supporting code completion and navigation from string literals to class or property names.
34 | * [Generate Menu](GenerateMenu.md) - add items to the Generate menu.
35 | * [Navigation](Navigation.md) - extend navigation.
36 | * [Options Pages](OptionsPages.md) - add your own options pages.
37 | * [Code Cleanup](CodeCleanup.md) - participate in code cleanup.
38 | * [Live Templates](LiveTemplates.md) - add macros for Live Templates.
39 | * [Refactoring](Refactoring.md) - add your own refactorings.
40 |
--------------------------------------------------------------------------------
/topics/Intro/about.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: About This Guide)
2 |
3 |
4 |
5 | Introduction and summary overview of contents.
6 |
7 | This guide is split into several parts, similar to a textbook.
8 | Each one builds on the content of the previous section, but it is not necessary to read the guide in order.
9 | The [Key Topics](key_topics.md) page aims to link to the pages that are necessary to be able to understand the architecture and get started building plugins.
10 |
11 | All source links and reference lists target ReSharper Platform %sdk-version%.
12 |
13 | > While browsing this guide, you will notice that there are topics that are greyed out.
14 | > Unfortunately, the guide is not complete and contains placeholders for specific topics.
15 | > We are working on increasing the coverage, but if you get stuck due to missing content, please see the [](getting_help.md) section for details on how to get moving again.
16 | >
17 | > The guide is also [Open Source on GitHub](%guide-repo%), and Pull Requests for new content, corrections or updates are always gratefully received.
18 | > Please see the [Contributing](_CONTRIBUTING.md) page for details.
19 | >
20 | {type="note"}
21 |
22 | [//]: # (> See also [Glossary]() for a handy reference of common terms.)
23 | [//]: # (>)
24 | [//]: # ({type="tip"})
25 |
26 | #### Part I — Plugins
27 |
28 | Describes how to create a plugin that can extend the ReSharper Platform.
29 | Includes details on how to set up the project, update to new versions of the ReSharper Platform, and how to package, deploy, and test your plugins.
30 |
31 | #### Part II — Platform
32 |
33 | Describes the foundational layer of the architecture, which provides many features and utilities, such as the component model, the user interface, documents and editors, settings, threading, zoning, and background tasks.
34 | The Platform layer mainly comprises the functionality of the ReSharper Platform that does not target language features or parsing.
35 |
36 | #### Part III — Project Model
37 |
38 | Documents the Project Model, which represents the files and configuration of the currently loaded solution, as well as the build system used to build the project.
39 |
40 | #### Part IV — PSI
41 |
42 | The Program Structure Interface (PSI) builds the syntactic and semantic models for lots of different file types.
43 | This section describes how to work with the PSI, navigating and manipulating the syntax trees, and also looks at the powerful reference system, which allows a syntax tree node to reference an item in the semantic model.
44 |
45 | #### Part V — Features
46 |
47 | Describes how to extend and interact with various features that use the PSI layer, such as code completion, navigation, Alt+Enter items, context actions, refactorings, and more.
48 | See also the section on Custom Languages below for language-specific features that are only applicable when adding support for a new language.
49 |
50 | #### Part VI — Testing
51 |
52 | Describes the available infrastructure for writing automated tests covering the functionality of plugins.
53 |
54 | #### Part VII — Custom Languages
55 |
56 | This section describes how to add support to the ReSharper Platform for a new language that isn't supported by default, creating parsers, syntactic and semantic models, and all the features that build on top.
57 |
58 | #### Part VIII — Product Specific
59 |
60 | A lot of the functionalities in the ReSharper Platform are product agnostic.
61 | This section describes product-specific features, such as specific project model differences and how to target them in a plugin.
62 |
--------------------------------------------------------------------------------
/topics/PSI/SyntaxTrees/ManualNavigation.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Manually Navigating a Syntax Tree)
2 |
3 | Manually walking a syntax tree is the lowest level means of navigation, and involves walking the nodes using the properties defined on `ITreeNode`.
4 |
5 | > Generally speaking, you should prefer to use [strongly typed navigation](StronglyTypedNavigation.md) or the visitor pattern to walk and process the tree. Failing that, you should use the `TreeNodeExtensions` helper methods that have implemented the boilerplate tree walking code for you.
6 | >
7 | {type="note"}
8 |
9 |
10 |
11 | ### Walking up the tree
12 |
13 | You can walk up the tree using the `Parent` property. This is very useful for finding the context that the current node is in - for example, you can walk the `Parent` property of a method invocation to see if the invocation is happening inside a method declaration that is async or not.
14 |
15 | To walk the `Parent` property, you will want to write code like this:
16 |
17 | ```csharp
18 | while(currentNode != null)
19 | {
20 | // Process node
21 | currentNode = currentNode.Parent;
22 | }
23 | ```
24 |
25 | ### Walking sibling nodes
26 |
27 | Since a file is parsed into a tree structure, nodes have siblings as well as children. For example, a C# file can have a class declaration that contains multiple methods. Each method is represented by an `IMethodDeclaration` node. Intuitively, each method is a child of the class, and therefore are siblings, and no method is higher or lower in the tree than any other.
28 |
29 | > Even though the method declarations will be siblings, they are not going to be direct siblings. The syntax tree is a full-fidelity representation of the C# file, which means the whitespace and comments between the method declarations are also added as nodes in the tree, and these will be siblings to the method declarations.
30 | >
31 | {type="note"}
32 |
33 | You can walk the siblings with code like this:
34 |
35 | ```csharp
36 | while(currentNode != null)
37 | {
38 | // Process node
39 | currentNode = currentNode.NextSibling;
40 | }
41 | ```
42 |
43 | Obviously the code to walk the sibling chain in reverse is just the same, but using the `PrevSibling` property.
44 |
45 | ### Walking down the tree
46 |
47 | Walking down the tree is very similar to walking the sibling chain. Again, since this is a tree structure a single node can have multiple children. For example, a C# file's list of `using` statements is represented by an `IUsingList` node, and this will have multiple children - multiple instances of `IUsingNamespaceDirective` (with each child again separated by whitespace nodes).
48 |
49 | To walk the immediate children of a node, you'll want to write code like this:
50 |
51 | ```csharp
52 | public void WalkChildren(ITreeNode root)
53 | {
54 | var child = root.FirstChild;
55 | while(child != null)
56 | {
57 | // Process child node
58 | child = child.NextSibling;
59 | }
60 | }
61 | ```
62 |
63 | Note that we start with `FirstChild` but then walk that child's siblings. To walk the children in reverse order, start with `LastChild`, and walk `PrevSibling`.
64 |
65 | If you want to walk all descendants of a node, simply recursively walk a child node's children.
66 |
67 | > While you do need to recursively walk the structure (walk a child node's children, then it's children, etc.), beware of an implementation that uses recursion to accomplish this. Recursion can run into problems with a very deeply nested syntax tree. It is better to iteratively walk the tree than to use recursion.
68 | >
69 | > Even better, you should avoid writing your own methods for walking the tree at all, and make use of the `TreeNodeVisitor` or `IRecursiveElementProcessor` patterns that ReSharper implements. Failing that, use the `TreeNodeExtensions` helper methods.
70 |
--------------------------------------------------------------------------------
/topics/CustomLanguages/Registration/Registration_Testing.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Testing)
2 |
3 | Testing language registration is fairly quick and easy. It's mostly checking that the Component Model has loaded the types correctly. This means the tests need to derive from `BaseTest`, so that the environment and Component Model has been initialised, but a solution hasn't been created.
4 |
5 | Testing the `IProjectFileLanguageService` and PSI `LanguageService` implementations is not so straightforward. It's better to test them indirectly, by testing other functionality such as lexing, parsing, and so on.
6 |
7 | ## Testing project file type definition
8 |
9 | To test if a project file type has been registered correctly, you can query the file type from `IProjectFileTypes`, or check that the `INSTANCE` field has been set to a non-`null` value.
10 |
11 | If `IProjectFileLanguageService` has been implemented, you can also check that `IProjectFileExtensions` returns the correct project file type for a given file extension.
12 |
13 | It's also useful to include a test marked `[Explicit]`, that doesn't normally run, and will dump all of the known project file types for debugging purposes.
14 |
15 | > It's likely that a project file type test is one of the first tests implemented in a test project. Make sure that the test project includes a proper assembly reference, so that the Component Model will load the components from the assembly under test.
16 | >
17 | {type="note"}
18 |
19 | ```csharp
20 | [TestFixture]
21 | public class MyProjectFileTypeTests : BaseTest
22 | {
23 | [Test]
24 | public void ProjectFileTypeIsRegistered()
25 | {
26 | // This line ensures that if this is the first test, there is at least one
27 | // reference to the assembly under test. If there are no references, the
28 | // Component Model doesn't know to use the assembly under test. The
29 | // reference to MyProjectFileType.Name doesn't count, as it's a const.
30 | Assert.NotNull(MyProjectFileType.Instance);
31 |
32 | var projectFileTypes = Shell.Instance.GetComponent();
33 | Assert.NotNull(projectFileTypes.GetFileType(MyProjectFileType.Name));
34 | }
35 |
36 | [Test]
37 | public void ProjectFileTypeFromExtension()
38 | {
39 | // This requires IProjectFileTypeLanguageService to be implemented, otherwise
40 | // ReSharper returns UnknownProjectFileType.INSTANCE
41 | var projectFileExtensions = Shell.Instance.GetComponent();
42 | Assert.AreSame(MyProjectFileType.Instance, projectFileExtensions.GetFileType(MyProjectFileType.MY_EXTENSION));
43 | }
44 |
45 | [Test, Explicit]
46 | public void DumpProjectFileTypes()
47 | {
48 | var projectFileTypes = Shell.Instance.GetComponent();
49 | foreach (var projectFileType in projectFileTypes.All)
50 | {
51 | Console.WriteLine(projectFileType.PresentableName);
52 | }
53 | }
54 | }
55 | ```
56 |
57 | ## Testing the PSI language service registration
58 |
59 | To test the PSI language service, simply check the language's `Instance` static field is not null, and check that ReSharper's `Languages` class can retrieve the language by name.
60 |
61 | Again, it's useful to have a test marked `[Explicit]` that will print all of the registered languages names for debugging.
62 |
63 | ```csharp
64 | [TestFixture]
65 | public class MyLanguageTests : BaseTest
66 | {
67 | [Test]
68 | public void LanguageIsRegistered()
69 | {
70 | Assert.NotNull(MyLanguage.Instance);
71 | Assert.NotNull(Languages.Instance.GetLanguageByName(MyLanguage.Name));
72 | }
73 |
74 | [Test, Explicit]
75 | public void DumpLanguages()
76 | {
77 | foreach (var languageType in Languages.Instance.All)
78 | {
79 | Console.WriteLine(languageType.PresentableName);
80 | }
81 | }
82 | }
83 | ```
84 |
--------------------------------------------------------------------------------
/topics/Features/QuickDoc/ImplementingProvider.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Implementing IQuickDocProvider)
2 |
3 | The `IQuickDocProvider` interface provides two methods:
4 |
5 | ```csharp
6 | public interface IQuickDocProvider
7 | {
8 | bool CanNavigate(IDataContext context);
9 | void Resolve(IDataContext context, Action resolved);
10 | }
11 | ```
12 |
13 | **`CanNavigate`** is called to see if the provider can generate documentation based on the given `IDataContext`. If it returns true, no other providers are checked. If it returns false, the `QuickDocManager` continues to other providers.
14 |
15 | The provider queries the passed in `IDataContext` to find data that it needs to provide documentation. This might be using `DataConstants.DOCUMENT` and `DataConstants.DOCUMENT_OFFSET` to get the current document and offset, in order to get the PSI tree node at the text caret location, or it might be using `DataConstants.DECLARED_ELEMENTS` to get the `IDeclaredElement` at the text caret. The requirements here depend on what the provider wants to document. (See `IDataContext` for more details.)
16 |
17 | **`Resolve`** is called by the `QuickDocManager` when initially displaying the documentation (the name makes more sense when dealing with navigation from one presenter to another). The `IDataContext` is passed in, from which the provider should extract whatever data is required in order to be able to display documentation, and this data is used to create an instance of `IQuickDocPresenter`. The provider then retrieves the `PsiLanguageType` of the item being documented, and calls the passed in `resolved` action. (This action, provided by `ShowQuickDocAction`, is responsible for creating and managing the popup window and the web browser used to host the HTML).
18 |
19 | > Retrieving the language can be done using the document from the `IDataContext`, and passing it, together with instances of `DocumentManager` and `ISolution` (injected into the constructor of your component) to the `PresentationUtil.GetPresentationLanguageByContainer` method:
20 | >
21 | > ```csharp
22 | > var document = context.GetData(DataConstants.DOCUMENT);
23 | > if (document != null)
24 | > projectFile = myDocumentManager.TryGetProjectFile(document);
25 | >
26 | > var defaultLanguage = PresentationUtil.GetPresentationLanguageByContainer(projectFile, mySolution);
27 | > resolved(presenter, defaultLanguage);
28 | > ```
29 | >
30 | {type="note"}
31 |
32 | You need to decorate your `IQuickDocProvider` class with `QuickDocProviderAttribute`, and pass a priority into the constructor. The list of providers maintained by `QuickDocManager` is an ordered list, with the lowest priority being at the start of the list (any new items being added to the `QuickDocManager`'s `IViewable` are inserted in the correct position in the list). The majority of the default providers have a priority of `0`. You only need to provide a higher or lower priority if the items you're intending to document are also handled by the default providers, and you wish to override or provide a fallback.
33 |
34 | ```csharp
35 | public class QuickDocProviderAttribute : SolutionComponentAttribute
36 | {
37 | public QuickDocProviderAttribute(int priority);
38 | public int Priority { get; }
39 | }
40 | ```
41 |
42 | > If an `IQuickDocProvider` or `IQuickDocPresenter` is displaying the QuickDoc information for an instance of `IDeclaredElement`, they should not store the declared element as a field, as the presenter can last longer than the lifetime of the declared element. E.g. if the QuickDoc window is pinned, and the text of the file is edited, the declared element may become invalid.
43 | >
44 | > Instead, the presenter should create a `DeclaredElementEnvoy`, which can both cache the presentation of the element, and recreate a valid element, with a call to `GetValidDeclaredElement`.
45 |
--------------------------------------------------------------------------------
/topics/Features/Refactoring.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Refactoring)
2 |
3 | Refactorings are one of the most powerful features of ReSharper, but also the most complicated. A refactoring can be triggered from a variety of events (e.g., from a simple edit or deliberate invocation) and can result in all sorts of operations, some involving just local code, others involving the project (e.g., renaming a file) or changing multiple files in many projects.
4 |
5 | At the most simple level, a refactoring consists of three things:
6 |
7 | * The workflow
8 | * The workflow provider
9 | * The refactoring itself
10 |
11 | Let's take a look at the way these components are defined.
12 |
13 | ## Workflow
14 |
15 | The workflow, as its name suggests, is a class which orchestrates the workflow during which the user may (or may not) perform the refactoring. Most refactorings are _driven_, meaning that the user has to go through menus which present, e.g., conflicts that this refactoring would create.
16 |
17 | In the simplest terms, a refactoring is a class which inherits from `DrivenRefactoringWorflow`. This class has quite a few members, most of which perform fairly obvious function.
18 |
19 | Execution of the workflow happens in the `PreExecute`, `Execute` and `PostExecute` methods. All of these, as well as other methods such as `IsAvailable`, return a `bool` value indicating whether this step is a success. If any of these returns `false`, the whole transaction is rolled back and no refactorings take place.
20 |
21 | ## Workflow provider
22 |
23 | The workflow provider is a class which provides workflows for ReSharper to consume. It is a class that
24 |
25 | * Implements the `IRefactorignWorkflowProvider` interface
26 | * Is decorated with `[RefactoringWorkflowProvider]` attribute
27 |
28 | The class has a single method - `CreateWorkflow()` that returns an `IEnumerable` of one or more workflows that you may wish to provide. Here is a typical example:
29 |
30 | ```csharp
31 | [RefactoringWorkflowProvider]
32 | public class MakeSingletonProvider : IRefactoringWorkflowProvider
33 | {
34 | public IEnumerable CreateWorkflow(IDataContext dataContext)
35 | {
36 | var solution = dataContext.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);
37 | yield return new MakeSingletonWorkflow(solution, "MakeSingleton");
38 | }
39 | }
40 | ```
41 |
42 | The constructor parameter passed into the workflow is an action ID, which is also useful if you want to expose the refactoring as an ordinary action.
43 |
44 | ## The refactoring
45 |
46 | One of the methods we forgot to mention in the workflow is the `CreateRefactoring()` method. This method is used to put together the refactoring worflow and the refactoring _driver_ - i.e., the element which drives the refactoring to completion.
47 |
48 | Thus, the refactoring itself is typically a class (let's call it `C`) inheriting from `DrivenRefactoring`, where `Workflow` corresponds to the refactoring workflow, and `Refactoring` corresponds to a type of `RefactoringExecBase`.
49 |
50 | ```csharp
51 | public class MakeSingletonRefactoring
52 | : DrivenRefactoring>
55 | {
56 | public MakeSingletonRefactoring(MakeSingletonWorkflow workflow, ISolution solution, IRefactoringDriver driver)
57 | : base(workflow, solution, driver)
58 | {
59 | }
60 |
61 | public override bool Execute(IProgressIndicator pi)
62 | {
63 | return true;
64 | }
65 | }
66 | ```
67 |
68 | The refactoring itself has the capability of dealing with cases where a particular refactoring is not supported on a ReSharper-supported language. For example, a particular C# refactoring might not be supported in VB, so usages after the change will not be updated. The number of such refactorings in ReSharper itself is really small, but it is likely you might need this functionality if your refactoring is, e.g., C#-only.
69 |
--------------------------------------------------------------------------------
/topics/PSI/Generating/Code.md:
--------------------------------------------------------------------------------
1 | [//]: # (title: Generating Code)
2 |
3 | If you plan to write plug-ins that generate code, it's important to understand how to use ReSharper to create new code elements and insert them into existing types.
4 |
5 | Depending on the situation, you will most likely encounter two usage patterns:
6 |
7 | * One element needs to be replaced by another. This is typically achieved by either calling the `ReplaceBy()` method on the element to be replaced or, if this method is not available, by physically removing one element and adding another.
8 | * An element needs to be inserted as a child of another element. In this case, there is typically a method in the API for doing exactly that.
9 |
10 | ## Element factory
11 |
12 | The Element Factory is a class which is used to manufacture all types of entities, be it statements or whole declarations. The element factory is created via a `GetInstance()` method, which is supplied the corresponding `PsiModule`:
13 |
14 | ```csharp
15 | var factory = CSharpElementFactory.GetInstance(provider.PsiModule);
16 | ```
17 |
18 | Having acquired the element factory, you can now use it to manufacture various objects by invoking one of its methods. For example, to create a simple statement, you would write the following simple piece of code:
19 |
20 | ```csharp
21 | ICSharpStatement st = factory.CreateStatement("int x = 0;", EmptyArray