@@ -130,25 +130,26 @@ private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, Xml
130130 var textElement = summaryElement . Content . FirstOrDefault ( ) as XmlTextSyntax ;
131131 var text = textElement == null ? string . Empty : XmlCommentHelper . GetText ( textElement , true ) . TrimStart ( ) ;
132132
133- bool startsWithGetOrSet = text . StartsWith ( startingTextGetsOrSets , StringComparison . OrdinalIgnoreCase ) ;
133+ bool prefixIsGetsOrSets = text . StartsWith ( startingTextGetsOrSets , StringComparison . OrdinalIgnoreCase ) ;
134+ bool prefixIsGets = ! prefixIsGetsOrSets && text . StartsWith ( startingTextGets , StringComparison . OrdinalIgnoreCase ) ;
135+ bool prefixIsSets = text . StartsWith ( startingTextSets , StringComparison . OrdinalIgnoreCase ) ;
136+
134137 bool getterVisible , setterVisible ;
135138 if ( getter != null && setter != null )
136139 {
137140 if ( ! getter . Modifiers . Any ( ) && ! setter . Modifiers . Any ( ) )
138141 {
139- // Case 1: The getter and setter have the same declared accessibility
142+ // The getter and setter have the same declared accessibility
140143 getterVisible = true ;
141144 setterVisible = true ;
142145 }
143146 else if ( getter . Modifiers . Any ( SyntaxKind . PrivateKeyword ) )
144147 {
145- // Case 3
146148 getterVisible = false ;
147149 setterVisible = true ;
148150 }
149151 else if ( setter . Modifiers . Any ( SyntaxKind . PrivateKeyword ) )
150152 {
151- // Case 3
152153 getterVisible = true ;
153154 setterVisible = false ;
154155 }
@@ -160,7 +161,7 @@ private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, Xml
160161 || propertyAccessibility == Accessibility . Private ;
161162 if ( propertyOnlyInternal )
162163 {
163- // Case 2: Property only internal and no accessor is explicitly private
164+ // Property only internal and no accessor is explicitly private
164165 getterVisible = true ;
165166 setterVisible = true ;
166167 }
@@ -174,7 +175,6 @@ private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, Xml
174175 case Accessibility . Public :
175176 case Accessibility . ProtectedOrInternal :
176177 case Accessibility . Protected :
177- // Case 4
178178 getterVisible = true ;
179179 break ;
180180
@@ -192,7 +192,6 @@ private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, Xml
192192 case Accessibility . Public :
193193 case Accessibility . ProtectedOrInternal :
194194 case Accessibility . Protected :
195- // Case 4
196195 setterVisible = true ;
197196 break ;
198197
@@ -225,51 +224,85 @@ private static void AnalyzeSummaryElement(SyntaxNodeAnalysisContext context, Xml
225224 {
226225 if ( setterVisible )
227226 {
228- if ( ! startsWithGetOrSet )
227+ // Both getter and setter are visible.
228+ if ( ! prefixIsGetsOrSets )
229229 {
230- diagnosticProperties . Add ( ExpectedTextKey , startingTextGetsOrSets ) ;
231-
232- if ( text . StartsWith ( startingTextGets , StringComparison . OrdinalIgnoreCase ) )
230+ ReportSA1623 ( context , diagnosticLocation , diagnosticProperties , text , expectedStartingText : startingTextGetsOrSets , unexpectedStartingText1 : startingTextGets , unexpectedStartingText2 : startingTextSets ) ;
231+ }
232+ }
233+ else if ( setter != null )
234+ {
235+ // Both getter and setter exist, but only getter is visible.
236+ if ( ! prefixIsGets )
237+ {
238+ if ( prefixIsGetsOrSets )
233239 {
234- diagnosticProperties . Add ( TextToRemoveKey , text . Substring ( 0 , startingTextGets . Length ) ) ;
240+ ReportSA1624 ( context , diagnosticLocation , diagnosticProperties , accessor : "get" , expectedStartingText : startingTextGets , startingTextToRemove : startingTextGetsOrSets ) ;
235241 }
236- else if ( text . StartsWith ( startingTextSets , StringComparison . OrdinalIgnoreCase ) )
242+ else
237243 {
238- diagnosticProperties . Add ( TextToRemoveKey , text . Substring ( 0 , startingTextSets . Length ) ) ;
244+ ReportSA1623 ( context , diagnosticLocation , diagnosticProperties , text , expectedStartingText : startingTextGets , unexpectedStartingText1 : startingTextSets ) ;
239245 }
240-
241- context . ReportDiagnostic ( Diagnostic . Create ( SA1623Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , startingTextGetsOrSets ) ) ;
242246 }
243247 }
244248 else
245249 {
246- if ( startsWithGetOrSet )
250+ // Getter exists and is visible. Setter does not exist.
251+ if ( ! prefixIsGets )
247252 {
248- diagnosticProperties . Add ( ExpectedTextKey , startingTextGets ) ;
249- diagnosticProperties . Add ( TextToRemoveKey , startingTextGetsOrSets ) ;
250- context . ReportDiagnostic ( Diagnostic . Create ( SA1624Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , "get" , startingTextGets ) ) ;
251- }
252- else if ( ! text . StartsWith ( startingTextGets , StringComparison . OrdinalIgnoreCase ) )
253- {
254- diagnosticProperties . Add ( ExpectedTextKey , startingTextGets ) ;
255- context . ReportDiagnostic ( Diagnostic . Create ( SA1623Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , startingTextGets ) ) ;
253+ ReportSA1623 ( context , diagnosticLocation , diagnosticProperties , text , expectedStartingText : startingTextGets , unexpectedStartingText1 : startingTextSets , unexpectedStartingText2 : startingTextGetsOrSets ) ;
256254 }
257255 }
258256 }
259257 else if ( setterVisible )
260258 {
261- if ( startsWithGetOrSet )
259+ if ( getter != null )
262260 {
263- diagnosticProperties . Add ( ExpectedTextKey , startingTextSets ) ;
264- diagnosticProperties . Add ( TextToRemoveKey , startingTextGetsOrSets ) ;
265- context . ReportDiagnostic ( Diagnostic . Create ( SA1624Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , "set" , startingTextSets ) ) ;
261+ // Both getter and setter exist, but only setter is visible.
262+ if ( ! prefixIsSets )
263+ {
264+ if ( prefixIsGetsOrSets )
265+ {
266+ ReportSA1624 ( context , diagnosticLocation , diagnosticProperties , accessor : "set" , expectedStartingText : startingTextSets , startingTextToRemove : startingTextGetsOrSets ) ;
267+ }
268+ else
269+ {
270+ ReportSA1623 ( context , diagnosticLocation , diagnosticProperties , text , expectedStartingText : startingTextSets , unexpectedStartingText1 : startingTextGets ) ;
271+ }
272+ }
266273 }
267- else if ( ! text . StartsWith ( startingTextSets , StringComparison . OrdinalIgnoreCase ) )
274+ else
268275 {
269- diagnosticProperties . Add ( ExpectedTextKey , startingTextSets ) ;
270- context . ReportDiagnostic ( Diagnostic . Create ( SA1623Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , startingTextSets ) ) ;
276+ // Setter exists and is visible. Getter does not exist.
277+ if ( ! prefixIsSets )
278+ {
279+ ReportSA1623 ( context , diagnosticLocation , diagnosticProperties , text , expectedStartingText : startingTextSets , unexpectedStartingText1 : startingTextGetsOrSets , unexpectedStartingText2 : startingTextGets ) ;
280+ }
271281 }
272282 }
273283 }
284+
285+ private static void ReportSA1623 ( SyntaxNodeAnalysisContext context , Location diagnosticLocation , ImmutableDictionary < string , string > . Builder diagnosticProperties , string text , string expectedStartingText , string unexpectedStartingText1 , string unexpectedStartingText2 = null )
286+ {
287+ diagnosticProperties . Add ( ExpectedTextKey , expectedStartingText ) ;
288+
289+ if ( text . StartsWith ( unexpectedStartingText1 , StringComparison . OrdinalIgnoreCase ) )
290+ {
291+ diagnosticProperties . Add ( TextToRemoveKey , text . Substring ( 0 , unexpectedStartingText1 . Length ) ) ;
292+ }
293+ else if ( ( unexpectedStartingText2 != null ) && text . StartsWith ( unexpectedStartingText2 , StringComparison . OrdinalIgnoreCase ) )
294+ {
295+ diagnosticProperties . Add ( TextToRemoveKey , text . Substring ( 0 , unexpectedStartingText2 . Length ) ) ;
296+ }
297+
298+ context . ReportDiagnostic ( Diagnostic . Create ( SA1623Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , expectedStartingText ) ) ;
299+ }
300+
301+ private static void ReportSA1624 ( SyntaxNodeAnalysisContext context , Location diagnosticLocation , ImmutableDictionary < string , string > . Builder diagnosticProperties , string accessor , string expectedStartingText , string startingTextToRemove )
302+ {
303+ diagnosticProperties . Add ( ExpectedTextKey , expectedStartingText ) ;
304+ diagnosticProperties . Add ( TextToRemoveKey , startingTextToRemove ) ;
305+ context . ReportDiagnostic ( Diagnostic . Create ( SA1624Descriptor , diagnosticLocation , diagnosticProperties . ToImmutable ( ) , accessor , expectedStartingText ) ) ;
306+ }
274307 }
275308}
0 commit comments