@@ -60,124 +60,42 @@ private static void HandleCompilationStart(CompilationStartAnalysisContext conte
6060
6161 private static void HandleSyntaxTree ( SyntaxTreeAnalysisContext context , StyleCopSettings settings )
6262 {
63- SyntaxTree syntaxTree = context . Tree ;
64- SourceText sourceText = syntaxTree . GetText ( context . CancellationToken ) ;
65-
66- ImmutableArray < TextSpan > convertToTabsSpans ;
67- ImmutableArray < TextSpan > convertToSpacesSpans ;
68- if ( ! LocateIncorrectTabUsage ( sourceText , settings . Indentation , out convertToTabsSpans , out convertToSpacesSpans ) )
69- {
70- return ;
71- }
72-
73- SyntaxNode root = syntaxTree . GetCompilationUnitRoot ( context . CancellationToken ) ;
63+ SyntaxNode root = context . Tree . GetCompilationUnitRoot ( context . CancellationToken ) ;
7464 ImmutableArray < TextSpan > excludedSpans ;
7565 if ( ! LocateExcludedSpans ( root , out excludedSpans ) )
7666 {
7767 return ;
7868 }
7969
80- int toTabsIndex = 0 ;
81- int toSpacesIndex = 0 ;
82-
83- for ( int excludedIndex = 0 ; excludedIndex < excludedSpans . Length ; excludedIndex ++ )
84- {
85- TextSpan excluded = excludedSpans [ excludedIndex ] ;
86-
87- while ( toTabsIndex < convertToTabsSpans . Length )
88- {
89- TextSpan included = convertToTabsSpans [ toTabsIndex ] ;
90- if ( included . Start >= excluded . End )
91- {
92- // Doesn't overlap the current excluded span, but might overlap the next
93- break ;
94- }
95-
96- if ( included . Start < excluded . Start )
97- {
98- int violationStart = included . Start ;
99- int violationEnd = Math . Min ( included . End , excluded . Start ) ;
100-
101- context . ReportDiagnostic (
102- Diagnostic . Create (
103- Descriptor ,
104- Location . Create ( syntaxTree , TextSpan . FromBounds ( violationStart , violationEnd ) ) ,
105- ConvertToTabsProperties ) ) ;
106- }
107-
108- if ( included . End > excluded . End )
109- {
110- // It overlapped the current excluded span, and might also overlap the next
111- break ;
112- }
113-
114- toTabsIndex ++ ;
115- }
116-
117- while ( toSpacesIndex < convertToSpacesSpans . Length )
118- {
119- TextSpan included = convertToSpacesSpans [ toSpacesIndex ] ;
120- if ( included . Start >= excluded . End )
121- {
122- // Doesn't overlap the current excluded span, but might overlap the next
123- break ;
124- }
125-
126- if ( included . Start < excluded . Start )
127- {
128- int violationStart = included . Start ;
129- int violationEnd = Math . Min ( included . End , excluded . Start ) ;
130-
131- context . ReportDiagnostic (
132- Diagnostic . Create (
133- Descriptor ,
134- Location . Create ( syntaxTree , TextSpan . FromBounds ( violationStart , violationEnd ) ) ,
135- ConvertToSpacesProperties ) ) ;
136- }
137-
138- if ( included . End > excluded . End )
139- {
140- // It overlapped the current excluded span, and might also overlap the next
141- break ;
142- }
143-
144- toSpacesIndex ++ ;
145- }
146- }
147-
148- for ( ; toTabsIndex < convertToTabsSpans . Length ; toTabsIndex ++ )
149- {
150- context . ReportDiagnostic (
151- Diagnostic . Create (
152- Descriptor ,
153- Location . Create ( syntaxTree , convertToTabsSpans [ toTabsIndex ] ) ,
154- ConvertToTabsProperties ) ) ;
155- }
156-
157- for ( ; toSpacesIndex < convertToSpacesSpans . Length ; toSpacesIndex ++ )
158- {
159- context . ReportDiagnostic (
160- Diagnostic . Create (
161- Descriptor ,
162- Location . Create ( syntaxTree , convertToSpacesSpans [ toSpacesIndex ] ) ,
163- ConvertToSpacesProperties ) ) ;
164- }
70+ ReportIncorrectTabUsage ( context , settings . Indentation , excludedSpans ) ;
16571 }
16672
167- private static bool LocateIncorrectTabUsage ( SourceText sourceText , IndentationSettings indentationSettings , out ImmutableArray < TextSpan > convertToTabsSpans , out ImmutableArray < TextSpan > convertToSpacesSpans )
73+ private static void ReportIncorrectTabUsage ( SyntaxTreeAnalysisContext context , IndentationSettings indentationSettings , ImmutableArray < TextSpan > excludedSpans )
16874 {
169- ImmutableArray < TextSpan > . Builder toTabsBuilder = ImmutableArray . CreateBuilder < TextSpan > ( ) ;
170- ImmutableArray < TextSpan > . Builder toSpacesBuilder = ImmutableArray . CreateBuilder < TextSpan > ( ) ;
75+ SyntaxTree syntaxTree = context . Tree ;
76+ SourceText sourceText = syntaxTree . GetText ( context . CancellationToken ) ;
17177
17278 string completeText = sourceText . ToString ( ) ;
17379 int length = completeText . Length ;
17480
17581 bool useTabs = indentationSettings . UseTabs ;
17682 int tabSize = indentationSettings . TabSize ;
17783
84+ int excludedSpanIndex = 0 ;
85+ var lastExcludedSpan = new TextSpan ( completeText . Length , 0 ) ;
86+ TextSpan nextExcludedSpan = ! excludedSpans . IsEmpty ? excludedSpans [ 0 ] : lastExcludedSpan ;
87+
17888 int lastLineStart = 0 ;
17989 for ( int startIndex = 0 ; startIndex < length ; startIndex ++ )
18090 {
91+ if ( startIndex == nextExcludedSpan . Start )
92+ {
93+ startIndex = nextExcludedSpan . End - 1 ;
94+ excludedSpanIndex ++ ;
95+ nextExcludedSpan = excludedSpanIndex < excludedSpans . Length ? excludedSpans [ excludedSpanIndex ] : lastExcludedSpan ;
96+ continue ;
97+ }
98+
18199 int tabCount = 0 ;
182100 bool containsSpaces = false ;
183101 bool tabAfterSpace = false ;
@@ -205,6 +123,11 @@ private static bool LocateIncorrectTabUsage(SourceText sourceText, IndentationSe
205123 int endIndex ;
206124 for ( endIndex = startIndex + 1 ; endIndex < length ; endIndex ++ )
207125 {
126+ if ( endIndex == nextExcludedSpan . Start )
127+ {
128+ break ;
129+ }
130+
208131 if ( completeText [ endIndex ] == ' ' )
209132 {
210133 containsSpaces = true ;
@@ -227,24 +150,28 @@ private static bool LocateIncorrectTabUsage(SourceText sourceText, IndentationSe
227150 int spaceCount = ( endIndex - startIndex ) - tabCount ;
228151 if ( tabAfterSpace || spaceCount >= tabSize )
229152 {
230- toTabsBuilder . Add ( TextSpan . FromBounds ( startIndex , endIndex ) ) ;
153+ context . ReportDiagnostic (
154+ Diagnostic . Create (
155+ Descriptor ,
156+ Location . Create ( syntaxTree , TextSpan . FromBounds ( startIndex , endIndex ) ) ,
157+ ConvertToTabsProperties ) ) ;
231158 }
232159 }
233160 else
234161 {
235162 if ( tabCount > 0 )
236163 {
237- toSpacesBuilder . Add ( TextSpan . FromBounds ( startIndex , endIndex ) ) ;
164+ context . ReportDiagnostic (
165+ Diagnostic . Create (
166+ Descriptor ,
167+ Location . Create ( syntaxTree , TextSpan . FromBounds ( startIndex , endIndex ) ) ,
168+ ConvertToSpacesProperties ) ) ;
238169 }
239170 }
240171
241172 // Make sure to not analyze overlapping spans
242173 startIndex = endIndex - 1 ;
243174 }
244-
245- convertToTabsSpans = toTabsBuilder . ToImmutable ( ) ;
246- convertToSpacesSpans = toSpacesBuilder . ToImmutable ( ) ;
247- return true ;
248175 }
249176
250177 private static bool LocateExcludedSpans ( SyntaxNode root , out ImmutableArray < TextSpan > excludedSpans )
0 commit comments