|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable disable
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
using InternalSyntax = Microsoft.CodeAnalysis.CSharp.Syntax.InternalSyntax;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class TrackNodeTests
{
[Fact]
public void TestGetCurrentNodeAfterTrackNodesReturnsCurrentNode()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var a = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(a);
var currentA = trackedExpr.GetCurrentNode(a);
Assert.NotNull(currentA);
Assert.Equal("a", currentA.ToString());
}
[Fact]
public void TestGetCurrentNodesAfterTrackNodesReturnsSingletonSequence()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var a = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(a);
var currentAs = trackedExpr.GetCurrentNodes(a);
Assert.NotNull(currentAs);
Assert.Equal(1, currentAs.Count());
Assert.Equal("a", currentAs.ElementAt(0).ToString());
}
[Fact]
public void TestGetCurrentNodeWithoutTrackNodesReturnsNull()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var a = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var currentA = expr.GetCurrentNode(a);
Assert.Null(currentA);
}
[Fact]
public void TestGetCurrentNodesWithoutTrackNodesReturnsEmptySequence()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var a = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var currentAs = expr.GetCurrentNodes(a);
Assert.NotNull(currentAs);
Assert.Equal(0, currentAs.Count());
}
[Fact]
public void TestGetCurrentNodeAfterEditReturnsCurrentNode()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
var newA = currentA.WithLeadingTrivia(SyntaxFactory.Comment("/* ayup */"));
var replacedExpr = trackedExpr.ReplaceNode(currentA, newA);
var latestA = replacedExpr.GetCurrentNode(originalA);
Assert.NotNull(latestA);
Assert.NotSame(latestA, newA); // not the same reference
Assert.Equal(newA.ToFullString(), latestA.ToFullString());
}
[Fact]
public void TestGetCurrentNodeAfterEditReturnsSingletonSequence()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
var newA = currentA.WithLeadingTrivia(SyntaxFactory.Comment("/* ayup */"));
var replacedExpr = trackedExpr.ReplaceNode(currentA, newA);
var latestAs = replacedExpr.GetCurrentNodes(originalA);
Assert.NotNull(latestAs);
Assert.Equal(1, latestAs.Count());
Assert.Equal(newA.ToFullString(), latestAs.ElementAt(0).ToFullString());
}
[WorkItem(1070667, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/1070667")]
[Fact]
public void TestGetCurrentNodeAfterRemovalReturnsNull()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
var replacedExpr = trackedExpr.ReplaceNode(currentA, SyntaxFactory.IdentifierName("c"));
var latestA = replacedExpr.GetCurrentNode(originalA);
Assert.Null(latestA);
}
[Fact]
public void TestGetCurrentNodesAfterRemovalEmptySequence()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
var replacedExpr = trackedExpr.ReplaceNode(currentA, SyntaxFactory.IdentifierName("c"));
var latestAs = replacedExpr.GetCurrentNodes(originalA);
Assert.NotNull(latestAs);
Assert.Equal(0, latestAs.Count());
}
[Fact]
public void TestGetCurrentNodeAfterAddingMultipleThrows()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
// replace all identifiers with same 'a'
var replacedExpr = trackedExpr.ReplaceNodes(trackedExpr.DescendantNodes().OfType<IdentifierNameSyntax>(), (original, changed) => currentA);
Assert.Throws<InvalidOperationException>(() => replacedExpr.GetCurrentNode(originalA));
}
[Fact]
public void TestGetCurrentNodeAfterAddingMultipleReturnsMultiple()
{
var expr = SyntaxFactory.ParseExpression("a + b");
var originalA = expr.DescendantNodes().OfType<IdentifierNameSyntax>().First(n => n.Identifier.Text == "a");
var trackedExpr = expr.TrackNodes(originalA);
var currentA = trackedExpr.GetCurrentNode(originalA);
// replace all identifiers with same 'a'
var replacedExpr = trackedExpr.ReplaceNodes(trackedExpr.DescendantNodes().OfType<IdentifierNameSyntax>(), (original, changed) => currentA);
var nodes = replacedExpr.GetCurrentNodes(originalA).ToList();
Assert.Equal(2, nodes.Count);
Assert.Equal("a", nodes[0].ToString());
Assert.Equal("a", nodes[1].ToString());
}
[Fact]
public void TestTrackNodesWithMultipleTracksAllNodes()
{
var expr = SyntaxFactory.ParseExpression("a + b + c");
var ids = expr.DescendantNodes().OfType<IdentifierNameSyntax>().ToList();
var trackedExpr = expr.TrackNodes(ids);
Assert.Equal(3, ids.Count);
foreach (var id in ids)
{
var currentId = trackedExpr.GetCurrentNode(id);
Assert.NotNull(currentId);
Assert.NotSame(id, currentId);
Assert.Equal(id.ToString(), currentId.ToString());
}
}
[Fact]
public void TestTrackNodesWithNoNodesTracksNothing()
{
var expr = SyntaxFactory.ParseExpression("a + b + c");
var ids = expr.DescendantNodes().OfType<IdentifierNameSyntax>().ToList();
var trackedExpr = expr.TrackNodes();
Assert.Equal(3, ids.Count);
foreach (var id in ids)
{
var currentId = trackedExpr.GetCurrentNode(id);
Assert.Null(currentId);
}
}
[Fact]
public void TestTrackNodeThatIsNotInTheSubtreeThrows()
{
var expr = SyntaxFactory.ParseExpression("a + b");
Assert.Throws<ArgumentException>(() => expr.TrackNodes(SyntaxFactory.IdentifierName("c")));
}
}
}
|