├── .gitattributes
├── .gitignore
├── Directory.Build.props
├── Directory.Build.targets
├── InheritanceMargin.sln
├── LICENSE.txt
├── PreviewLarge.png
├── README.md
├── Reference
├── Microsoft.CodeAnalysis.EditorFeatures.Text.dll
└── SharedKey.snk
├── TunnelVisionLabs.InheritanceMargin.ruleset
├── Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy
├── CSharpInheritanceAnalyzer.cs
├── CSharpMemberIdentifierEqualityComparer.cs
├── MemberTarget.cs
├── RoslynMemberTarget.cs
├── RoslynTypeTarget.cs
├── SpecializedMatchingMemberCollector.cs
├── Tvl.VisualStudio.InheritanceMargin.CSharp.11.0.csproj
├── Tvl.VisualStudio.InheritanceMargin.CSharp.12.0.csproj
├── TypeCollector.cs
├── TypeDeclarationNodeSelector.cs
└── TypeTarget.cs
├── Tvl.VisualStudio.InheritanceMargin.CSharp
├── AbstractTarget.cs
├── BackgroundParser.cs
├── CSharpInheritanceAnalyzer.cs
├── MemberTarget.cs
├── Properties
│ └── AssemblyInfo.cs
├── Tvl.VisualStudio.InheritanceMargin.CSharp.14.0.csproj
├── Tvl.VisualStudio.InheritanceMargin.CSharp.15.0.csproj
├── Tvl.VisualStudio.InheritanceMargin.CSharp.16.0.csproj
├── Tvl.VisualStudio.InheritanceMargin.CSharp.17.0.csproj
├── Tvl.VisualStudio.InheritanceMargin.CSharp.Roslyn.csproj
└── TypeTarget.cs
├── Tvl.VisualStudio.InheritanceMargin.Interfaces
├── IInheritanceParser.cs
├── IInheritanceTag.cs
├── IInheritanceTagFactory.cs
├── IInheritanceTarget.cs
├── InheritanceGlyph.cs
├── InheritanceParseResultEventArgs.cs
├── MefBindingWorkaround.cs
├── Properties
│ └── AssemblyInfo.cs
└── Tvl.VisualStudio.InheritanceMargin.Interfaces.csproj
├── Tvl.VisualStudio.InheritanceMargin
├── CSharpInheritanceTagger.cs
├── CSharpInheritanceTaggerProvider.cs
├── CommandTranslation
│ ├── CommandId.cs
│ ├── CommandRouter.cs
│ └── CommandTargetParameters.cs
├── InheritanceGlyphFactory.cs
├── InheritanceGlyphFactoryProvider.cs
├── InheritanceGlyphMouseHandler.cs
├── InheritanceGlyphMouseHandlerProvider.cs
├── InheritanceMargin.vsct
├── InheritanceMarginConstants.cs
├── InheritanceMarginPackage.cs
├── InheritanceTag.cs
├── InheritanceTagFactory.cs
├── Properties
│ ├── AssemblyInfo.cs
│ └── launchSettings.json
├── ProvideBindingPathAttribute.cs
├── Resources
│ ├── has-implementations.png
│ ├── implements.png
│ ├── is-overridden.png
│ ├── override-is-overridden-combined.png
│ ├── override-is-overridden-combined2.png
│ └── overrides.png
├── RoslynUtilities.cs
├── Tvl.VisualStudio.InheritanceMargin.csproj
├── VSIXImage_large.png
├── VSIXImage_small.png
├── VSPackage.resx
└── source.extension.vsixmanifest
├── appveyor.yml
├── global.json
├── stylecop.json
└── version.json
/.gitattributes:
--------------------------------------------------------------------------------
1 | * text=auto
2 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Per-user files
2 | *.csproj.user
3 | *.suo
4 |
5 | # Temporary files created by the IDE
6 | .vs/
7 |
8 | # NuGet packages
9 | packages/
10 |
11 | # Build output
12 | bin/
13 | obj/
14 |
--------------------------------------------------------------------------------
/Directory.Build.props:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | true
6 | full
7 |
8 |
9 |
10 | pdbonly
11 |
12 |
13 |
14 | true
15 | $(MSBuildThisFileDirectory)TunnelVisionLabs.InheritanceMargin.ruleset
16 | true
17 | $(MSBuildThisFileDirectory)Reference\SharedKey.snk
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 | Tunnel Vision Laboratories, LLC
27 | Copyright © Sam Harwell 2014
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/Directory.Build.targets:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/InheritanceMargin.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.28315.86
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{3E5B8C5F-AEEB-484A-80C8-F5660CB8FA27}"
7 | ProjectSection(SolutionItems) = preProject
8 | appveyor.yml = appveyor.yml
9 | LICENSE.txt = LICENSE.txt
10 | README.md = README.md
11 | stylecop.json = stylecop.json
12 | TunnelVisionLabs.InheritanceMargin.ruleset = TunnelVisionLabs.InheritanceMargin.ruleset
13 | EndProjectSection
14 | EndProject
15 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin", "Tvl.VisualStudio.InheritanceMargin\Tvl.VisualStudio.InheritanceMargin.csproj", "{C5BE4BE1-F167-4D34-980A-1A2F83C5D74A}"
16 | EndProject
17 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.Interfaces", "Tvl.VisualStudio.InheritanceMargin.Interfaces\Tvl.VisualStudio.InheritanceMargin.Interfaces.csproj", "{F4B709E6-8926-42E6-914A-749CB473F37B}"
18 | EndProject
19 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.11.0", "Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy\Tvl.VisualStudio.InheritanceMargin.CSharp.11.0.csproj", "{2ACB7340-8400-4D5D-8624-A4E7FE8FC474}"
20 | EndProject
21 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.12.0", "Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy\Tvl.VisualStudio.InheritanceMargin.CSharp.12.0.csproj", "{FBB6E057-77DA-4FF6-A867-EF741971E511}"
22 | EndProject
23 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.Roslyn", "Tvl.VisualStudio.InheritanceMargin.CSharp\Tvl.VisualStudio.InheritanceMargin.CSharp.Roslyn.csproj", "{912F988E-C5D9-413A-9B81-86D0AA67947B}"
24 | EndProject
25 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.14.0", "Tvl.VisualStudio.InheritanceMargin.CSharp\Tvl.VisualStudio.InheritanceMargin.CSharp.14.0.csproj", "{7D84BB06-4C50-4EB4-ABD5-71C63B0C2409}"
26 | EndProject
27 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.15.0", "Tvl.VisualStudio.InheritanceMargin.CSharp\Tvl.VisualStudio.InheritanceMargin.CSharp.15.0.csproj", "{A3EBBB23-61F7-4A28-9179-59221875B713}"
28 | EndProject
29 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.16.0", "Tvl.VisualStudio.InheritanceMargin.CSharp\Tvl.VisualStudio.InheritanceMargin.CSharp.16.0.csproj", "{10788A42-FFD8-4FDD-9F78-34860257D008}"
30 | EndProject
31 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Tvl.VisualStudio.InheritanceMargin.CSharp.17.0", "Tvl.VisualStudio.InheritanceMargin.CSharp\Tvl.VisualStudio.InheritanceMargin.CSharp.17.0.csproj", "{FC878788-4674-4975-B90F-7CCFF33E32D5}"
32 | EndProject
33 | Global
34 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
35 | Debug|Any CPU = Debug|Any CPU
36 | Release|Any CPU = Release|Any CPU
37 | EndGlobalSection
38 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
39 | {C5BE4BE1-F167-4D34-980A-1A2F83C5D74A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
40 | {C5BE4BE1-F167-4D34-980A-1A2F83C5D74A}.Debug|Any CPU.Build.0 = Debug|Any CPU
41 | {C5BE4BE1-F167-4D34-980A-1A2F83C5D74A}.Release|Any CPU.ActiveCfg = Release|Any CPU
42 | {C5BE4BE1-F167-4D34-980A-1A2F83C5D74A}.Release|Any CPU.Build.0 = Release|Any CPU
43 | {F4B709E6-8926-42E6-914A-749CB473F37B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
44 | {F4B709E6-8926-42E6-914A-749CB473F37B}.Debug|Any CPU.Build.0 = Debug|Any CPU
45 | {F4B709E6-8926-42E6-914A-749CB473F37B}.Release|Any CPU.ActiveCfg = Release|Any CPU
46 | {F4B709E6-8926-42E6-914A-749CB473F37B}.Release|Any CPU.Build.0 = Release|Any CPU
47 | {2ACB7340-8400-4D5D-8624-A4E7FE8FC474}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
48 | {2ACB7340-8400-4D5D-8624-A4E7FE8FC474}.Debug|Any CPU.Build.0 = Debug|Any CPU
49 | {2ACB7340-8400-4D5D-8624-A4E7FE8FC474}.Release|Any CPU.ActiveCfg = Release|Any CPU
50 | {2ACB7340-8400-4D5D-8624-A4E7FE8FC474}.Release|Any CPU.Build.0 = Release|Any CPU
51 | {FBB6E057-77DA-4FF6-A867-EF741971E511}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
52 | {FBB6E057-77DA-4FF6-A867-EF741971E511}.Debug|Any CPU.Build.0 = Debug|Any CPU
53 | {FBB6E057-77DA-4FF6-A867-EF741971E511}.Release|Any CPU.ActiveCfg = Release|Any CPU
54 | {FBB6E057-77DA-4FF6-A867-EF741971E511}.Release|Any CPU.Build.0 = Release|Any CPU
55 | {912F988E-C5D9-413A-9B81-86D0AA67947B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
56 | {912F988E-C5D9-413A-9B81-86D0AA67947B}.Debug|Any CPU.Build.0 = Debug|Any CPU
57 | {912F988E-C5D9-413A-9B81-86D0AA67947B}.Release|Any CPU.ActiveCfg = Release|Any CPU
58 | {912F988E-C5D9-413A-9B81-86D0AA67947B}.Release|Any CPU.Build.0 = Release|Any CPU
59 | {7D84BB06-4C50-4EB4-ABD5-71C63B0C2409}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
60 | {7D84BB06-4C50-4EB4-ABD5-71C63B0C2409}.Debug|Any CPU.Build.0 = Debug|Any CPU
61 | {7D84BB06-4C50-4EB4-ABD5-71C63B0C2409}.Release|Any CPU.ActiveCfg = Release|Any CPU
62 | {7D84BB06-4C50-4EB4-ABD5-71C63B0C2409}.Release|Any CPU.Build.0 = Release|Any CPU
63 | {A3EBBB23-61F7-4A28-9179-59221875B713}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
64 | {A3EBBB23-61F7-4A28-9179-59221875B713}.Debug|Any CPU.Build.0 = Debug|Any CPU
65 | {A3EBBB23-61F7-4A28-9179-59221875B713}.Release|Any CPU.ActiveCfg = Release|Any CPU
66 | {A3EBBB23-61F7-4A28-9179-59221875B713}.Release|Any CPU.Build.0 = Release|Any CPU
67 | {10788A42-FFD8-4FDD-9F78-34860257D008}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
68 | {10788A42-FFD8-4FDD-9F78-34860257D008}.Debug|Any CPU.Build.0 = Debug|Any CPU
69 | {10788A42-FFD8-4FDD-9F78-34860257D008}.Release|Any CPU.ActiveCfg = Release|Any CPU
70 | {10788A42-FFD8-4FDD-9F78-34860257D008}.Release|Any CPU.Build.0 = Release|Any CPU
71 | {FC878788-4674-4975-B90F-7CCFF33E32D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
72 | {FC878788-4674-4975-B90F-7CCFF33E32D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
73 | {FC878788-4674-4975-B90F-7CCFF33E32D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
74 | {FC878788-4674-4975-B90F-7CCFF33E32D5}.Release|Any CPU.Build.0 = Release|Any CPU
75 | EndGlobalSection
76 | GlobalSection(SolutionProperties) = preSolution
77 | HideSolutionNode = FALSE
78 | EndGlobalSection
79 | GlobalSection(ExtensibilityGlobals) = postSolution
80 | SolutionGuid = {E2CC4FE1-7257-44CA-B677-9A80EDFCDE0B}
81 | EndGlobalSection
82 | EndGlobal
83 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) Tunnel Vision Laboratories, LLC
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/PreviewLarge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunnelvisionlabs/InheritanceMargin/7c3ebf3d71d0185d8b6f74a4b4c1c99f3f9217e6/PreviewLarge.png
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Inheritance Margin extension for Visual Studio 2012+
2 |
3 | [](https://ci.appveyor.com/project/sharwell/inheritancemargin/branch/master)
4 |
5 | This extension adds inheritance glyphs to the glyph margin in the Visual Studio text editor. Glyphs are displayed for the following items:
6 |
7 | * Interface methods/properties/events which are implemented by the current item
8 | * Virtual methods/properties/events in base classes which are overridden by the current item
9 | * Types which extend or implement the current type
10 | * For interfaces:
11 | * Methods/properties/events in derived types which implement the current item
12 | * Interfaces which extend the current interface
13 | * Classes which implement the current interface
14 | * For base classes:
15 | * Methods/properties/events in derived types which override the current item
16 | * Classes which extend the current class
17 |
18 | 
19 |
20 | ## Limitations
21 |
22 | * **C# only:** The current version only supports C#. In the future, I plan to support other languages via other MEF extensions.
23 | * **Updates while you type:** The glyphs for a file are only updated when that file is opened and when text in that file changes. If changes in open files are not being reflected, you can either close and reopen the affected file or type in the file to force an update.
24 | * **ReSharper users:** ReSharper provides its own version of a similar feature, so this extension isn't necessary for ReSharper users.
25 |
26 | I've tested this extension in one of my reasonably large projects (44 projects, 2000+ C# source files), and the extension should never impact the performance of the editor. Depending on the complexity of the current file (size, number of classes/methods, number of derived classes, etc), it may take several seconds for the glyphs to update after the file is opened or text is changed. During this time you should be able to work like normal. If you experience text editor slowdowns due to this extension, please [let us know](https://github.com/tunnelvisionlabs/InheritanceMargin/issues) and we'll work to correct it.
27 |
--------------------------------------------------------------------------------
/Reference/Microsoft.CodeAnalysis.EditorFeatures.Text.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunnelvisionlabs/InheritanceMargin/7c3ebf3d71d0185d8b6f74a4b4c1c99f3f9217e6/Reference/Microsoft.CodeAnalysis.EditorFeatures.Text.dll
--------------------------------------------------------------------------------
/Reference/SharedKey.snk:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/tunnelvisionlabs/InheritanceMargin/7c3ebf3d71d0185d8b6f74a4b4c1c99f3f9217e6/Reference/SharedKey.snk
--------------------------------------------------------------------------------
/TunnelVisionLabs.InheritanceMargin.ruleset:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/CSharpInheritanceAnalyzer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Linq;
9 | using System.Runtime.InteropServices;
10 | using System.Threading.Tasks;
11 | using Microsoft.RestrictedUsage.CSharp.Compiler;
12 | using Microsoft.RestrictedUsage.CSharp.Compiler.IDE;
13 | using Microsoft.RestrictedUsage.CSharp.Core;
14 | using Microsoft.RestrictedUsage.CSharp.Extensions;
15 | using Microsoft.RestrictedUsage.CSharp.Semantics;
16 | using Microsoft.RestrictedUsage.CSharp.Syntax;
17 | using Microsoft.VisualStudio.Shell;
18 | using Microsoft.VisualStudio.Text;
19 | using Microsoft.VisualStudio.Text.Editor;
20 | using Microsoft.VisualStudio.Text.Tagging;
21 | using Tvl.VisualStudio.OutputWindow.Interfaces;
22 | using CSRPOSDATA = Microsoft.VisualStudio.CSharp.Services.Language.Interop.CSRPOSDATA;
23 | using ICSharpTextBuffer = Microsoft.VisualStudio.CSharp.Services.Language.Interop.ICSharpTextBuffer;
24 | using ILangService = Microsoft.VisualStudio.CSharp.Services.Language.Interop.ILangService;
25 | using IProject = Microsoft.VisualStudio.CSharp.Services.Language.Interop.IProject;
26 | using Stopwatch = System.Diagnostics.Stopwatch;
27 | using StringBuilder = System.Text.StringBuilder;
28 |
29 | internal class CSharpInheritanceAnalyzer : BackgroundParser
30 | {
31 | private readonly SVsServiceProvider _serviceProvider;
32 | private readonly IInheritanceTagFactory _tagFactory;
33 |
34 | public CSharpInheritanceAnalyzer(ITextView textView, ITextBuffer textBuffer, TaskScheduler taskScheduler, ITextDocumentFactoryService textDocumentFactoryService, IOutputWindowService outputWindowService, SVsServiceProvider serviceProvider, IInheritanceTagFactory tagFactory)
35 | : base(textBuffer, taskScheduler, textDocumentFactoryService, outputWindowService)
36 | {
37 | if (serviceProvider == null)
38 | throw new ArgumentNullException("serviceProvider");
39 |
40 | _serviceProvider = serviceProvider;
41 | _tagFactory = tagFactory;
42 | textView.Closed += (sender, e) => Dispose();
43 | }
44 |
45 | ///
46 | public override string Name
47 | {
48 | get
49 | {
50 | return "C# Inheritance Analyzer";
51 | }
52 | }
53 |
54 | [DllImport("CSLangSvc.dll", PreserveSig = false)]
55 | internal static extern void LangService_GetInstance(out ILangService langService);
56 |
57 | public static Tuple ResolveMemberIdentifier(IEnumerable projectList, CSharpMemberIdentifier memberId)
58 | {
59 | return Resolve(projectList, project => project.ResolveMemberIdentifier(memberId), memberId.AssemblyIdentifier);
60 | }
61 |
62 | public static Tuple ResolveTypeIdentifier(IEnumerable projectList, CSharpTypeIdentifier typeId)
63 | {
64 | return Resolve(projectList, project => project.ResolveTypeIdentifier(typeId), typeId.AssemblyIdentifier);
65 | }
66 |
67 | public static Tuple Resolve(IEnumerable compilations, Func resolver, CSharpAssemblyIdentifier definingAssembly)
68 | where T : class
69 | {
70 | Compilation compilation = null;
71 | T result = default(T);
72 | foreach (Compilation c in compilations)
73 | {
74 | T t = resolver(c);
75 | if (t != null)
76 | {
77 | result = t;
78 | compilation = c;
79 | }
80 |
81 | if (c.MainAssembly.SymbolicIdentifier.Equals(definingAssembly))
82 | {
83 | return Tuple.Create(t, c);
84 | }
85 | }
86 |
87 | if (compilation != null && result != null)
88 | {
89 | return Tuple.Create(result, compilation);
90 | }
91 |
92 | return null;
93 | }
94 |
95 | public static void NavigateToType(CSharpTypeIdentifier typeIdentifier)
96 | {
97 | bool result = false;
98 | try
99 | {
100 | CSharpType currentType = ResolveType(typeIdentifier);
101 | if (currentType == null)
102 | return;
103 |
104 | var sourceLocations = currentType.SourceLocations;
105 | if (sourceLocations == null || sourceLocations.Count == 0)
106 | return;
107 |
108 | var location = sourceLocations[0];
109 | if (location.FileName == null || !location.Position.IsValid)
110 | return;
111 |
112 | CSRPOSDATA position = new CSRPOSDATA()
113 | {
114 | LineIndex = location.Position.Line,
115 | ColumnIndex = location.Position.Character
116 | };
117 |
118 | ILangService languageService;
119 | CSharpInheritanceAnalyzer.LangService_GetInstance(out languageService);
120 | if (languageService == null)
121 | return;
122 |
123 | IProject project = null;
124 | languageService.OpenSourceFile(project, location.FileName.Value, position);
125 | }
126 | catch (ApplicationException)
127 | {
128 | ////_callHierarchy.LanguageService.DisplayErrorMessage(exception.Message);
129 | return;
130 | }
131 | catch (InvalidOperationException)
132 | {
133 | ////this._callHierarchy.LanguageService.DisplayErrorMessage(exception2.Message);
134 | return;
135 | }
136 |
137 | if (!result)
138 | {
139 | ////NativeMessageId.Create(this._callHierarchy.LanguageService, jrc_StringResource_identifiers.IDS_HIDDEN_DEFINITION, new object[0]).DisplayError(this._callHierarchy.LanguageService);
140 | }
141 | }
142 |
143 | public static void NavigateToMember(CSharpMemberIdentifier memberIdentifier)
144 | {
145 | bool result = false;
146 | try
147 | {
148 | CSharpMember currentMember = ResolveMember(memberIdentifier);
149 | if (currentMember == null)
150 | return;
151 |
152 | var sourceLocations = currentMember.SourceLocations;
153 | if (sourceLocations == null || sourceLocations.Count == 0)
154 | return;
155 |
156 | var location = sourceLocations[0];
157 | if (location.FileName == null || !location.Position.IsValid)
158 | return;
159 |
160 | CSRPOSDATA position = new CSRPOSDATA()
161 | {
162 | LineIndex = location.Position.Line,
163 | ColumnIndex = location.Position.Character
164 | };
165 |
166 | ILangService languageService;
167 | CSharpInheritanceAnalyzer.LangService_GetInstance(out languageService);
168 | if (languageService == null)
169 | return;
170 |
171 | IProject project = null;
172 | languageService.OpenSourceFile(project, location.FileName.Value, position);
173 | }
174 | catch (ApplicationException)
175 | {
176 | ////_callHierarchy.LanguageService.DisplayErrorMessage(exception.Message);
177 | return;
178 | }
179 | catch (InvalidOperationException)
180 | {
181 | ////this._callHierarchy.LanguageService.DisplayErrorMessage(exception2.Message);
182 | return;
183 | }
184 |
185 | if (!result)
186 | {
187 | ////NativeMessageId.Create(this._callHierarchy.LanguageService, jrc_StringResource_identifiers.IDS_HIDDEN_DEFINITION, new object[0]).DisplayError(this._callHierarchy.LanguageService);
188 | }
189 | }
190 |
191 | private static CSharpType ResolveType(CSharpTypeIdentifier memberIdentifier)
192 | {
193 | IDECompilerHost host = new IDECompilerHost();
194 | var currentCompilations = host.Compilers.Select(i => i.GetCompilation()).ToList();
195 | var resolved = ResolveTypeIdentifier(currentCompilations, memberIdentifier);
196 | if (resolved != null)
197 | return resolved.Item1;
198 |
199 | return null;
200 | }
201 |
202 | private static CSharpMember ResolveMember(CSharpMemberIdentifier memberIdentifier)
203 | {
204 | IDECompilerHost host = new IDECompilerHost();
205 | var currentCompilations = host.Compilers.Select(i => i.GetCompilation()).ToList();
206 | var resolved = ResolveMemberIdentifier(currentCompilations, memberIdentifier);
207 | if (resolved != null)
208 | return resolved.Item1;
209 |
210 | return null;
211 | }
212 |
213 | ///
214 | /// If is a , this method selects
215 | /// all children of . Otherwise,
216 | /// this method returns a collection containing itself.
217 | ///
218 | /// The node.
219 | ///
220 | /// If is a , this method returns
221 | /// . Otherwise, this method returns
222 | /// a collection containing itself.
223 | ///
224 | private static IEnumerable SelectDeclaratorsFromFields(ParseTreeNode node)
225 | {
226 | FieldDeclarationNode fieldDeclarationNode = node as FieldDeclarationNode;
227 | if (fieldDeclarationNode == null)
228 | return Enumerable.Repeat(node, 1);
229 |
230 | return fieldDeclarationNode.VariableDeclarators;
231 | }
232 |
233 | ///
234 | protected override void ReParseImpl()
235 | {
236 | Stopwatch stopwatch = Stopwatch.StartNew();
237 |
238 | ITextSnapshot snapshot = TextBuffer.CurrentSnapshot;
239 |
240 | try
241 | {
242 | ITextDocument textDocument = TextDocument;
243 | string fileName = textDocument != null ? textDocument.FilePath : null;
244 | IDECompilerHost host = new IDECompilerHost();
245 | IProject project = null;
246 |
247 | ILangService languageService;
248 | LangService_GetInstance(out languageService);
249 | if (languageService != null)
250 | {
251 | ICSharpTextBuffer csharpBuffer = languageService.FindTextBuffer(fileName);
252 | if (csharpBuffer != null)
253 | project = csharpBuffer.Project;
254 | }
255 |
256 | List> tags = new List>();
257 |
258 | if (host != null && project != null && !string.IsNullOrEmpty(fileName))
259 | {
260 | Compilation compilation = host.CreateCompiler(project).GetCompilation();
261 | SourceFile sourceFile;
262 | if (!compilation.SourceFiles.TryGetValue(new FileName(fileName), out sourceFile))
263 | {
264 | InheritanceParseResultEventArgs errorResult = new InheritanceParseResultEventArgs(snapshot, stopwatch.Elapsed, tags);
265 | OnParseComplete(errorResult);
266 | return;
267 | }
268 |
269 | ParseTree parseTree = sourceFile.GetParseTree();
270 |
271 | SpecializedMatchingMemberCollector collector = new SpecializedMatchingMemberCollector(host.Compilers.Select(i => i.GetCompilation()), false);
272 |
273 | IEnumerable nodes = SelectTypes(parseTree);
274 | foreach (var node in nodes)
275 | {
276 | CSharpType type = null;
277 |
278 | type = compilation.GetTypeFromTypeDeclaration(node);
279 | if (type == null)
280 | {
281 | MarkDirty(true);
282 | return;
283 | }
284 |
285 | if (type.IsSealed)
286 | continue;
287 |
288 | // types which implement or derive from this type
289 | ISet derivedClasses = collector.GetDerivedTypes(type.SymbolicIdentifier);
290 |
291 | if (derivedClasses.Count == 0)
292 | continue;
293 |
294 | StringBuilder builder = new StringBuilder();
295 | string elementKindDisplayName =
296 | "types";
297 |
298 | builder.AppendLine("Derived " + elementKindDisplayName + ":");
299 | foreach (var derived in derivedClasses)
300 | builder.AppendLine(" " + derived.GetFullTypeName());
301 |
302 | int nameIndex = node.Token;
303 | Token token = parseTree.LexData.Tokens[nameIndex];
304 | ITextSnapshotLine line = snapshot.GetLineFromLineNumber(token.StartPosition.Line);
305 | SnapshotSpan span = new SnapshotSpan(snapshot, new Span(line.Start + token.StartPosition.Character, token.EndPosition.Character - token.StartPosition.Character));
306 |
307 | InheritanceGlyph tag = type.IsInterface ? InheritanceGlyph.HasImplementations : InheritanceGlyph.Overridden;
308 |
309 | var targets = derivedClasses.Select(i => new TypeTarget(i.GetFullTypeName(), i.SymbolicIdentifier));
310 | tags.Add(new TagSpan(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets)));
311 | }
312 |
313 | nodes = parseTree.SelectMethodsPropertiesAndFields();
314 | nodes = nodes.SelectMany(SelectDeclaratorsFromFields);
315 | foreach (var node in nodes)
316 | {
317 | if (node is AccessorDeclarationNode)
318 | {
319 | // these nodes always result in an ArgumentException in GetMemberFromMemberDeclaration
320 | continue;
321 | }
322 |
323 | CSharpMember member;
324 | try
325 | {
326 | member = compilation.GetMemberFromMemberDeclaration(node);
327 | }
328 | catch (ArgumentException)
329 | {
330 | continue;
331 | }
332 |
333 | if (member == null)
334 | {
335 | MarkDirty(true);
336 | return;
337 | }
338 |
339 | if (!SpecializedMatchingMemberCollector.IsSupportedMemberType(member))
340 | continue;
341 |
342 | // methods which this method implements
343 | ISet implementedMethods = collector.GetImplementedInterfaceMembers(member.SymbolicIdentifier);
344 |
345 | // methods which this method overrides
346 | ISet overriddenMethods = collector.GetOverriddenBaseMembers(member.SymbolicIdentifier);
347 |
348 | // methods which override this method
349 | ISet overridingMethods = collector.GetOverridersFromDerivedTypes(member.SymbolicIdentifier);
350 |
351 | // methods which implement this method
352 | ISet implementingMethods = collector.GetImplementorsForInterfaceMember(member.SymbolicIdentifier);
353 |
354 | if (implementingMethods.Count == 0 && implementedMethods.Count == 0 && overriddenMethods.Count == 0 && overridingMethods.Count == 0)
355 | continue;
356 |
357 | StringBuilder builder = new StringBuilder();
358 | string elementKindDisplayName =
359 | member.IsProperty ? "properties" :
360 | member.IsEvent ? "events" :
361 | "methods";
362 |
363 | if (implementedMethods.Count > 0)
364 | {
365 | builder.AppendLine("Implemented " + elementKindDisplayName + ":");
366 | foreach (var methodId in implementedMethods)
367 | builder.AppendLine(" " + methodId.ToString());
368 | }
369 |
370 | if (overriddenMethods.Count > 0)
371 | {
372 | builder.AppendLine("Overridden " + elementKindDisplayName + ":");
373 | foreach (var methodId in overriddenMethods)
374 | builder.AppendLine(" " + methodId.ToString());
375 | }
376 |
377 | if (implementingMethods.Count > 0)
378 | {
379 | builder.AppendLine("Implementing " + elementKindDisplayName + " in derived types:");
380 | foreach (var methodId in implementingMethods)
381 | builder.AppendLine(" " + methodId.ToString());
382 | }
383 |
384 | if (overridingMethods.Count > 0)
385 | {
386 | builder.AppendLine("Overriding " + elementKindDisplayName + " in derived types:");
387 | foreach (var methodId in overridingMethods)
388 | builder.AppendLine(" " + methodId.ToString());
389 | }
390 |
391 | int nameIndex = node.Token;
392 | Token token = parseTree.LexData.Tokens[nameIndex];
393 | ITextSnapshotLine line = snapshot.GetLineFromLineNumber(token.StartPosition.Line);
394 | SnapshotSpan span = new SnapshotSpan(snapshot, new Span(line.Start + token.StartPosition.Character, token.EndPosition.Character - token.StartPosition.Character));
395 |
396 | InheritanceGlyph tag;
397 | if (implementedMethods.Count > 0)
398 | {
399 | if (overridingMethods.Count > 0)
400 | tag = InheritanceGlyph.ImplementsAndOverridden;
401 | else if (implementingMethods.Count > 0)
402 | tag = InheritanceGlyph.ImplementsAndHasImplementations;
403 | else
404 | tag = InheritanceGlyph.Implements;
405 | }
406 | else if (implementingMethods.Count > 0)
407 | {
408 | tag = InheritanceGlyph.HasImplementations;
409 | }
410 | else if (overriddenMethods.Count > 0)
411 | {
412 | if (overridingMethods.Count > 0)
413 | tag = InheritanceGlyph.OverridesAndOverridden;
414 | else
415 | tag = InheritanceGlyph.Overrides;
416 | }
417 | else
418 | {
419 | tag = InheritanceGlyph.Overridden;
420 | }
421 |
422 | List members = new List();
423 | members.AddRange(implementedMethods);
424 | members.AddRange(overriddenMethods);
425 | members.AddRange(implementingMethods);
426 | members.AddRange(overridingMethods);
427 |
428 | var targets = members.Select(i => new MemberTarget(i));
429 | tags.Add(new TagSpan(span, _tagFactory.CreateTag(tag, builder.ToString().TrimEnd(), targets)));
430 | }
431 | }
432 |
433 | InheritanceParseResultEventArgs result = new InheritanceParseResultEventArgs(snapshot, stopwatch.Elapsed, tags);
434 | OnParseComplete(result);
435 | }
436 | catch (InvalidOperationException)
437 | {
438 | MarkDirty(true);
439 | throw;
440 | }
441 | }
442 |
443 | private IEnumerable SelectTypes(ParseTree parseTree)
444 | {
445 | if (parseTree == null)
446 | return Enumerable.Empty();
447 |
448 | return new TypeCollector(parseTree.RootNode);
449 | }
450 |
451 | private IEnumerable FindHideBySigMethod(CSharpType type, CSharpMember member, bool checkBaseTypes, bool includeInheritedInterfaces)
452 | {
453 | List results = new List();
454 | FindHideBySigMethod(results, type, member, checkBaseTypes, includeInheritedInterfaces);
455 | return results;
456 | }
457 |
458 | private void FindHideBySigMethod(List results, CSharpType type, CSharpMember member, bool checkBaseTypes, bool includeInheritedInterfaces)
459 | {
460 | foreach (var potential in type.Members)
461 | {
462 | if (!member.IsSameSignature(potential))
463 | continue;
464 |
465 | results.Add(potential);
466 | }
467 |
468 | if (checkBaseTypes)
469 | {
470 | CSharpType baseType = type.BaseClass;
471 | if (baseType != null)
472 | FindHideBySigMethod(results, baseType, member, checkBaseTypes, includeInheritedInterfaces);
473 | }
474 |
475 | if (includeInheritedInterfaces)
476 | {
477 | IList interfaces = type.BaseInterfaces;
478 | if (interfaces != null)
479 | {
480 | foreach (CSharpType interfaceType in interfaces.OfType())
481 | FindHideBySigMethod(results, interfaceType, member, checkBaseTypes, includeInheritedInterfaces);
482 | }
483 | }
484 | }
485 |
486 | private List GetTypeDeclarationNodes(ParseTree parseTree)
487 | {
488 | TypeDeclarationNodeSelector collector = new TypeDeclarationNodeSelector();
489 | collector.Visit(parseTree.RootNode);
490 | return collector.Nodes;
491 | }
492 | }
493 | }
494 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/CSharpMemberIdentifierEqualityComparer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System.Collections.Generic;
7 | using Microsoft.RestrictedUsage.CSharp.Semantics;
8 |
9 | internal class CSharpMemberIdentifierEqualityComparer : IEqualityComparer
10 | {
11 | ///
12 | public bool Equals(CSharpMemberIdentifier left, CSharpMemberIdentifier right)
13 | {
14 | if (object.ReferenceEquals(left, right))
15 | return true;
16 |
17 | if (object.ReferenceEquals(left, null) || object.ReferenceEquals(right, null))
18 | return false;
19 |
20 | return left.Equals(right);
21 | }
22 |
23 | ///
24 | public int GetHashCode(CSharpMemberIdentifier identifier)
25 | {
26 | return identifier.GetHashCode();
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/MemberTarget.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using Microsoft.RestrictedUsage.CSharp.Semantics;
7 |
8 | internal sealed class MemberTarget : IInheritanceTarget
9 | {
10 | private readonly CSharpMemberIdentifier _memberIdentifier;
11 |
12 | public MemberTarget(CSharpMemberIdentifier memberIdentifier)
13 | {
14 | _memberIdentifier = memberIdentifier;
15 | }
16 |
17 | ///
18 | public string DisplayName
19 | {
20 | get
21 | {
22 | return _memberIdentifier.ToString();
23 | }
24 | }
25 |
26 | ///
27 | public void NavigateTo()
28 | {
29 | CSharpInheritanceAnalyzer.NavigateToMember(_memberIdentifier);
30 | }
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/RoslynMemberTarget.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | #if ROSLYN
5 |
6 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
7 | {
8 | using Microsoft.CodeAnalysis;
9 | using Microsoft.CodeAnalysis.Text;
10 |
11 | internal sealed class MemberTarget : IInheritanceTarget
12 | {
13 | private readonly SourceTextContainer _textContainer;
14 | private readonly ISymbol _memberIdentifier;
15 | private readonly Project _project;
16 | private readonly Solution _solution;
17 |
18 | public MemberTarget(SourceTextContainer textContainer, ISymbol memberIdentifier, Project project, Solution solution)
19 | {
20 | _textContainer = textContainer;
21 | _memberIdentifier = memberIdentifier;
22 | _project = project;
23 | _solution = solution;
24 | }
25 |
26 | public string DisplayName
27 | {
28 | get
29 | {
30 | return _memberIdentifier.ToString();
31 | }
32 | }
33 |
34 | public void NavigateTo()
35 | {
36 | CSharpInheritanceAnalyzer.NavigateToSymbol(_textContainer, _memberIdentifier, _project);
37 | }
38 | }
39 | }
40 |
41 | #endif
42 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/RoslynTypeTarget.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | #if ROSLYN
5 |
6 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
7 | {
8 | using Microsoft.CodeAnalysis;
9 | using Microsoft.CodeAnalysis.Text;
10 |
11 | internal sealed class TypeTarget : IInheritanceTarget
12 | {
13 | private readonly SourceTextContainer _textContainer;
14 | private readonly ISymbol _typeIdentifier;
15 | private readonly Solution _solution;
16 |
17 | public TypeTarget(SourceTextContainer textContainer, ISymbol typeIdentifier, Solution solution)
18 | {
19 | _textContainer = textContainer;
20 | _typeIdentifier = typeIdentifier;
21 | _solution = solution;
22 | }
23 |
24 | public string DisplayName
25 | {
26 | get
27 | {
28 | return _typeIdentifier.ToString();
29 | }
30 | }
31 |
32 | public void NavigateTo()
33 | {
34 | CSharpInheritanceAnalyzer.NavigateToSymbol(_textContainer, _typeIdentifier, _solution.GetProject(_typeIdentifier.ContainingAssembly));
35 | }
36 | }
37 | }
38 |
39 | #endif
40 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/SpecializedMatchingMemberCollector.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System.Collections.Generic;
7 | using Microsoft.RestrictedUsage.CSharp.Compiler;
8 | using Microsoft.RestrictedUsage.CSharp.Semantics;
9 | using Microsoft.RestrictedUsage.CSharp.Utilities;
10 | using Microsoft.VisualStudio.CSharp.Services.Language.Refactoring;
11 |
12 | internal class SpecializedMatchingMemberCollector : MatchingMemberCollector
13 | {
14 | public SpecializedMatchingMemberCollector(IEnumerable allProjects, bool searchOverloads)
15 | : base(allProjects, searchOverloads)
16 | {
17 | }
18 |
19 | public static new bool IsSupportedMemberType(CSharpMember member)
20 | {
21 | return MatchingMemberCollector.IsSupportedMemberType(member);
22 | }
23 |
24 | public ISet GetImplementedInterfaceMembers(CSharpMemberIdentifier memberId)
25 | {
26 | CSharpMember member = CSharpInheritanceAnalyzer.ResolveMemberIdentifier(AllProjects, memberId).Item1;
27 | ISet resultList = CreateHashSet(new CSharpMemberIdentifierEqualityComparer());
28 | if (!IsSupportedMemberType(member))
29 | return resultList;
30 |
31 | AddImplementedInterfaceMembers(member, resultList);
32 | return resultList;
33 | }
34 |
35 | public ISet GetImplementorsForInterfaceMember(CSharpMemberIdentifier memberId)
36 | {
37 | CSharpMember member = CSharpInheritanceAnalyzer.ResolveMemberIdentifier(AllProjects, memberId).Item1;
38 | ISet resultList = CreateHashSet(new CSharpMemberIdentifierEqualityComparer());
39 | if (!IsSupportedMemberType(member))
40 | return resultList;
41 |
42 | AddImplementorsForInterfaceMember(member, resultList);
43 | return resultList;
44 | }
45 |
46 | public ISet GetOverriddenBaseMembers(CSharpMemberIdentifier memberId)
47 | {
48 | CSharpMember member = CSharpInheritanceAnalyzer.ResolveMemberIdentifier(AllProjects, memberId).Item1;
49 | ISet resultList = CreateHashSet(new CSharpMemberIdentifierEqualityComparer());
50 | if (!IsSupportedMemberType(member))
51 | return resultList;
52 |
53 | AddOverridenBaseMembers(member, resultList);
54 | return resultList;
55 | }
56 |
57 | public ISet GetOverridersFromDerivedTypes(CSharpMemberIdentifier memberId)
58 | {
59 | CSharpMember member = CSharpInheritanceAnalyzer.ResolveMemberIdentifier(AllProjects, memberId).Item1;
60 | ISet resultList = CreateHashSet(new CSharpMemberIdentifierEqualityComparer());
61 | if (!IsSupportedMemberType(member))
62 | return resultList;
63 |
64 | AddVirtualOverridersFromDerivedTypes(member, resultList);
65 | return resultList;
66 | }
67 |
68 | public ISet GetDerivedTypes(CSharpTypeIdentifier typeId)
69 | {
70 | ISet result = new HashSet();
71 | foreach (Compilation compilation in AllProjects)
72 | {
73 | CSharpType baseType = compilation.ResolveTypeIdentifier(typeId);
74 | if (baseType == null)
75 | continue;
76 |
77 | BaseTypeCollector collector = baseType.IsInterface ? GetBaseInterfaceCollector() : GetBaseClassCollector();
78 | foreach (CSharpType type in compilation.MainAssembly.Types)
79 | {
80 | // an interface can't be derived from a class
81 | if (type.IsInterface && !baseType.IsInterface)
82 | continue;
83 |
84 | var baseTypes = collector.GetBaseTypes(type);
85 | if (baseType.TypeParameters != null && baseType.TypeParameters.Count > 0)
86 | {
87 | foreach (var candidate in baseTypes)
88 | {
89 | if (Equals(baseType, candidate.DefiningType))
90 | {
91 | result.Add(type);
92 | break;
93 | }
94 | }
95 | }
96 | else
97 | {
98 | if (baseTypes.Contains(baseType))
99 | result.Add(type);
100 | }
101 | }
102 | }
103 |
104 | return result;
105 | }
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/Tvl.VisualStudio.InheritanceMargin.CSharp.11.0.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | obj\vs2012\
5 | obj\vs2012\
6 |
7 |
8 |
9 |
10 |
11 | net45
12 | Tvl.VisualStudio.InheritanceMargin.CSharp
13 |
14 | bin\vs2012\$(Configuration)\
15 | $(DefaultItemExcludes);obj/vs2013/**
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/Tvl.VisualStudio.InheritanceMargin.CSharp.12.0.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | obj\vs2013\
5 | obj\vs2013\
6 |
7 |
8 |
9 |
10 |
11 | net45
12 | Tvl.VisualStudio.InheritanceMargin.CSharp
13 |
14 | bin\vs2013\$(Configuration)\
15 | $(DefaultItemExcludes);obj/vs2012/**
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/TypeCollector.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System.Collections.Generic;
7 | using Microsoft.RestrictedUsage.CSharp.Syntax;
8 | using IEnumerable = System.Collections.IEnumerable;
9 | using IEnumerator = System.Collections.IEnumerator;
10 |
11 | internal class TypeCollector : ParseTreeVisitor, IEnumerable
12 | {
13 | private readonly List _nodes = new List();
14 |
15 | public TypeCollector(ParseTreeNode node)
16 | {
17 | Visit(node);
18 | }
19 |
20 | ///
21 | public IEnumerator GetEnumerator()
22 | {
23 | return _nodes.GetEnumerator();
24 | }
25 |
26 | ///
27 | IEnumerator IEnumerable.GetEnumerator()
28 | {
29 | return GetEnumerator();
30 | }
31 |
32 | ///
33 | public override bool TraverseInteriorTree(ParseTreeNode node)
34 | {
35 | return false;
36 | }
37 |
38 | ///
39 | public override void VisitAccessorDeclarationNode(AccessorDeclarationNode node)
40 | {
41 | // Types cannot be declared in an accessor, so we stop here
42 | }
43 |
44 | ///
45 | public override void VisitConstructorDeclarationNode(ConstructorDeclarationNode node)
46 | {
47 | // Types cannot be declared in a constructor, so we stop here
48 | }
49 |
50 | ///
51 | public override void VisitDelegateDeclarationNode(DelegateDeclarationNode node)
52 | {
53 | }
54 |
55 | ///
56 | public override void VisitEnumMemberDeclarationNode(EnumMemberDeclarationNode node)
57 | {
58 | }
59 |
60 | ///
61 | public override void VisitFieldDeclarationNode(FieldDeclarationNode node)
62 | {
63 | }
64 |
65 | ///
66 | public override void VisitMemberDeclarationNode(MemberDeclarationNode node)
67 | {
68 | }
69 |
70 | ///
71 | public override void VisitMethodDeclarationNode(MethodDeclarationNode node)
72 | {
73 | }
74 |
75 | ///
76 | public override void VisitNamespaceDeclarationNode(NamespaceDeclarationNode node)
77 | {
78 | VisitList(node.NamespaceMemberDeclarations);
79 | }
80 |
81 | ///
82 | public override void VisitNestedTypeDeclarationNode(NestedTypeDeclarationNode node)
83 | {
84 | Visit(node.Type);
85 | }
86 |
87 | ///
88 | public override void VisitOperatorDeclarationNode(OperatorDeclarationNode node)
89 | {
90 | }
91 |
92 | ///
93 | public override void VisitParseTreeNode(ParseTreeNode node)
94 | {
95 | }
96 |
97 | ///
98 | public override void VisitPropertyDeclarationNode(PropertyDeclarationNode node)
99 | {
100 | }
101 |
102 | ///
103 | public override void VisitTypeDeclarationNode(TypeDeclarationNode node)
104 | {
105 | _nodes.Add(node);
106 |
107 | for (MemberDeclarationNode node2 = node.MemberDeclarations; node2 != null; node2 = node2.Next)
108 | {
109 | Visit(node2);
110 | }
111 | }
112 | }
113 | }
114 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/TypeDeclarationNodeSelector.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System.Collections.Generic;
7 | using Microsoft.RestrictedUsage.CSharp.Syntax;
8 |
9 | internal class TypeDeclarationNodeSelector : ParseTreeVisitor
10 | {
11 | private readonly List _nodes = new List();
12 |
13 | public List Nodes
14 | {
15 | get
16 | {
17 | return _nodes;
18 | }
19 | }
20 |
21 | ///
22 | public override bool TraverseInteriorTree(ParseTreeNode node)
23 | {
24 | return false;
25 | }
26 |
27 | ///
28 | public override void VisitTypeDeclarationNode(TypeDeclarationNode node)
29 | {
30 | _nodes.Add(node);
31 | base.VisitTypeDeclarationNode(node);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp.Legacy/TypeTarget.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using Microsoft.RestrictedUsage.CSharp.Semantics;
7 |
8 | internal sealed class TypeTarget : IInheritanceTarget
9 | {
10 | private readonly string _displayName;
11 | private readonly CSharpTypeIdentifier _typeIdentifier;
12 |
13 | public TypeTarget(string displayName, CSharpTypeIdentifier typeIdentifier)
14 | {
15 | _displayName = displayName;
16 | _typeIdentifier = typeIdentifier;
17 | }
18 |
19 | ///
20 | public string DisplayName
21 | {
22 | get
23 | {
24 | return _displayName;
25 | }
26 | }
27 |
28 | ///
29 | public void NavigateTo()
30 | {
31 | CSharpInheritanceAnalyzer.NavigateToType(_typeIdentifier);
32 | }
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp/AbstractTarget.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System.Collections.Generic;
7 | using System.Collections.Immutable;
8 | using Microsoft.CodeAnalysis;
9 | using Microsoft.CodeAnalysis.Text;
10 |
11 | internal abstract class AbstractTarget : IInheritanceTarget
12 | {
13 | private readonly SourceTextContainer _textContainer;
14 | private readonly ProjectId _projectId;
15 | private readonly string _displayName;
16 | private readonly KeyValuePair[] _symbolPath;
17 |
18 | protected AbstractTarget(SourceTextContainer textContainer, Project currentProject, Solution solution, ISymbol symbol)
19 | {
20 | Project project = solution.GetProject(symbol.ContainingAssembly) ?? currentProject;
21 |
22 | _textContainer = textContainer;
23 | _projectId = project.Id;
24 | _displayName = symbol.ToString();
25 |
26 | List> symbolPath = new List>();
27 | for (ISymbol currentSymbol = symbol.OriginalDefinition; currentSymbol != null; currentSymbol = currentSymbol.ContainingSymbol)
28 | {
29 | ImmutableArray parameters = default(ImmutableArray);
30 | ImmutableArray typeParameters = default(ImmutableArray);
31 | switch (currentSymbol.Kind)
32 | {
33 | case SymbolKind.Method:
34 | parameters = ((IMethodSymbol)currentSymbol).Parameters;
35 | typeParameters = ((IMethodSymbol)currentSymbol).TypeParameters;
36 | break;
37 |
38 | case SymbolKind.Property:
39 | parameters = ((IPropertySymbol)currentSymbol).Parameters;
40 | break;
41 |
42 | default:
43 | break;
44 | }
45 |
46 | if (!parameters.IsDefaultOrEmpty)
47 | {
48 | for (int i = parameters.Length - 1; i >= 0; i--)
49 | {
50 | symbolPath.Add(new KeyValuePair(SymbolKind.Parameter, parameters[i].ToString()));
51 | }
52 | }
53 |
54 | if (currentSymbol.Kind == SymbolKind.Namespace && ((INamespaceSymbol)currentSymbol).IsGlobalNamespace)
55 | break;
56 |
57 | if (currentSymbol.Kind == SymbolKind.NetModule || currentSymbol.Kind == SymbolKind.Assembly)
58 | break;
59 |
60 | string metadataName = currentSymbol.MetadataName;
61 | if (currentSymbol.Kind == SymbolKind.Method && !typeParameters.IsDefaultOrEmpty)
62 | metadataName = metadataName + '`' + typeParameters.Length;
63 |
64 | symbolPath.Add(new KeyValuePair(currentSymbol.Kind, metadataName));
65 | }
66 |
67 | symbolPath.Reverse();
68 | _symbolPath = symbolPath.ToArray();
69 | }
70 |
71 | ///
72 | public string DisplayName
73 | {
74 | get
75 | {
76 | return _displayName;
77 | }
78 | }
79 |
80 | ///
81 | public void NavigateTo()
82 | {
83 | CSharpInheritanceAnalyzer.NavigateToSymbol(_textContainer, _projectId, _symbolPath);
84 | }
85 | }
86 | }
87 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp/BackgroundParser.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System;
7 | using System.Diagnostics;
8 | using System.Threading;
9 | using System.Threading.Tasks;
10 | using Microsoft.VisualStudio.Text;
11 | using Tvl.VisualStudio.OutputWindow.Interfaces;
12 | using ErrorHandler = Microsoft.VisualStudio.ErrorHandler;
13 | using Path = System.IO.Path;
14 | using Timer = System.Threading.Timer;
15 |
16 | internal abstract class BackgroundParser : IInheritanceParser, IDisposable
17 | {
18 | private readonly WeakReference _textBuffer;
19 | private readonly TaskScheduler _taskScheduler;
20 | private readonly ITextDocumentFactoryService _textDocumentFactoryService;
21 | private readonly IOutputWindowService _outputWindowService;
22 | private readonly string _outputWindowName;
23 | private readonly Timer _timer;
24 |
25 | private TimeSpan _reparseDelay;
26 | private DateTimeOffset _lastEdit;
27 | private bool _dirty;
28 | private int _parsing;
29 |
30 | [Obsolete]
31 | public BackgroundParser(ITextBuffer textBuffer, ITextDocumentFactoryService textDocumentFactoryService, IOutputWindowService outputWindowService)
32 | : this(textBuffer, TaskScheduler.Default, textDocumentFactoryService, outputWindowService, PredefinedOutputWindowPanes.TvlDiagnostics)
33 | {
34 | }
35 |
36 | public BackgroundParser(ITextBuffer textBuffer, TaskScheduler taskScheduler, ITextDocumentFactoryService textDocumentFactoryService, IOutputWindowService outputWindowService)
37 | : this(textBuffer, taskScheduler, textDocumentFactoryService, outputWindowService, PredefinedOutputWindowPanes.TvlDiagnostics)
38 | {
39 | }
40 |
41 | public BackgroundParser(ITextBuffer textBuffer, TaskScheduler taskScheduler, ITextDocumentFactoryService textDocumentFactoryService, IOutputWindowService outputWindowService, string outputPaneName)
42 | {
43 | if (textBuffer == null)
44 | throw new ArgumentNullException("textBuffer");
45 | if (taskScheduler == null)
46 | throw new ArgumentNullException("taskScheduler");
47 | if (textDocumentFactoryService == null)
48 | throw new ArgumentNullException("textDocumentFactoryService");
49 | if (outputWindowService == null)
50 | throw new ArgumentNullException("outputWindowService");
51 |
52 | _textBuffer = new WeakReference(textBuffer);
53 | _taskScheduler = taskScheduler;
54 | _textDocumentFactoryService = textDocumentFactoryService;
55 | _outputWindowService = outputWindowService;
56 | _outputWindowName = outputPaneName;
57 |
58 | textBuffer.PostChanged += TextBufferPostChanged;
59 |
60 | _dirty = true;
61 | _reparseDelay = TimeSpan.FromMilliseconds(1500);
62 | _timer = new Timer(ParseTimerCallback, null, _reparseDelay, _reparseDelay);
63 | _lastEdit = DateTimeOffset.MinValue;
64 | }
65 |
66 | ///
67 | public event EventHandler ParseComplete;
68 |
69 | public ITextBuffer TextBuffer
70 | {
71 | get
72 | {
73 | return (ITextBuffer)_textBuffer.Target;
74 | }
75 | }
76 |
77 | public ITextDocument TextDocument
78 | {
79 | get
80 | {
81 | ITextBuffer textBuffer = TextBuffer;
82 | if (textBuffer == null)
83 | return null;
84 |
85 | ITextDocument textDocument;
86 | if (!TextDocumentFactoryService.TryGetTextDocument(textBuffer, out textDocument))
87 | return null;
88 |
89 | return textDocument;
90 | }
91 | }
92 |
93 | public bool Disposed
94 | {
95 | get;
96 | private set;
97 | }
98 |
99 | public TimeSpan ReparseDelay
100 | {
101 | get
102 | {
103 | return _reparseDelay;
104 | }
105 |
106 | set
107 | {
108 | TimeSpan originalDelay = _reparseDelay;
109 | try
110 | {
111 | _reparseDelay = value;
112 | _timer.Change(value, value);
113 | }
114 | catch (ArgumentException)
115 | {
116 | _reparseDelay = originalDelay;
117 | }
118 | }
119 | }
120 |
121 | public virtual string Name
122 | {
123 | get
124 | {
125 | return string.Empty;
126 | }
127 | }
128 |
129 | protected ITextDocumentFactoryService TextDocumentFactoryService
130 | {
131 | get
132 | {
133 | return _textDocumentFactoryService;
134 | }
135 | }
136 |
137 | protected IOutputWindowService OutputWindowService
138 | {
139 | get
140 | {
141 | return _outputWindowService;
142 | }
143 | }
144 |
145 | ///
146 | public void Dispose()
147 | {
148 | Dispose(true);
149 | GC.SuppressFinalize(this);
150 | }
151 |
152 | ///
153 | public void RequestParse(bool forceReparse)
154 | {
155 | TryReparse(forceReparse);
156 | }
157 |
158 | protected virtual void Dispose(bool disposing)
159 | {
160 | if (disposing)
161 | {
162 | ITextBuffer textBuffer = TextBuffer;
163 | if (textBuffer != null)
164 | textBuffer.PostChanged -= TextBufferPostChanged;
165 |
166 | _timer.Dispose();
167 | }
168 |
169 | Disposed = true;
170 | }
171 |
172 | protected abstract void ReParseImpl();
173 |
174 | protected virtual void OnParseComplete(InheritanceParseResultEventArgs e)
175 | {
176 | if (e == null)
177 | throw new ArgumentNullException("e");
178 |
179 | var t = ParseComplete;
180 | if (t != null)
181 | t(this, e);
182 | }
183 |
184 | protected void MarkDirty(bool resetTimer)
185 | {
186 | _dirty = true;
187 | _lastEdit = DateTimeOffset.Now;
188 |
189 | if (resetTimer)
190 | _timer.Change(_reparseDelay, _reparseDelay);
191 | }
192 |
193 | private void TextBufferPostChanged(object sender, EventArgs e)
194 | {
195 | MarkDirty(true);
196 | }
197 |
198 | private void ParseTimerCallback(object state)
199 | {
200 | if (TextBuffer == null)
201 | {
202 | Dispose();
203 | return;
204 | }
205 |
206 | TryReparse(_dirty);
207 | }
208 |
209 | private void TryReparse(bool forceReparse)
210 | {
211 | if (!_dirty && !forceReparse)
212 | return;
213 |
214 | if (DateTimeOffset.Now - _lastEdit < TimeSpan.FromSeconds(2))
215 | return;
216 |
217 | if (Interlocked.CompareExchange(ref _parsing, 1, 0) == 0)
218 | {
219 | try
220 | {
221 | Task task = Task.Factory.StartNew(ReParse, CancellationToken.None, TaskCreationOptions.LongRunning, _taskScheduler);
222 | task.ContinueWith(_ => _parsing = 0);
223 | }
224 | catch
225 | {
226 | _parsing = 0;
227 | throw;
228 | }
229 | }
230 | }
231 |
232 | private void ReParse()
233 | {
234 | try
235 | {
236 | _dirty = false;
237 |
238 | IOutputWindowPane outputWindow = null;
239 | if (_outputWindowService != null && !string.IsNullOrEmpty(_outputWindowName))
240 | outputWindow = _outputWindowService.TryGetPane(_outputWindowName);
241 |
242 | Stopwatch stopwatch = Stopwatch.StartNew();
243 |
244 | string message = "{0}: Background parse {1}{2} in {3}ms. {4}";
245 | string name = Name;
246 | if (!string.IsNullOrEmpty(name))
247 | name = "(" + name + ") ";
248 |
249 | string filename = "";
250 | ITextDocument textDocument = TextDocument;
251 | if (textDocument != null)
252 | {
253 | filename = textDocument.FilePath;
254 | if (filename != null)
255 | filename = filename.Substring(filename.LastIndexOfAny(new char[] { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar }) + 1);
256 | }
257 |
258 | try
259 | {
260 | ReParseImpl();
261 |
262 | if (outputWindow != null)
263 | {
264 | long time = stopwatch.ElapsedMilliseconds;
265 | outputWindow.WriteLine(string.Format(message, filename, name, "succeeded", time, string.Empty));
266 | }
267 | }
268 | catch (Exception e2)
269 | {
270 | if (ErrorHandler.IsCriticalException(e2))
271 | throw;
272 |
273 | try
274 | {
275 | if (outputWindow != null)
276 | {
277 | long time = stopwatch.ElapsedMilliseconds;
278 | outputWindow.WriteLine(string.Format(message, filename, name, "failed", time, e2.Message + e2.StackTrace));
279 | }
280 | }
281 | catch (Exception e3)
282 | {
283 | if (ErrorHandler.IsCriticalException(e3))
284 | throw;
285 | }
286 | }
287 | }
288 | catch (Exception ex)
289 | {
290 | if (ErrorHandler.IsCriticalException(ex))
291 | throw;
292 | }
293 | }
294 | }
295 | }
296 |
--------------------------------------------------------------------------------
/Tvl.VisualStudio.InheritanceMargin.CSharp/CSharpInheritanceAnalyzer.cs:
--------------------------------------------------------------------------------
1 | // Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2 | // Licensed under the MIT License. See LICENSE.txt in the project root for license information.
3 |
4 | namespace Tvl.VisualStudio.InheritanceMargin.CSharp
5 | {
6 | using System;
7 | using System.Collections.Generic;
8 | using System.Collections.Immutable;
9 | using System.Linq;
10 | using System.Reflection;
11 | using System.Threading;
12 | using System.Threading.Tasks;
13 | using Microsoft.CodeAnalysis;
14 | using Microsoft.CodeAnalysis.CSharp;
15 | using Microsoft.CodeAnalysis.CSharp.Syntax;
16 | using Microsoft.CodeAnalysis.FindSymbols;
17 | using Microsoft.CodeAnalysis.Text;
18 | using Microsoft.VisualStudio.LanguageServices;
19 | using Microsoft.VisualStudio.Text;
20 | using Microsoft.VisualStudio.Text.Editor;
21 | using Microsoft.VisualStudio.Text.Tagging;
22 | using Tvl.VisualStudio.OutputWindow.Interfaces;
23 | using Stopwatch = System.Diagnostics.Stopwatch;
24 | using StringBuilder = System.Text.StringBuilder;
25 | using SVsServiceProvider = Microsoft.VisualStudio.Shell.SVsServiceProvider;
26 |
27 | #if ROSLYN2
28 | using System.Linq.Expressions;
29 | using IEnumerable = System.Collections.IEnumerable;
30 | #endif
31 |
32 | internal class CSharpInheritanceAnalyzer : BackgroundParser
33 | {
34 | private static readonly Lazy DependentTypeFinder = new Lazy(() => typeof(SymbolFinder).Assembly.GetType("Microsoft.CodeAnalysis.FindSymbols.DependentTypeFinder"));
35 |
36 | private static readonly Lazy, CancellationToken, Task>>> FindDerivedClassesAsync =
37 | new Lazy, CancellationToken, Task>>>(() =>
38 | {
39 | #if ROSLYN2
40 | return SymbolFinder.FindDerivedClassesAsync;
41 | #else
42 | // Assume we are using Roslyn 1.3...
43 | var methodInfo = DependentTypeFinder.Value.GetMethod(
44 | "FindTransitivelyDerivedClassesAsync",
45 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
46 | null,
47 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(IImmutableSet), typeof(CancellationToken) },
48 | null);
49 |
50 | if (methodInfo == null)
51 | {
52 | // If we are wrong, try the Roslyn 1.0-1.2 method
53 | methodInfo = DependentTypeFinder.Value.GetMethod(
54 | "FindDerivedClassesAsync",
55 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
56 | null,
57 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(IImmutableSet), typeof(CancellationToken) },
58 | null);
59 | }
60 |
61 | return (Func, CancellationToken, Task>>)Delegate.CreateDelegate(typeof(Func, CancellationToken, Task>>), methodInfo);
62 | #endif
63 | });
64 |
65 | // Roslyn 1.0-1.1
66 | private static readonly Lazy FindDerivedInterfacesAsyncMethodInfo =
67 | new Lazy(() => DependentTypeFinder.Value.GetMethod(
68 | "FindDerivedInterfacesAsync",
69 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
70 | null,
71 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(IImmutableSet), typeof(CancellationToken) },
72 | null));
73 |
74 | // Roslyn 1.2
75 | private static readonly Lazy GetTypesImmediatelyDerivedFromInterfacesAsyncMethodInfo =
76 | new Lazy(() => DependentTypeFinder.Value.GetMethod(
77 | "GetTypesImmediatelyDerivedFromInterfacesAsync",
78 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
79 | null,
80 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(CancellationToken) },
81 | null));
82 |
83 | // Roslyn 1.3
84 | private static readonly Lazy FindImmediatelyDerivedAndImplementingTypesAsyncMethodInfo =
85 | new Lazy(() => DependentTypeFinder.Value.GetMethod(
86 | "FindImmediatelyDerivedAndImplementingTypesAsync",
87 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
88 | null,
89 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(CancellationToken) },
90 | null));
91 |
92 | // Roslyn 3.7-beta2
93 | private static readonly Lazy SymbolFinderFindDerivedInterfacesAsync =
94 | new Lazy(() => typeof(SymbolFinder).GetMethod(
95 | "FindDerivedInterfacesAsync",
96 | BindingFlags.Static | BindingFlags.Public,
97 | null,
98 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(IImmutableSet), typeof(CancellationToken) },
99 | null));
100 |
101 | ///
102 | /// Prior to Roslyn 1.2, DependentTypeFinder.FindDerivedInterfacesAsync can be used directly. In Roslyn
103 | /// 1.2, DependentTypeFinder.GetTypesImmediatelyDerivedFromInterfacesAsync must be used instead. In
104 | /// Roslyn 1.3, DependentTypeFinder.FindImmediatelyDerivedAndImplementingTypesAsync must be used instead.
105 | ///
106 | private static readonly Lazy, CancellationToken, Task>>> FindDerivedInterfacesAsync =
107 | new Lazy, CancellationToken, Task>>>(() =>
108 | {
109 | #if ROSLYN2
110 | // Roslyn 3.7-beta2 switched to a new public API
111 | if (SymbolFinderFindDerivedInterfacesAsync.Value is MethodInfo symbolFinderMethod)
112 | {
113 | return (Func, CancellationToken, Task>>)Delegate.CreateDelegate(typeof(Func, CancellationToken, Task>>), symbolFinderMethod);
114 | }
115 |
116 | if (FindImmediatelyDerivedAndImplementingTypesAsyncMethodInfo.Value is MethodInfo method
117 | && method.ReturnType == typeof(Task>))
118 | {
119 | // Roslyn 3.7-beta1 switched back to the form from Roslyn 1.3, with the exception of the return type.
120 | var immediatelyDerived = (Func>>)Delegate.CreateDelegate(typeof(Func>>), method);
121 | return (symbol, solution, projects, cancellationToken) => GetDerivedInterfacesFromImmediatelyDerivedAsync(symbol, solution, projects, immediatelyDerived, cancellationToken);
122 | }
123 |
124 | Func, CancellationToken, Task>> fallbackAccessor =
125 | (symbol, solution, projects, cancellationToken) => Task.FromResult(Enumerable.Empty());
126 |
127 | Type symbolAndProjectIdT = DependentTypeFinder.Value.Assembly.GetType("Microsoft.CodeAnalysis.FindSymbols.SymbolAndProjectId`1", false, false);
128 | if (symbolAndProjectIdT == null)
129 | return fallbackAccessor;
130 |
131 | Type namedTypeSymbolAndProjectId = symbolAndProjectIdT.MakeGenericType(typeof(INamedTypeSymbol));
132 |
133 | MethodInfo declaredMethodInfo = DependentTypeFinder.Value.GetMethod(
134 | "FindImmediatelyDerivedAndImplementingTypesAsync",
135 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
136 | null,
137 | new[] { typeof(INamedTypeSymbol), typeof(Solution), typeof(CancellationToken) },
138 | null);
139 |
140 | ParameterExpression typeParameter = Expression.Parameter(typeof(INamedTypeSymbol), "type");
141 | Expression typeParameterReference;
142 | if (declaredMethodInfo is object)
143 | {
144 | // Our argument matches the one expected by FindImmediatelyDerivedAndImplementingTypesAsync
145 | typeParameterReference = typeParameter;
146 | }
147 | else
148 | {
149 | // Roslyn 3.6 changed the first argument type
150 | declaredMethodInfo = DependentTypeFinder.Value.GetMethod(
151 | "FindImmediatelyDerivedAndImplementingTypesAsync",
152 | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic,
153 | null,
154 | new[] { namedTypeSymbolAndProjectId, typeof(Solution), typeof(CancellationToken) },
155 | null);
156 | if (declaredMethodInfo == null)
157 | return fallbackAccessor;
158 |
159 | typeParameterReference = Expression.New(
160 | namedTypeSymbolAndProjectId.GetConstructors().Single(),
161 | typeParameter,
162 | Expression.Convert(Expression.Constant(null), typeof(ProjectId)));
163 | }
164 |
165 | // Here we build up the actual call to FindDerivedAndImplementingTypesAsync
166 | ParameterExpression solutionParameter = Expression.Parameter(typeof(Solution), "solution");
167 | ParameterExpression cancellationTokenParameter = Expression.Parameter(typeof(CancellationToken), "cancellationToken");
168 | Func callAsync =
169 | Expression.Lambda>(
170 | Expression.Call(
171 | declaredMethodInfo,
172 | typeParameterReference,
173 | solutionParameter,
174 | cancellationTokenParameter),
175 | typeParameter,
176 | solutionParameter,
177 | cancellationTokenParameter)
178 | .Compile();
179 |
180 | // The return type is Task>>. Here we build up a
181 | // method to get the task result, and a method which can extract the type symbol from a
182 | // SymbolAndProjectId.
183 | Type specificTaskType = typeof(Task<>).MakeGenericType(typeof(ImmutableArray<>).MakeGenericType(namedTypeSymbolAndProjectId));
184 | PropertyInfo resultProperty = specificTaskType.GetProperty(nameof(Task.Result), BindingFlags.Public | BindingFlags.Instance);
185 | ParameterExpression taskParameter = Expression.Parameter(typeof(Task), "task");
186 | Func readResult =
187 | Expression.Lambda>(
188 | Expression.Convert(
189 | Expression.Property(Expression.Convert(taskParameter, specificTaskType), resultProperty.GetMethod),
190 | typeof(IEnumerable)),
191 | taskParameter)
192 | .Compile();
193 |
194 | FieldInfo symbolField = namedTypeSymbolAndProjectId.GetField("Symbol", BindingFlags.Public | BindingFlags.Instance);
195 | ParameterExpression symbolAndProjectIdParameter = Expression.Parameter(typeof(object), "symbolAndProjectId");
196 | Func