public static TextSpan GetSpanWithoutAttributes(this ISyntaxFacts syntaxFacts, SyntaxNode root, SyntaxNode node) { // Span without AttributeLists // - No AttributeLists -> original .Span // - Some AttributeLists -> (first non-trivia/comment Token.Span.Begin, original.Span.End) // - We need to be mindful about comments due to: // // [Test1] // //Comment1 // [||]object Property1 { get; set; } // the comment node being part of the next token's (`object`) leading trivia and not the AttributeList's node. // - In case only attribute is written we need to be careful to not to use next (unrelated) token as beginning current the node. var attributeList = syntaxFacts.GetAttributeLists(node); if (attributeList.Any()) { var endOfAttributeLists = attributeList.Last().Span.End; var afterAttributesToken = root.FindTokenOnRightOfPosition(endOfAttributeLists); var endOfNode = node.Span.End; var startOfNodeWithoutAttributes = Math.Min(afterAttributesToken.Span.Start, endOfNode); return(TextSpan.FromBounds(startOfNodeWithoutAttributes, endOfNode)); } return(node.Span); }