diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxDiffingTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxDiffingTests.cs index 9718a27a6b42d62cdb421703f40d82d6a43e2904..c245c9eab6b3b0d4971e3b2b441c670df4259ccd 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxDiffingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxDiffingTests.cs @@ -1,9 +1,10 @@ // Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; -using Microsoft.CodeAnalysis.CSharp.Symbols; +using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.Text; +using Roslyn.Test.Utilities; using Xunit; namespace Microsoft.CodeAnalysis.CSharp.UnitTests @@ -253,7 +254,7 @@ public void TestDiffClassChangedToStruct() Assert.Equal("struct", changes[0].NewText); } - [Fact] + [Fact, WorkItem(463, "https://github.com/dotnet/roslyn/issues/463")] public void TestQualifyWithThis() { var original = @" @@ -319,5 +320,69 @@ private void TestQualifyWithThisCore(SyntaxNode root, int index) Assert.Equal(1, changes.Count); Assert.Equal("this.", changes[0].NewText); } + + [Fact(Skip = "463"), WorkItem(463, "https://github.com/dotnet/roslyn/issues/463")] + public void TestReplaceWithBuiltInType() + { + var original = @" +using System; +using System.Collections.Generic; + +public class TestClass +{ + public void TestMethod() + { + var dictionary = new Dictionary(); + dictionary[new Object()] = new Object(); + } +}"; + var oldTree = SyntaxFactory.ParseSyntaxTree(original); + var root = oldTree.GetRoot(); + + var indexText = "Object"; + + // Expected behavior: Replacing identifier 'Object' with 'object' and doing a diff between trees + // should return a single text change for character replace. + + // Works as expected for first index + var index = original.IndexOf(indexText, StringComparison.Ordinal); + TestReplaceWithBuiltInTypeCore(root, index); + + // Works as expected for last index + index = original.LastIndexOf(indexText, StringComparison.Ordinal); + TestReplaceWithBuiltInTypeCore(root, index); + + // Doesn't work as expected for the third index. + // It returns 2 changes with add followed by delete, + // causing the 2 isolated edits to seem conflicting edits, even though they are not. + // See https://github.com/dotnet/roslyn/issues/320 for details. + indexText = "Object()"; + index = original.IndexOf(indexText, StringComparison.Ordinal); + TestReplaceWithBuiltInTypeCore(root, index); + } + + private void TestReplaceWithBuiltInTypeCore(SyntaxNode root, int index) + { + var oldTree = root.SyntaxTree; + + var nodesToReplace = root.DescendantNodes().Where(n => n is SimpleNameSyntax && n.ToString() == "Object"); + + var span = new TextSpan(index, 6); + var node = root.FindNode(span, getInnermostNodeForTie: true) as SimpleNameSyntax; + Assert.NotNull(node); + Assert.Equal("Object", node.Identifier.ValueText); + + var leadingTrivia = node.GetLeadingTrivia(); + var newNode = SyntaxFactory.PredefinedType(SyntaxFactory.Token(SyntaxKind.ObjectKeyword)) + .WithLeadingTrivia(leadingTrivia); + + var newRoot = root.ReplaceNode(node, newNode); + var newTree = newRoot.SyntaxTree; + + var changes = newTree.GetChanges(oldTree); + Assert.NotNull(changes); + Assert.Equal(1, changes.Count); + Assert.Equal("o", changes[0].NewText); + } } }