| File: SyntaxNodeExtensionsTests.cs | Web Access |
| Project: src\test\Analyzers\Microsoft.Analyzers.Extra.Tests\Microsoft.Analyzers.Extra.Tests.csproj (Microsoft.Analyzers.Extra.Tests) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System; using System.Collections.Generic; using System.Linq; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Extensions.ExtraAnalyzers.Utilities; using Moq; using Xunit; namespace Microsoft.Extensions.ExtraAnalyzers.Test; public class SyntaxNodeExtensionsTests { [Fact] public void CheckFindNodeInTreeUpToSpecifiedParentByMethodNameReturnsNullWhenNodeIsNotfound() { var node = SyntaxFactory.VariableDeclarator("v"); var emptyList = new List<string>(); Assert.Null(node.FindNodeInTreeUpToSpecifiedParentByMethodName(new Mock<SemanticModel>().Object, emptyList, new List<Type>())); } [Fact] public void FindNodeInTreeUpToSpecifiedParentByMethodName_WhenNodeFounded() { string codeStr = @" public static class Extensions { public static string AddA(this string a) { return a + ""a""; } } public class MyClass { int Method1() { return 0; } void Method2() { string a = ""ab""; a.AddA(); } }"; SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(codeStr); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var model = compilation.GetSemanticModel(tree); var methodInvocSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().FirstOrDefault(); var parentToFind = "Extensions.AddA(string)"; Assert.Equal("a.AddA()", methodInvocSyntax?.FindNodeInTreeUpToSpecifiedParentByMethodName(model, new[] { parentToFind }, Array.Empty<Type>())?.ToString()); } [Fact] public void FindNodeInTreeUpToSpecifiedParentByMethodName_WhenStopped() { string codeStr = @" public static class Extensions { public static string AddA(this string a) { return a + ""a""; } } public class MyClass { int Method1() { return 0; } void Method2() { string a = ""ab""; a.AddA().AddA(); } }"; SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(codeStr); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var model = compilation.GetSemanticModel(tree); var methodInvocSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().FirstOrDefault(); var typesToStopTraversing = new HashSet<Type> { typeof(ExpressionStatementSyntax), }; Assert.Null(methodInvocSyntax?.FindNodeInTreeUpToSpecifiedParentByMethodName(model, Array.Empty<string>(), typesToStopTraversing)); } [Fact] public void CheckGetFirstAncestorOfSyntaxKindReturnsNullWhenNodeIsNotfound() { var node = SyntaxFactory.VariableDeclarator("v"); Assert.Null(node.GetFirstAncestorOfSyntaxKind(SyntaxKind.EqualsValueClause)); } [Fact] public void GetExpressionNameReturnsNullWhenExpressionIsNotMemberAccessOrMemeberBinding() { var node = SyntaxFactory.InvocationExpression(SyntaxFactory.IdentifierName("CheckGetFirstAncestorOfSyntaxKindReturnsNullWhenNodeIsNotfound")); Assert.Null(node.GetExpressionName()); } [Theory] [InlineData("expectedName", true)] [InlineData("anotherNameExpected", false)] public void IdentifierNameEqualsReturnsResultWhenNodeTypeIsIdentifierNameSyntax(string expectedName, bool result) { var node = SyntaxFactory.IdentifierName("expectedName"); Assert.Equal(result, node.IdentifierNameEquals(expectedName)); } [Fact] public void IdentifierNameEqualsReturnsFalseWhenNodeTypeIsNotIdentifierNameSyntax() { Assert.False(((LiteralExpressionSyntax)null!).IdentifierNameEquals("a")); } [Fact] public void NodeHasSpecifiedMethodReturnsFalseWhenMethodSymbolIsNull() { string codeStr = @" using System; public class MyClassClass { virtual public void MyMehtod() { Console.WriteLine(""Hello from MyClass""); } } "; SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(codeStr); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var model = compilation.GetSemanticModel(tree); var methodInvocSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().FirstOrDefault(); Assert.False(methodInvocSyntax!.NodeHasSpecifiedMethod(model, new HashSet<string>())); } [Fact] public void NodeHasSpecifiedMethodContainsReducedForm() { string codeStr = @" public static class Extensions { public static string AddA(this string a) { return a + ""a""; } } public class MyClass { int Method1() { return 0; } void Method2() { string a = ""ab""; a.AddA(); } }"; SyntaxTree tree = SyntaxFactory.ParseSyntaxTree(codeStr); var compilation = CSharpCompilation.Create( "MyCompilation", syntaxTrees: new[] { tree }, references: new[] { MetadataReference.CreateFromFile(typeof(object).Assembly.Location) }); var model = compilation.GetSemanticModel(tree); var methodInvocSyntax = tree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>().FirstOrDefault(); Assert.True(methodInvocSyntax!.NodeHasSpecifiedMethod(model, new HashSet<string> { "Extensions.AddA(string)" })); } [Fact] public void GetExpressionName_WithMemberAccessExpression() { var console = SyntaxFactory.IdentifierName("Console"); var writeline = SyntaxFactory.IdentifierName("WriteLine"); var memberaccess = SyntaxFactory.MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, console, writeline); var expression = SyntaxFactory.InvocationExpression(memberaccess, SyntaxFactory.ArgumentList()); Assert.Equal(writeline.ToString(), expression.GetExpressionName()?.ToString()); } [Fact] public void GetExpressionName_WithMemberBindingExpression() { var b = SyntaxFactory.IdentifierName("b"); var memberbind = SyntaxFactory.MemberBindingExpression(SyntaxFactory.ParseToken("."), b); var expression = SyntaxFactory.InvocationExpression(memberbind); Assert.Equal(b.ToString(), expression.GetExpressionName()?.ToString()); } }