55using System ;
66using System . Collections . Generic ;
77using System . Collections . Immutable ;
8+ using System . Linq ;
89using System . Reflection ;
910using Microsoft . CodeAnalysis ;
1011using Microsoft . CodeAnalysis . Diagnostics ;
@@ -46,6 +47,31 @@ internal VisualStudioDiagnosticAnalyzerProvider(object extensionManager, Type ty
4647 public ImmutableArray < ( AnalyzerFileReference reference , string extensionId ) > GetAnalyzerReferencesInExtensions ( )
4748 => _lazyAnalyzerReferences . Value ;
4849
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+ }
60+
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+
4975 private ImmutableArray < ( AnalyzerFileReference reference , string extensionId ) > GetAnalyzerReferencesImpl ( )
5076 {
5177 try
@@ -54,37 +80,12 @@ internal VisualStudioDiagnosticAnalyzerProvider(object extensionManager, Type ty
5480 // implementation of the public interface in internal type. so we can't use dynamic here
5581 var _ = PooledDictionary < AnalyzerFileReference , string > . GetInstance ( out var analyzePaths ) ;
5682
57- // var enabledExtensions = extensionManager.GetEnabledExtensions(AnalyzerContentTypeName);
58- var extensionManagerType = _extensionManager . GetType ( ) ;
59- var extensionManager_GetEnabledExtensionsMethod = extensionManagerType . GetRuntimeMethod ( "GetEnabledExtensions" , [ typeof ( string ) ] ) ;
60- var enabledExtensions = ( IEnumerable < object > ) extensionManager_GetEnabledExtensionsMethod . Invoke ( _extensionManager , [ AnalyzerContentTypeName ] ) ;
61-
83+ var enabledExtensions = GetEnabledExtensions ( AnalyzerContentTypeName ) ;
6284 foreach ( var extension in enabledExtensions )
6385 {
64- var extensionType = extension . GetType ( ) ;
65- var extensionType_HeaderProperty = extensionType . GetRuntimeProperty ( "Header" ) ;
66- var extension_Header = extensionType_HeaderProperty . GetValue ( extension ) ;
67- var extension_HeaderType = extension_Header . GetType ( ) ;
68- var extension_HeaderType_Identifier = extension_HeaderType . GetRuntimeProperty ( "Identifier" ) ;
69- var identifier = ( string ) extension_HeaderType_Identifier . GetValue ( extension_Header ) ;
70-
71- var extensionType_ContentProperty = extensionType . GetRuntimeProperty ( "Content" ) ;
72- var extension_Content = ( IEnumerable < object > ) extensionType_ContentProperty . GetValue ( extension ) ;
73-
74- foreach ( var content in extension_Content )
86+ var identifier = GetExtensionIdentifier ( extension ) ;
87+ foreach ( var assemblyPath in GetExtensionContent ( extension , AnalyzerContentTypeName ) )
7588 {
76- if ( ! ShouldInclude ( content ) )
77- {
78- continue ;
79- }
80-
81- var extensionType_GetContentMethod = extensionType . GetRuntimeMethod ( "GetContentLocation" , [ _typeIExtensionContent ] ) ;
82- if ( extensionType_GetContentMethod ? . Invoke ( extension , [ content ] ) is not string assemblyPath ||
83- string . IsNullOrEmpty ( assemblyPath ) )
84- {
85- continue ;
86- }
87-
8889 analyzePaths . Add ( new AnalyzerFileReference ( assemblyPath , AnalyzerAssemblyLoader ) , identifier ) ;
8990 }
9091 }
@@ -108,13 +109,60 @@ internal VisualStudioDiagnosticAnalyzerProvider(object extensionManager, Type ty
108109 }
109110 }
110111
111- private static bool ShouldInclude ( object content )
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+
159+ private static bool ShouldInclude ( object content , string contentTypeName )
112160 {
113161 // var content_ContentTypeName = content.ContentTypeName;
114162 var contentType = content . GetType ( ) ;
115163 var contentType_ContentTypeNameProperty = contentType . GetRuntimeProperty ( "ContentTypeName" ) ;
116164 var content_ContentTypeName = contentType_ContentTypeNameProperty . GetValue ( content ) as string ;
117165
118- return string . Equals ( content_ContentTypeName , AnalyzerContentTypeName , StringComparison . InvariantCultureIgnoreCase ) ;
166+ return string . Equals ( content_ContentTypeName , contentTypeName , StringComparison . InvariantCultureIgnoreCase ) ;
119167 }
120168}
0 commit comments