File: IncrementalParsing\CompoundAssignment.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 changes between different compound assignment expressions
    public class CompoundAssignment
    {
        [Fact]
        public void AssignToPlus()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression);
        }
 
        [Fact]
        public void AssignToSubtract()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.SubtractAssignmentExpression);
        }
 
        [Fact]
        public void AssignToMultiply()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.MultiplyAssignmentExpression);
        }
 
        [Fact]
        public void AssignToDivide()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.DivideAssignmentExpression);
        }
 
        [Fact]
        public void AssignToModule()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.ModuloAssignmentExpression);
        }
 
        [Fact]
        public void AssignToExclusiveOr()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.ExclusiveOrAssignmentExpression);
        }
 
        [Fact]
        public void AssignToLeftShift()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression);
        }
 
        [Fact]
        public void AssignToRightShift()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.RightShiftAssignmentExpression);
        }
 
        [Fact]
        public void AssignToUnsignedRightShift()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.UnsignedRightShiftAssignmentExpression);
        }
 
        [Fact]
        public void AssignToAnd()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AndAssignmentExpression);
        }
 
        [Fact]
        public void AssignToOr()
        {
            MakeAssignmentChange(SyntaxKind.SimpleAssignmentExpression, SyntaxKind.OrAssignmentExpression);
        }
 
        #region Helper Methods
        private static void MakeAssignmentChange(SyntaxKind oldStyle, SyntaxKind newStyle)
        {
            MakeAssignmentChanges(oldStyle, newStyle);
            MakeAssignmentChanges(oldStyle, newStyle, options: TestOptions.Script);
            MakeAssignmentChanges(oldStyle, newStyle, topLevel: true, options: TestOptions.Script);
        }
 
        private static void MakeAssignmentChanges(SyntaxKind oldSyntaxKind, SyntaxKind newSyntaxKind, bool topLevel = false, CSharpParseOptions options = null)
        {
            string oldName = GetExpressionString(oldSyntaxKind);
            string newName = GetExpressionString(newSyntaxKind);
 
            string topLevelStatement = "x " + oldName + " y";
            var code = @"class C { void m() {
                 " + topLevelStatement + @";
                }}";
 
            var oldTree = SyntaxFactory.ParseSyntaxTree(topLevel ? topLevelStatement : code, options: options);
 
            // Make the change to the node
            var newTree = oldTree.WithReplaceFirst(oldName, newName);
            var binNode = topLevel ? GetGlobalStatementSyntaxChange(newTree) : GetExpressionSyntaxChange(newTree);
            Assert.Equal(binNode.Kind(), newSyntaxKind);
        }
 
        private static string GetExpressionString(SyntaxKind oldStyle)
        {
            switch (oldStyle)
            {
                case SyntaxKind.SimpleAssignmentExpression:
                    return "=";
                case SyntaxKind.AddAssignmentExpression:
                    return "+=";
                case SyntaxKind.SubtractAssignmentExpression:
                    return "-=";
                case SyntaxKind.MultiplyAssignmentExpression:
                    return "*=";
                case SyntaxKind.DivideAssignmentExpression:
                    return "/=";
                case SyntaxKind.ModuloAssignmentExpression:
                    return "%=";
                case SyntaxKind.AndAssignmentExpression:
                    return "&=";
                case SyntaxKind.ExclusiveOrAssignmentExpression:
                    return "^=";
                case SyntaxKind.OrAssignmentExpression:
                    return "|=";
                case SyntaxKind.LeftShiftAssignmentExpression:
                    return "<<=";
                case SyntaxKind.RightShiftAssignmentExpression:
                    return ">>=";
                case SyntaxKind.UnsignedRightShiftAssignmentExpression:
                    return ">>>=";
                default:
                    throw new Exception("No operator found");
            }
        }
 
        private static AssignmentExpressionSyntax GetExpressionSyntaxChange(SyntaxTree newTree)
        {
            var classType = newTree.GetCompilationUnitRoot().Members[0] as TypeDeclarationSyntax;
            var method = classType.Members[0] as MethodDeclarationSyntax;
            var block = method.Body;
            var statement = block.Statements[0] as ExpressionStatementSyntax;
            var expression = statement.Expression as AssignmentExpressionSyntax;
            return expression;
        }
 
        private static AssignmentExpressionSyntax GetGlobalStatementSyntaxChange(SyntaxTree newTree)
        {
            var statementType = newTree.GetCompilationUnitRoot().Members[0] as GlobalStatementSyntax;
            Assert.True(statementType.AttributeLists.Count == 0);
            Assert.True(statementType.Modifiers.Count == 0);
            var statement = statementType.Statement as ExpressionStatementSyntax;
            var expression = statement.Expression as AssignmentExpressionSyntax;
            return expression;
        }
        #endregion
    }
}