66
77using System . Collections . Concurrent ;
88using System . Diagnostics ;
9- using System . Linq ;
109using System . Threading ;
1110using Microsoft . CodeAnalysis ;
1211using Microsoft . CodeAnalysis . CodeStyle ;
@@ -45,6 +44,8 @@ protected override void InitializeWorker(AnalysisContext context)
4544 var fieldStateMap = new ConcurrentDictionary < IFieldSymbol , ( bool isCandidate , bool written ) > ( ) ;
4645
4746 var threadStaticAttribute = compilationStartContext . Compilation . ThreadStaticAttributeType ( ) ;
47+ var dataContractAttribute = compilationStartContext . Compilation . DataContractAttribute ( ) ;
48+ var dataMemberAttribute = compilationStartContext . Compilation . DataMemberAttribute ( ) ;
4849
4950 // We register following actions in the compilation:
5051 // 1. A symbol action for field symbols to ensure the field state is initialized for every field in
@@ -112,7 +113,7 @@ void OnSymbolEnd(SymbolAnalysisContext symbolEndContext)
112113 }
113114 }
114115
115- static bool IsCandidateField ( IFieldSymbol symbol , INamedTypeSymbol threadStaticAttribute , Compilation compilation ) =>
116+ static bool IsCandidateField ( IFieldSymbol symbol , INamedTypeSymbol threadStaticAttribute , INamedTypeSymbol dataContractAttribute , INamedTypeSymbol dataMemberAttribute ) =>
116117 symbol . DeclaredAccessibility == Accessibility . Private &&
117118 ! symbol . IsReadOnly &&
118119 ! symbol . IsConst &&
@@ -123,21 +124,21 @@ static bool IsCandidateField(IFieldSymbol symbol, INamedTypeSymbol threadStaticA
123124 ! symbol . GetAttributes ( ) . Any (
124125 static ( a , threadStaticAttribute ) => SymbolEqualityComparer . Default . Equals ( a . AttributeClass , threadStaticAttribute ) ,
125126 threadStaticAttribute ) &&
126- ! IsDataContractSerializable ( symbol , compilation ) ;
127+ ! IsDataContractSerializable ( symbol , dataContractAttribute , dataMemberAttribute ) ;
127128
128- static bool IsDataContractSerializable ( IFieldSymbol symbol , Compilation compilation )
129+ static bool IsDataContractSerializable ( IFieldSymbol symbol , INamedTypeSymbol dataContractAttribute , INamedTypeSymbol dataMemberAttribute )
129130 {
130- var dataMemberAttribute = compilation . DataMemberAttribute ( ) ;
131- var dataContractAttribute = compilation . DataContractAttribute ( ) ;
131+ if ( dataContractAttribute is null || dataMemberAttribute is null )
132+ return false ;
132133
133- return symbol . GetAttributes ( ) . Any ( x => x . AttributeClass == dataMemberAttribute )
134- && symbol . ContainingType . GetAttributes ( ) . Any ( x => x . AttributeClass == dataContractAttribute ) ;
134+ return symbol . GetAttributes ( ) . Any ( static ( x , dataMemberAttribute ) => SymbolEqualityComparer . Default . Equals ( x . AttributeClass , dataMemberAttribute ) , dataMemberAttribute )
135+ && symbol . ContainingType . GetAttributes ( ) . Any ( static ( x , dataContractAttribute ) => SymbolEqualityComparer . Default . Equals ( x . AttributeClass , dataContractAttribute ) , dataContractAttribute ) ;
135136 }
136137
137138 // Method to update the field state for a candidate field written outside constructor and field initializer.
138139 void UpdateFieldStateOnWrite ( IFieldSymbol field )
139140 {
140- Debug . Assert ( IsCandidateField ( field , threadStaticAttribute , compilationStartContext . Compilation ) ) ;
141+ Debug . Assert ( IsCandidateField ( field , threadStaticAttribute , dataContractAttribute , dataMemberAttribute ) ) ;
141142 Debug . Assert ( fieldStateMap . ContainsKey ( field ) ) ;
142143
143144 fieldStateMap [ field ] = ( isCandidate : true , written : true ) ;
@@ -146,7 +147,7 @@ void UpdateFieldStateOnWrite(IFieldSymbol field)
146147 // Method to get or initialize the field state.
147148 ( bool isCandidate , bool written ) TryGetOrInitializeFieldState ( IFieldSymbol fieldSymbol , AnalyzerOptions options , CancellationToken cancellationToken )
148149 {
149- if ( ! IsCandidateField ( fieldSymbol , threadStaticAttribute , compilationStartContext . Compilation ) )
150+ if ( ! IsCandidateField ( fieldSymbol , threadStaticAttribute , dataContractAttribute , dataMemberAttribute ) )
150151 {
151152 return default ;
152153 }
@@ -156,14 +157,14 @@ void UpdateFieldStateOnWrite(IFieldSymbol field)
156157 return result ;
157158 }
158159
159- result = ComputeInitialFieldState ( fieldSymbol , options , threadStaticAttribute , compilationStartContext . Compilation , cancellationToken ) ;
160+ result = ComputeInitialFieldState ( fieldSymbol , options , threadStaticAttribute , dataContractAttribute , dataMemberAttribute , cancellationToken ) ;
160161 return fieldStateMap . GetOrAdd ( fieldSymbol , result ) ;
161162 }
162163
163164 // Method to compute the initial field state.
164- static ( bool isCandidate , bool written ) ComputeInitialFieldState ( IFieldSymbol field , AnalyzerOptions options , INamedTypeSymbol threadStaticAttribute , Compilation compilation , CancellationToken cancellationToken )
165+ static ( bool isCandidate , bool written ) ComputeInitialFieldState ( IFieldSymbol field , AnalyzerOptions options , INamedTypeSymbol threadStaticAttribute , INamedTypeSymbol dataContractAttribute , INamedTypeSymbol dataMemberAttribute , CancellationToken cancellationToken )
165166 {
166- Debug . Assert ( IsCandidateField ( field , threadStaticAttribute , compilation ) ) ;
167+ Debug . Assert ( IsCandidateField ( field , threadStaticAttribute , dataContractAttribute , dataMemberAttribute ) ) ;
167168
168169 var option = GetCodeStyleOption ( field , options , cancellationToken ) ;
169170 if ( option == null || ! option . Value )
0 commit comments