55using System ;
66using System . Collections . Generic ;
77using System . Collections . Immutable ;
8- using System . Linq ;
8+ using System . Configuration . Assemblies ;
99using System . Reflection ;
10+ using ICSharpCode . Decompiler . CSharp . Syntax ;
1011using Microsoft . CodeAnalysis ;
1112using Microsoft . CodeAnalysis . Diagnostics ;
1213using Microsoft . CodeAnalysis . PooledObjects ;
@@ -23,6 +24,8 @@ internal sealed partial class VisualStudioDiagnosticAnalyzerProvider : IHostDiag
2324{
2425 private const string AnalyzerContentTypeName = "Microsoft.VisualStudio.Analyzer" ;
2526
27+ private const string RazorContentTypeName = "Microsoft.VisualStudio.RazorAssembly" ;
28+
2629 /// <summary>
2730 /// Loader for VSIX-based analyzers.
2831 /// </summary>
@@ -32,6 +35,7 @@ internal sealed partial class VisualStudioDiagnosticAnalyzerProvider : IHostDiag
3235 private readonly Type _typeIExtensionContent ;
3336
3437 private readonly Lazy < ImmutableArray < ( AnalyzerFileReference reference , string extensionId ) > > _lazyAnalyzerReferences ;
38+ private readonly Lazy < ImmutableArray < ( string path , string extensionId ) > > _lazyRazorReferences ;
3539
3640 // internal for testing
3741 internal VisualStudioDiagnosticAnalyzerProvider ( object extensionManager , Type typeIExtensionContent )
@@ -41,52 +45,56 @@ internal VisualStudioDiagnosticAnalyzerProvider(object extensionManager, Type ty
4145
4246 _extensionManager = extensionManager ;
4347 _typeIExtensionContent = typeIExtensionContent ;
44- _lazyAnalyzerReferences = new Lazy < ImmutableArray < ( AnalyzerFileReference , string ) > > ( GetAnalyzerReferencesImpl ) ;
48+ _lazyAnalyzerReferences = new Lazy < ImmutableArray < ( AnalyzerFileReference , string ) > > ( ( ) => GetExtensionContent ( AnalyzerContentTypeName ) . SelectAsArray ( c => ( new AnalyzerFileReference ( c . path , AnalyzerAssemblyLoader ) , c . extensionId ) ) ) ;
49+ _lazyRazorReferences = new Lazy < ImmutableArray < ( string , string ) > > ( ( ) => GetExtensionContent ( RazorContentTypeName ) ) ;
4550 }
4651
4752 public ImmutableArray < ( AnalyzerFileReference reference , string extensionId ) > GetAnalyzerReferencesInExtensions ( )
4853 => _lazyAnalyzerReferences . Value ;
4954
50- public ImmutableArray < string > GetContentInExtension ( string extensionId , string contentTypeName )
51- {
52- try
53- {
54- var enabledExtensions = GetEnabledExtensions ( contentTypeName ) ;
55- var extension = enabledExtensions . FirstOrDefault ( e => string . Equals ( GetExtensionIdentifier ( e ) , extensionId , StringComparison . InvariantCultureIgnoreCase ) ) ;
56- if ( extension is null )
57- {
58- return [ ] ;
59- }
55+ public ImmutableArray < ( string path , string extensionId ) > GetRazorReferencesInExtensions ( )
56+ => _lazyRazorReferences . Value ;
6057
61- return GetExtensionContent ( extension , contentTypeName ) ;
62- }
63- catch ( TargetInvocationException ex ) when ( ex . InnerException is InvalidOperationException )
64- {
65- // this can be called from any thread, and extension manager could be disposed in the middle of us using it since
66- // now all these are free-threaded and there is no central coordinator, or API or state is immutable that prevent states from
67- // changing in the middle of others using it.
68- //
69- // fortunately, this only happens on disposing at shutdown, so we just catch the exception and silently swallow it.
70- // we are about to shutdown anyway.
71- return [ ] ;
72- }
73- }
74-
75- private ImmutableArray < ( AnalyzerFileReference reference , string extensionId ) > GetAnalyzerReferencesImpl ( )
58+ private ImmutableArray < ( string path , string extensionId ) > GetExtensionContent ( string contentTypeName )
7659 {
7760 try
7861 {
7962 // dynamic is weird. it can't see internal type with public interface even if callee is
8063 // implementation of the public interface in internal type. so we can't use dynamic here
81- var _ = PooledDictionary < AnalyzerFileReference , string > . GetInstance ( out var analyzePaths ) ;
64+ var _ = PooledDictionary < string , string > . GetInstance ( out var analyzePaths ) ;
65+
66+ // var enabledExtensions = extensionManager.GetEnabledExtensions(contentTypeName);
67+ var extensionManagerType = _extensionManager . GetType ( ) ;
68+ var extensionManager_GetEnabledExtensionsMethod = extensionManagerType . GetRuntimeMethod ( "GetEnabledExtensions" , [ typeof ( string ) ] ) ;
69+ var enabledExtensions = ( IEnumerable < object > ) extensionManager_GetEnabledExtensionsMethod . Invoke ( _extensionManager , [ contentTypeName ] ) ;
8270
83- var enabledExtensions = GetEnabledExtensions ( AnalyzerContentTypeName ) ;
8471 foreach ( var extension in enabledExtensions )
8572 {
86- var identifier = GetExtensionIdentifier ( extension ) ;
87- foreach ( var assemblyPath in GetExtensionContent ( extension , AnalyzerContentTypeName ) )
73+ var extensionType = extension . GetType ( ) ;
74+ var extensionType_HeaderProperty = extensionType . GetRuntimeProperty ( "Header" ) ;
75+ var extension_Header = extensionType_HeaderProperty . GetValue ( extension ) ;
76+ var extension_HeaderType = extension_Header . GetType ( ) ;
77+ var extension_HeaderType_Identifier = extension_HeaderType . GetRuntimeProperty ( "Identifier" ) ;
78+ var identifier = ( string ) extension_HeaderType_Identifier . GetValue ( extension_Header ) ;
79+
80+ var extensionType_ContentProperty = extensionType . GetRuntimeProperty ( "Content" ) ;
81+ var extension_Content = ( IEnumerable < object > ) extensionType_ContentProperty . GetValue ( extension ) ;
82+
83+ foreach ( var content in extension_Content )
8884 {
89- analyzePaths . Add ( new AnalyzerFileReference ( assemblyPath , AnalyzerAssemblyLoader ) , identifier ) ;
85+ if ( ! ShouldInclude ( content , contentTypeName ) )
86+ {
87+ continue ;
88+ }
89+
90+ var extensionType_GetContentMethod = extensionType . GetRuntimeMethod ( "GetContentLocation" , [ _typeIExtensionContent ] ) ;
91+ if ( extensionType_GetContentMethod ? . Invoke ( extension , [ content ] ) is not string assemblyPath ||
92+ string . IsNullOrEmpty ( assemblyPath ) )
93+ {
94+ continue ;
95+ }
96+
97+ analyzePaths . Add ( assemblyPath , identifier ) ;
9098 }
9199 }
92100
@@ -95,7 +103,7 @@ public ImmutableArray<string> GetContentInExtension(string extensionId, string c
95103 GC . KeepAlive ( enabledExtensions ) ;
96104
97105 // Order for deterministic result.
98- return analyzePaths . OrderBy ( ( x , y ) => string . CompareOrdinal ( x . Key . FullPath , y . Key . FullPath ) ) . SelectAsArray ( entry => ( entry . Key , entry . Value ) ) ;
106+ return analyzePaths . OrderBy ( ( x , y ) => string . CompareOrdinal ( x . Key , y . Key ) ) . SelectAsArray ( entry => ( entry . Key , entry . Value ) ) ;
99107 }
100108 catch ( TargetInvocationException ex ) when ( ex . InnerException is InvalidOperationException )
101109 {
@@ -109,53 +117,6 @@ public ImmutableArray<string> GetContentInExtension(string extensionId, string c
109117 }
110118 }
111119
112- private IEnumerable < object > GetEnabledExtensions ( string contentTypeName )
113- {
114- // var enabledExtensions = extensionManager.GetEnabledExtensions(contentTypeName);
115- var extensionManagerType = _extensionManager . GetType ( ) ;
116- var extensionManager_GetEnabledExtensionsMethod = extensionManagerType . GetRuntimeMethod ( "GetEnabledExtensions" , [ typeof ( string ) ] ) ;
117- var enabledExtensions = ( IEnumerable < object > ) extensionManager_GetEnabledExtensionsMethod . Invoke ( _extensionManager , [ contentTypeName ] ) ;
118- return enabledExtensions ;
119- }
120-
121- private static string GetExtensionIdentifier ( object extension )
122- {
123- var extensionType = extension . GetType ( ) ;
124- var extensionType_HeaderProperty = extensionType . GetRuntimeProperty ( "Header" ) ;
125- var extension_Header = extensionType_HeaderProperty . GetValue ( extension ) ;
126- var extension_HeaderType = extension_Header . GetType ( ) ;
127- var extension_HeaderType_Identifier = extension_HeaderType . GetRuntimeProperty ( "Identifier" ) ;
128- var identifier = ( string ) extension_HeaderType_Identifier . GetValue ( extension_Header ) ;
129- return identifier ;
130- }
131-
132- private ImmutableArray < string > GetExtensionContent ( object extension , string contentType )
133- {
134- var paths = ArrayBuilder < string > . GetInstance ( ) ;
135- var extensionType = extension . GetType ( ) ;
136-
137- var extensionType_ContentProperty = extensionType . GetRuntimeProperty ( "Content" ) ;
138- var extension_Content = ( IEnumerable < object > ) extensionType_ContentProperty . GetValue ( extension ) ;
139-
140- foreach ( var content in extension_Content )
141- {
142- if ( ! ShouldInclude ( content , contentType ) )
143- {
144- continue ;
145- }
146-
147- var extensionType_GetContentMethod = extensionType . GetRuntimeMethod ( "GetContentLocation" , [ _typeIExtensionContent ] ) ;
148- if ( extensionType_GetContentMethod ? . Invoke ( extension , [ content ] ) is not string assemblyPath ||
149- string . IsNullOrEmpty ( assemblyPath ) )
150- {
151- continue ;
152- }
153- paths . Add ( assemblyPath ) ;
154- }
155-
156- return paths . ToImmutableAndFree ( ) ;
157- }
158-
159120 private static bool ShouldInclude ( object content , string contentTypeName )
160121 {
161122 // var content_ContentTypeName = content.ContentTypeName;
0 commit comments