Skip to content

Commit

Permalink
Preserve trivia when simplifier removes unnecessary this / Me keywords.
Browse files Browse the repository at this point in the history
Fixes #50
  • Loading branch information
shyamnamboodiripad committed Apr 21, 2015
1 parent 0a54d67 commit d9fc374
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 2 deletions.
36 changes: 36 additions & 0 deletions src/EditorFeatures/Test2/Simplification/TypeNameSimplifierTest.vb
Original file line number Diff line number Diff line change
Expand Up @@ -1426,6 +1426,42 @@ public class C
Test(input, expected)
End Sub

<Fact, Trait(Traits.Feature, Traits.Features.Simplification)>
<WorkItem(50, "https://github.com/dotnet/roslyn/issues/50")>
Public Sub TestCSRemoveThisPreservesTrivia()
Dim input =
<Workspace>
<Project Language="C#" CommonReferences="true">
<Document>
class C1
{
int _field;

void M()
{
this /*comment 1*/ . /* comment 2 */ {|SimplifyParent:_field|} /* comment 3 */ = 0;
}
}
</Document>
</Project>
</Workspace>

Dim expected =
<code>
class C1
{
int _field;

void M()
{
/*comment 1*/ /* comment 2 */ _field /* comment 3 */ = 0;
}
}
</code>

Test(input, expected)
End Sub

<WorkItem(649385)>
<Fact, Trait(Traits.Feature, Traits.Features.Simplification)>
Public Sub CSharpSimplifyToVarCorrect()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -773,7 +773,9 @@ private static bool TryReduce(
}
}

replacementNode = memberAccess.Name.WithLeadingTrivia(memberAccess.GetLeadingTrivia()).WithTrailingTrivia(memberAccess.GetTrailingTrivia());
replacementNode = memberAccess.Name
.WithLeadingTrivia(memberAccess.GetLeadingTriviaForSimplifiedMemberAccess())
.WithTrailingTrivia(memberAccess.GetTrailingTrivia());
issueSpan = memberAccess.Expression.Span;

if (replacementNode == null)
Expand All @@ -784,6 +786,24 @@ private static bool TryReduce(
return memberAccess.CanReplaceWithReducedName(replacementNode, semanticModel, cancellationToken);
}

private static SyntaxTriviaList GetLeadingTriviaForSimplifiedMemberAccess(this MemberAccessExpressionSyntax memberAccess)
{
// We want to include any user-typed trivia that may be present between the 'Expression', 'OperatorToken' and 'Identifier' of the MemberAccessExpression.
// However, we don't want to include any elastic trivia that may have been introduced by the expander in these locations. This is to avoid triggering
// aggressive formatting. Otherwise, formatter will see this elastic trivia added by the expander and use that as a cue to introduce unnecessary blank lines
// etc. around the user's original code.
return memberAccess.GetLeadingTrivia()
.AddRange(memberAccess.Expression.GetTrailingTrivia().WithoutElasticTrivia())
.AddRange(memberAccess.OperatorToken.LeadingTrivia.WithoutElasticTrivia())
.AddRange(memberAccess.OperatorToken.TrailingTrivia.WithoutElasticTrivia())
.AddRange(memberAccess.Name.GetLeadingTrivia().WithoutElasticTrivia());
}

private static IEnumerable<SyntaxTrivia> WithoutElasticTrivia(this IEnumerable<SyntaxTrivia> list)
{
return list.Where(t => !t.IsElastic());
}

private static bool InsideCrefReference(ExpressionSyntax expr)
{
var crefAttribute = expr.FirstAncestorOrSelf<XmlCrefAttributeSyntax>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1023,7 +1023,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
.WithIdentifier(VisualBasicSimplificationService.TryEscapeIdentifierToken(
memberAccess.Name.Identifier,
semanticModel)) _
.WithLeadingTrivia(memberAccess.GetLeadingTrivia())
.WithLeadingTrivia(memberAccess.GetLeadingTriviaForSimplifiedMemberAccess()) _
.WithTrailingTrivia(memberAccess.GetTrailingTrivia())
issueSpan = memberAccess.Expression.Span

If memberAccess.CanReplaceWithReducedName(replacementNode, semanticModel, cancellationToken) Then
Expand All @@ -1040,6 +1041,24 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Extensions
Return False
End Function

<Extension>
Private Function GetLeadingTriviaForSimplifiedMemberAccess(memberAccess As MemberAccessExpressionSyntax) As SyntaxTriviaList
' We want to include any user-typed trivia that may be present between the 'Expression', 'OperatorToken' and 'Identifier' of the MemberAccessExpression.
' However, we don't want to include any elastic trivia that may have been introduced by the expander in these locations. This is to avoid triggering
' aggressive formatting. Otherwise, formatter will see this elastic trivia added by the expander And use that as a cue to introduce unnecessary blank lines
' etc. around the user's original code.
Return memberAccess.GetLeadingTrivia().
AddRange(memberAccess.Expression.GetTrailingTrivia().WithoutElasticTrivia()).
AddRange(memberAccess.OperatorToken.LeadingTrivia.WithoutElasticTrivia()).
AddRange(memberAccess.OperatorToken.TrailingTrivia.WithoutElasticTrivia()).
AddRange(memberAccess.Name.GetLeadingTrivia().WithoutElasticTrivia())
End Function

<Extension>
Private Function WithoutElasticTrivia(list As IEnumerable(Of SyntaxTrivia)) As IEnumerable(Of SyntaxTrivia)
Return list.Where(Function(t) Not t.IsElastic())
End Function

Private Function InsideCrefReference(expr As ExpressionSyntax) As Boolean
Dim crefAttribute = expr.FirstAncestorOrSelf(Of XmlCrefAttributeSyntax)()
Return crefAttribute IsNot Nothing
Expand Down

0 comments on commit d9fc374

Please sign in to comment.