Skip to content

Commit 83cd527

Browse files
committed
Improve indentation analysis (RCS0054)
1 parent 7615293 commit 83cd527

File tree

3 files changed

+166
-2
lines changed

3 files changed

+166
-2
lines changed

src/CSharp/CSharp/IndentationAnalysis.cs

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,33 @@ SyntaxTrivia DetermineIndentationSize(CompilationUnitSyntax compilationUnit)
235235
if (member2 != null)
236236
return SyntaxTriviaAnalysis.DetermineIndentation(member2, cancellationToken);
237237
}
238+
else if (member is GlobalStatementSyntax globalStatement)
239+
{
240+
StatementSyntax statement2 = globalStatement.Statement;
241+
242+
if (statement2 is SwitchStatementSyntax switchStatement)
243+
{
244+
SwitchSectionSyntax switchSection = switchStatement.Sections.FirstOrDefault();
245+
246+
if (switchSection is not null)
247+
return SyntaxTriviaAnalysis.DetermineIndentation(switchSection, cancellationToken);
248+
249+
break;
250+
}
251+
else
252+
{
253+
StatementSyntax statement3 = GetContainedStatement(statement2);
254+
255+
if (statement3 is not null)
256+
{
257+
if (statement3 is BlockSyntax block)
258+
statement3 = block.Statements.FirstOrDefault();
259+
260+
if (statement3 is not null)
261+
return SyntaxTriviaAnalysis.DetermineIndentation(statement3, cancellationToken);
262+
}
263+
}
264+
}
238265
}
239266

240267
return default;
@@ -260,6 +287,50 @@ SyntaxTrivia DetermineIndentationSize(CompilationUnitSyntax compilationUnit)
260287

261288
return default;
262289
}
290+
291+
StatementSyntax GetContainedStatement(StatementSyntax statement)
292+
{
293+
switch (statement.Kind())
294+
{
295+
case SyntaxKind.WhileStatement:
296+
return ((WhileStatementSyntax)statement).Statement;
297+
298+
case SyntaxKind.DoStatement:
299+
return ((DoStatementSyntax)statement).Statement;
300+
301+
case SyntaxKind.ForStatement:
302+
return ((ForStatementSyntax)statement).Statement;
303+
304+
case SyntaxKind.ForEachStatement:
305+
case SyntaxKind.ForEachVariableStatement:
306+
return ((CommonForEachStatementSyntax)statement).Statement;
307+
308+
case SyntaxKind.UsingStatement:
309+
return ((UsingStatementSyntax)statement).Statement;
310+
311+
case SyntaxKind.FixedStatement:
312+
return ((FixedStatementSyntax)statement).Statement;
313+
314+
case SyntaxKind.CheckedStatement:
315+
case SyntaxKind.UncheckedStatement:
316+
return ((CheckedStatementSyntax)statement).Block;
317+
318+
case SyntaxKind.UnsafeStatement:
319+
return ((UnsafeStatementSyntax)statement).Block;
320+
321+
case SyntaxKind.LockStatement:
322+
return ((LockStatementSyntax)statement).Statement;
323+
324+
case SyntaxKind.IfStatement:
325+
return ((IfStatementSyntax)statement).Statement;
326+
327+
case SyntaxKind.TryStatement:
328+
return ((TryStatementSyntax)statement).Block;
329+
330+
default:
331+
return null;
332+
}
333+
}
263334
}
264335
}
265336
}

src/Formatting.Analyzers/CSharp/FixFormattingOfCallChainAnalyzer.cs

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,13 @@ bool AnalyzeToken(SyntaxToken token)
123123
int endLine = lines.IndexOf(token.SpanStart);
124124

125125
if (startLine != endLine)
126-
ReportDiagnostic();
126+
{
127+
if (!indentationAnalysis.IsDefault
128+
|| !AnalyzeIndentation(expression).IsDefault)
129+
{
130+
ReportDiagnostic();
131+
}
132+
}
127133

128134
return true;
129135
}
@@ -133,8 +139,13 @@ bool AnalyzeToken(SyntaxToken token)
133139
case SyntaxKind.WhitespaceTrivia:
134140
{
135141
if (indentationAnalysis.IsDefault)
142+
{
136143
indentationAnalysis = AnalyzeIndentation(expression);
137144

145+
if (indentationAnalysis.IsDefault)
146+
return true;
147+
}
148+
138149
if (en.Current.Span.Length != indentationAnalysis.IncreasedIndentationLength)
139150
{
140151
if (!en.MoveNext()
@@ -156,7 +167,12 @@ bool AnalyzeToken(SyntaxToken token)
156167
{
157168
if (expression.FindTrivia(token.FullSpan.Start - 1).IsEndOfLineTrivia())
158169
{
159-
ReportDiagnostic();
170+
if (!indentationAnalysis.IsDefault
171+
|| !AnalyzeIndentation(expression).IsDefault)
172+
{
173+
ReportDiagnostic();
174+
}
175+
160176
return true;
161177
}
162178

src/Tests/Formatting.Analyzers.Tests/RCS0054FixFormattingOfCallChainTests.cs

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,60 @@ C M(string s)
314314
");
315315
}
316316

317+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
318+
public async Task Test_TopLevelStatement_SwitchStatement()
319+
{
320+
await VerifyDiagnosticAndFixAsync(@"
321+
var s = """";
322+
323+
s = [|s.ToString().ToString()
324+
.ToString()|];
325+
326+
switch (s)
327+
{
328+
default:
329+
break;
330+
}
331+
", @"
332+
var s = """";
333+
334+
s = s.ToString().ToString()
335+
.ToString();
336+
337+
switch (s)
338+
{
339+
default:
340+
break;
341+
}
342+
", options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication)));
343+
}
344+
345+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
346+
public async Task Test_TopLevelStatement_ForEachStatement()
347+
{
348+
await VerifyDiagnosticAndFixAsync(@"
349+
var s = """";
350+
351+
s = [|s.ToString().ToString()
352+
.ToString()|];
353+
354+
foreach (char ch in s)
355+
{
356+
var x = ch;
357+
}
358+
", @"
359+
var s = """";
360+
361+
s = s.ToString().ToString()
362+
.ToString();
363+
364+
foreach (char ch in s)
365+
{
366+
var x = ch;
367+
}
368+
", options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication)));
369+
}
370+
317371
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
318372
public async Task Test_TopLevelStatement()
319373
{
@@ -332,6 +386,29 @@ void Main(string[] args)
332386
", options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication)));
333387
}
334388

389+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
390+
public async Task Test_TopLevelStatement2()
391+
{
392+
await VerifyNoDiagnosticAsync(@"
393+
var s = """";
394+
395+
s = s.ToString().ToString()
396+
.ToString();
397+
", options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication)));
398+
}
399+
400+
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
401+
public async Task Test_TopLevelStatement3()
402+
{
403+
await VerifyNoDiagnosticAsync(@"
404+
var s = """";
405+
406+
s = s.ToString().ToString()
407+
408+
.ToString();
409+
", options: Options.WithCompilationOptions(Options.CompilationOptions.WithOutputKind(OutputKind.ConsoleApplication)));
410+
}
411+
335412
[Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.FixFormattingOfCallChain)]
336413
public async Task TestNoDiagnostic()
337414
{

0 commit comments

Comments
 (0)