@@ -196,9 +196,9 @@ private static void HandleMemberList(SyntaxNodeAnalysisContext context, SyntaxLi
196196 // or the previous declaration is of different type
197197 // or the current declaration has documentation
198198 // or the current declaration is not a field declaration,
199- if ( IsMultiline ( members [ i - 1 ] )
200- || ! members [ i - 1 ] . IsKind ( members [ i ] . Kind ( ) )
201- || ! members [ i ] . IsKind ( SyntaxKind . FieldDeclaration ) )
199+ if ( ! members [ i - 1 ] . IsKind ( members [ i ] . Kind ( ) )
200+ || ! members [ i ] . IsKind ( SyntaxKind . FieldDeclaration )
201+ || IsMultiline ( members [ i - 1 ] ) )
202202 {
203203 ReportIfThereIsNoBlankLine ( context , members [ i - 1 ] , members [ i ] ) ;
204204 }
@@ -209,8 +209,21 @@ private static void HandleMemberList(SyntaxNodeAnalysisContext context, SyntaxLi
209209 private static bool IsMultiline ( SyntaxNode node )
210210 {
211211 var lineSpan = node . GetLineSpan ( ) ;
212+ var attributes = GetAttributes ( node ) ;
213+ int startLine ;
212214
213- return lineSpan . StartLinePosition . Line != lineSpan . EndLinePosition . Line ;
215+ // Exclude attributes when determining if a node spans multiple lines
216+ if ( attributes . Count > 0 )
217+ {
218+ var lastAttributeSpan = node . SyntaxTree . GetLineSpan ( attributes . Last ( ) . FullSpan ) ;
219+ startLine = lastAttributeSpan . EndLinePosition . Line ;
220+ }
221+ else
222+ {
223+ startLine = lineSpan . StartLinePosition . Line ;
224+ }
225+
226+ return startLine != lineSpan . EndLinePosition . Line ;
214227 }
215228
216229 private static void ReportIfThereIsNoBlankLine ( SyntaxNodeAnalysisContext context , SyntaxNode firstNode , SyntaxNode secondNode )
@@ -270,5 +283,52 @@ private static bool HasEmptyLine(IEnumerable<SyntaxTrivia> allTrivia)
270283
271284 return false ;
272285 }
286+
287+ // copied from Roslyn code, as its inaccessible there
288+ // (from Microsoft.CodeAnalysis.CSharp.Extensions.MemberDeclarationSyntaxExtensions)
289+ private static SyntaxList < AttributeListSyntax > GetAttributes ( SyntaxNode node )
290+ {
291+ var memberDeclaration = node as MemberDeclarationSyntax ;
292+ if ( memberDeclaration != null )
293+ {
294+ switch ( memberDeclaration . Kind ( ) )
295+ {
296+ case SyntaxKind . EnumDeclaration :
297+ return ( ( EnumDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
298+ case SyntaxKind . EnumMemberDeclaration :
299+ return ( ( EnumMemberDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
300+ case SyntaxKind . ClassDeclaration :
301+ case SyntaxKind . InterfaceDeclaration :
302+ case SyntaxKind . StructDeclaration :
303+ return ( ( TypeDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
304+ case SyntaxKind . DelegateDeclaration :
305+ return ( ( DelegateDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
306+ case SyntaxKind . FieldDeclaration :
307+ return ( ( FieldDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
308+ case SyntaxKind . EventFieldDeclaration :
309+ return ( ( EventFieldDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
310+ case SyntaxKind . ConstructorDeclaration :
311+ return ( ( ConstructorDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
312+ case SyntaxKind . DestructorDeclaration :
313+ return ( ( DestructorDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
314+ case SyntaxKind . PropertyDeclaration :
315+ return ( ( PropertyDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
316+ case SyntaxKind . EventDeclaration :
317+ return ( ( EventDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
318+ case SyntaxKind . IndexerDeclaration :
319+ return ( ( IndexerDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
320+ case SyntaxKind . OperatorDeclaration :
321+ return ( ( OperatorDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
322+ case SyntaxKind . ConversionOperatorDeclaration :
323+ return ( ( ConversionOperatorDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
324+ case SyntaxKind . MethodDeclaration :
325+ return ( ( MethodDeclarationSyntax ) memberDeclaration ) . AttributeLists ;
326+ case SyntaxKind . IncompleteMember :
327+ return ( ( IncompleteMemberSyntax ) memberDeclaration ) . AttributeLists ;
328+ }
329+ }
330+
331+ return SyntaxFactory . List < AttributeListSyntax > ( ) ;
332+ }
273333 }
274334}
0 commit comments