44 using Microsoft . CodeAnalysis . CSharp ;
55 using Microsoft . CodeAnalysis . CSharp . Syntax ;
66
7+ using System . Collections . Generic ;
78 using System . Collections . Immutable ;
89 using System . Globalization ;
910 using System . Linq ;
@@ -86,6 +87,37 @@ public static ImmutableArray<AttributeSyntax> GetAttributes(INamedTypeSymbol? at
8687 return attributesBuilder . ToImmutable ( ) ;
8788 }
8889
90+ public static int GetAttributeUsageCount ( string attributeName , Compilation compilation , SyntaxList < AttributeListSyntax > attributeLists , SemanticModel semanticModel ) => GetAttributeUsageCount ( compilation . GetTypeByMetadataName ( attributeName ) , attributeLists , semanticModel ) ;
91+
92+ public static int GetAttributeUsageCount ( INamedTypeSymbol ? attributeTypeSymbol , SyntaxList < AttributeListSyntax > attributeLists , SemanticModel semanticModel )
93+ {
94+ var attributeUsageCount = 0 ;
95+
96+ if ( attributeTypeSymbol == null )
97+ {
98+ return 0 ;
99+ }
100+
101+ foreach ( var attributeListSyntax in attributeLists )
102+ {
103+ foreach ( var attributeSyntax in attributeListSyntax . Attributes )
104+ {
105+ var attributeSyntaxTypeSymbol = semanticModel . GetTypeInfo ( attributeSyntax ) . Type ;
106+ if ( attributeSyntaxTypeSymbol == null )
107+ {
108+ continue ;
109+ }
110+
111+ if ( attributeSyntaxTypeSymbol . Equals ( attributeTypeSymbol , SymbolEqualityComparer . Default ) )
112+ {
113+ attributeUsageCount ++ ;
114+ }
115+ }
116+ }
117+
118+ return attributeUsageCount ;
119+ }
120+
89121 public static string NormalizeTypeName ( INamedTypeSymbol namedTypeSymbol )
90122 {
91123 string typeName ;
@@ -146,8 +178,8 @@ static void Method() {{
146178
147179 private static bool IsAssignableTo ( string codeTemplate1 , string codeTemplate2 , Compilation compilation , ITypeSymbol targetType , string valueExpression , Optional < object ? > constantValue , string ? valueType )
148180 {
149- var hasNoCompilationErrors = HasNoCompilationErrors ( string . Format ( codeTemplate1 , targetType , valueExpression ) , compilation ) ;
150- if ( hasNoCompilationErrors )
181+ var hasCompilerDiagnostics = HasNoCompilerDiagnostics ( string . Format ( codeTemplate1 , targetType , valueExpression ) , compilation ) ;
182+ if ( hasCompilerDiagnostics )
151183 {
152184 return true ;
153185 }
@@ -163,20 +195,20 @@ private static bool IsAssignableTo(string codeTemplate1, string codeTemplate2, C
163195 return false ;
164196 }
165197
166- return HasNoCompilationErrors ( string . Format ( codeTemplate2 , targetType , valueType , constantLiteral ) , compilation ) ;
198+ return HasNoCompilerDiagnostics ( string . Format ( codeTemplate2 , targetType , valueType , constantLiteral ) , compilation ) ;
167199 }
168200
169- private static bool HasNoCompilationErrors ( string code , Compilation compilation )
201+ private static bool HasNoCompilerDiagnostics ( string code , Compilation compilation )
170202 {
171203 var syntaxTree = CSharpSyntaxTree . ParseText ( code ) ;
172204
173- var compilationErrors = compilation . AddSyntaxTrees ( syntaxTree )
174- . GetSemanticModel ( syntaxTree )
175- . GetMethodBodyDiagnostics ( )
176- . Where ( d => d . DefaultSeverity == DiagnosticSeverity . Error )
177- . ToList ( ) ;
205+ var compilerDiagnostics = compilation . AddSyntaxTrees ( syntaxTree )
206+ . GetSemanticModel ( syntaxTree )
207+ . GetMethodBodyDiagnostics ( )
208+ . Where ( d => d . DefaultSeverity == DiagnosticSeverity . Error )
209+ . ToList ( ) ;
178210
179- return compilationErrors . Count == 0 ;
211+ return compilerDiagnostics . Count == 0 ;
180212 }
181213
182214 private static string ? FormatLiteral ( object ? value )
@@ -201,5 +233,11 @@ private static bool HasNoCompilationErrors(string code, Compilation compilation)
201233 _ => null
202234 } ;
203235 }
236+
237+ public static void Deconstruct < T1 , T2 > ( this KeyValuePair < T1 , T2 > tuple , out T1 key , out T2 value )
238+ {
239+ key = tuple . Key ;
240+ value = tuple . Value ;
241+ }
204242 }
205243}
0 commit comments