File: IncrementalParsing\ChangingIdentifiers.cs
Web Access
Project: src\src\Compilers\CSharp\Test\Syntax\Microsoft.CodeAnalysis.CSharp.Syntax.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.Syntax.UnitTests)
// 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 Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Xunit;
 
namespace Microsoft.CodeAnalysis.CSharp.UnitTests.IncrementalParsing
{
    // These tests test changing between different types of identifiers
    public class ChangingIdentifiers
    {
        internal enum NameTypes
        {
            SingleName,
            DottedName,
            GenericName,
            AliasedName,
            PredefinedName,
            ArrayName,
            PointerName,
 
            // Not done
            // ArrayRankSpecifier
            // Type Argument - TODO: How would we do this???
        }
 
        [Fact]
        public void BasicToDotted()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.DottedName, expressionValidator: nameTree =>
            {
                NodeValidators.DottedNameVerification(nameTree, "b", "b");
            });
        }
 
        [Fact]
        public void BasicToGeneric()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.GenericName, expressionValidator: nameTree =>
            {
                NodeValidators.GenericNameVerification(nameTree, "b", "T");
            });
        }
 
        [Fact]
        public void BasicToAlias()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.AliasedName, expressionValidator: nameTree =>
            {
                NodeValidators.AliasedNameVerification(nameTree, "b", "d");
            });
        }
 
        [Fact]
        public void BasicToArray()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.ArrayName, expressionValidator: nameTree =>
            {
                NodeValidators.ArrayNameVerification(nameTree, "b", 1);
            });
        }
 
        [Fact]
        public void BasicToPredefined()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.PredefinedName, expressionValidator: nameTree =>
            {
                NodeValidators.PredefinedNameVerification(nameTree, "int");
            });
        }
 
        [Fact]
        public void BasicToPointer()
        {
            MakeIncrementalNameChange(NameTypes.SingleName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        [Fact]
        public void GenericToDotted()
        {
            MakeIncrementalNameChange(NameTypes.GenericName, NameTypes.DottedName, expressionValidator: nameTree =>
            {
                NodeValidators.DottedNameVerification(nameTree, "b", "b");
            });
        }
 
        [Fact]
        public void GenericToAlias()
        {
            MakeIncrementalNameChange(NameTypes.GenericName, NameTypes.AliasedName, expressionValidator: nameTree =>
            {
                NodeValidators.AliasedNameVerification(nameTree, "b", "d");
            });
        }
 
        [Fact]
        public void GenericToArray()
        {
            MakeIncrementalNameChange(NameTypes.GenericName, NameTypes.ArrayName, expressionValidator: nameTree =>
            {
                NodeValidators.ArrayNameVerification(nameTree, "b", 1);
            });
        }
 
        [Fact]
        public void GenericToPredefined()
        {
            MakeIncrementalNameChange(NameTypes.GenericName, NameTypes.PredefinedName, expressionValidator: nameTree =>
            {
                NodeValidators.PredefinedNameVerification(nameTree, "int");
            });
        }
 
        [Fact]
        public void GenericToPointer()
        {
            MakeIncrementalNameChange(NameTypes.GenericName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        [Fact]
        public void DottedToAlias()
        {
            MakeIncrementalNameChange(NameTypes.DottedName, NameTypes.AliasedName, expressionValidator: nameTree =>
            {
                NodeValidators.AliasedNameVerification(nameTree, "b", "d");
            });
        }
 
        [Fact]
        public void DottedToArray()
        {
            MakeIncrementalNameChange(NameTypes.DottedName, NameTypes.ArrayName, expressionValidator: nameTree =>
                {
                    NodeValidators.ArrayNameVerification(nameTree, "b", 1);
                });
        }
 
        [Fact]
        public void DottedToPredefined()
        {
            MakeIncrementalNameChange(NameTypes.DottedName, NameTypes.PredefinedName, expressionValidator: nameTree =>
            {
                NodeValidators.PredefinedNameVerification(nameTree, "int");
            });
        }
 
        [Fact]
        public void DottedToPointer()
        {
            MakeIncrementalNameChange(NameTypes.AliasedName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        [Fact]
        public void AliasToArray()
        {
            MakeIncrementalNameChange(NameTypes.AliasedName, NameTypes.ArrayName, expressionValidator: nameTree =>
            {
                NodeValidators.ArrayNameVerification(nameTree, "b", 1);
            });
        }
 
        [Fact]
        public void AliasToPredefined()
        {
            MakeIncrementalNameChange(NameTypes.AliasedName, NameTypes.PredefinedName, expressionValidator: nameTree =>
            {
                NodeValidators.PredefinedNameVerification(nameTree, "int");
            });
        }
 
        [Fact]
        public void AliasToPointer()
        {
            MakeIncrementalNameChange(NameTypes.AliasedName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        [Fact]
        public void ArrayToPredefined()
        {
            MakeIncrementalNameChange(NameTypes.ArrayName, NameTypes.PredefinedName, expressionValidator: nameTree =>
            {
                NodeValidators.PredefinedNameVerification(nameTree, "int");
            });
        }
 
        [Fact]
        public void ArrayToPointer()
        {
            MakeIncrementalNameChange(NameTypes.ArrayName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        [Fact]
        public void PredefinedToPointer()
        {
            MakeIncrementalNameChange(NameTypes.PredefinedName, NameTypes.PointerName, expressionValidator: nameTree =>
            {
                NodeValidators.PointerNameVerification(nameTree, "b");
            });
        }
 
        #region Specific helper functions
 
        private static string GetNameString(NameTypes newStyle)
        {
            switch (newStyle)
            {
                case NameTypes.SingleName: return "abc";
                case NameTypes.PredefinedName: return "int";
                case NameTypes.PointerName: return "b*";
                case NameTypes.GenericName: return "b<T>";
                case NameTypes.DottedName: return "b.b";
                case NameTypes.ArrayName: return "b[]";
                case NameTypes.AliasedName: return "b::d";
                default:
                    throw new Exception("Unexpected type here!!");
            }
        }
 
        private static void MakeIncrementalNameChange(NameTypes oldStyle, NameTypes newStyle, Action<ExpressionSyntax> expressionValidator)
        {
            MakeIncrementalNameChanges(oldStyle, newStyle, expressionValidator);
            MakeIncrementalNameChanges(oldStyle, newStyle, expressionValidator, options: TestOptions.Script);
            MakeIncrementalNameChanges(oldStyle, newStyle, expressionValidator, topLevel: true, options: TestOptions.Script);
        }
 
        private static void MakeIncrementalNameChanges(NameTypes oldStyle, NameTypes newStyle,
            Action<ExpressionSyntax> expressionValidator, bool topLevel = false, CSharpParseOptions options = null)
        {
            string oldName = GetNameString(oldStyle);
            string newName = GetNameString(newStyle);
 
            string code = oldName + @" m() {}";
            if (!topLevel)
            {
                code = @"class C { " + code + @"}";
            }
            else if (oldStyle == NameTypes.PointerName || newStyle == NameTypes.PointerName)
            {
                code = "unsafe " + code;
            }
 
            var oldTree = SyntaxFactory.ParseSyntaxTree(code, options: options);
 
            // Make the change to the node
            var newTree = oldTree.WithReplaceFirst(oldName, newName);
            var nameTree = topLevel ? GetGlobalMethodDeclarationSyntaxChange(newTree) : GetExpressionSyntaxChange(newTree);
            expressionValidator(nameTree);
        }
 
        private static ExpressionSyntax GetExpressionSyntaxChange(SyntaxTree newTree)
        {
            TypeDeclarationSyntax classType = newTree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            MethodDeclarationSyntax method = classType.Members[0] as MethodDeclarationSyntax;
            var nameTree = method.ReturnType;
            return nameTree;
        }
 
        private static ExpressionSyntax GetGlobalMethodDeclarationSyntaxChange(SyntaxTree newTree)
        {
            var method = newTree.GetCompilationUnitRoot().Members[0] as MethodDeclarationSyntax;
            return method.ReturnType;
        }
        #endregion
    }
}