-
Notifications
You must be signed in to change notification settings - Fork 4.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Don't format regions inside inactive conditionals #64551
Conversation
else | ||
{ | ||
return LineColumnRule.Preserve; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this likely warrants docs :)
// skip whitespace trivia. | ||
} | ||
|
||
if (!previous.IsKind(SyntaxKind.DisabledTextTrivia)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit, consider inverting.
var previous = trivia2; | ||
while ((previous = previous.GetPreviousTrivia(previous.SyntaxTree, CancellationToken.None)).IsKind(SyntaxKind.WhitespaceTrivia)) | ||
{ | ||
// skip whitespace trivia. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
needs more explanation :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about end-of-line trivia?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
what about end-of-line trivia?
The following test just passes:
[Fact]
public async Task TestRegion2()
{
var testCode = @"
class MyClass
{
#if true
public void M()
{
[||]#region ABC
System.Console.WriteLine();
[||]#endregion
}
#else
public void M()
{
#region ABC
System.Console.WriteLine();
#endregion
}
#endif
}
";
var fixedCode = @"
class MyClass
{
#if true
public void M()
{
#region ABC
System.Console.WriteLine();
#endregion
}
#else
public void M()
{
#region ABC
System.Console.WriteLine();
#endregion
}
#endif
}
";
await Verify.VerifyCodeFixAsync(testCode, fixedCode);
}
(I'll definitely commit and push it)
'#region'.GetPreviousTrivia(..)
is not an end of line trivia for this case though.
Do you have an interesting test case where the tree will have end of line trivia?
I found a niche case where my logic is incorrect apart from EOL trivia:
#region OUTER
#region ABC
System.Console.WriteLine();
#endregion
#endregion
Here, after we go back consuming whitespace trivia, we don't find a disabled text, but we are in disabled text.
Is there a compiler API for the "Is this position conditionally excluded?" question?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does IsInInactiveRegion work?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CyrusNajmabadi It doesn't 😕
Lines 477 to 538 in 75bbc51
public static bool IsInInactiveRegion( | |
this SyntaxTree syntaxTree, int position, CancellationToken cancellationToken) | |
{ | |
Contract.ThrowIfNull(syntaxTree); | |
// cases: | |
// $ is EOF | |
// #if false | |
// | | |
// #if false | |
// |$ | |
// #if false | |
// | | |
// #if false | |
// |$ | |
if (syntaxTree.IsPreProcessorKeywordContext(position, cancellationToken)) | |
{ | |
return false; | |
} | |
// The latter two are the hard cases we don't actually have an | |
// DisabledTextTrivia yet. | |
var trivia = syntaxTree.GetRoot(cancellationToken).FindTrivia(position, findInsideTrivia: false); | |
if (trivia.Kind() == SyntaxKind.DisabledTextTrivia) | |
{ | |
return true; | |
} | |
var token = syntaxTree.FindTokenOrEndToken(position, cancellationToken); | |
if (token.Kind() == SyntaxKind.EndOfFileToken) | |
{ | |
var triviaList = token.LeadingTrivia; | |
foreach (var triviaTok in triviaList.Reverse()) | |
{ | |
if (triviaTok.Span.Contains(position)) | |
{ | |
return false; | |
} | |
if (triviaTok.Span.End < position) | |
{ | |
if (!triviaTok.HasStructure) | |
{ | |
return false; | |
} | |
var structure = triviaTok.GetStructure(); | |
if (structure is BranchingDirectiveTriviaSyntax branch) | |
{ | |
return !branch.IsActive || !branch.BranchTaken; | |
} | |
} | |
} | |
} | |
return false; | |
} |
That seems a hard-to-answer question on the IDE side.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems a hard-to-answer question on the IDE side.
Not really. I think I see how I can do it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@CyrusNajmabadi This is ready for another look now :)
Currently failing test: Microsoft.CodeAnalysis.CSharp.UnitTests.Formatting.FormattingEngineTriviaTests.MixAll |
Fixed. Not an ideal fix though, just falling back to the original behavior for edge cases that are harder to handle. |
@CyrusNajmabadi Can you take a look please? Thanks! |
...aredUtilitiesAndExtensions/Compiler/CSharp/Formatting/Engine/Trivia/CSharpTriviaFormatter.cs
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tentative approval. but would like answer to question posed.
Fixes #62612