From aa810ccbb68699cff27effcfccb8e3217392b8bb Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Mon, 6 May 2024 16:27:37 -0300 Subject: [PATCH] fix analyzer exception 'Syntax node is not within syntax tree' (#307) During orchestration method analysis, since the syntax tree of the callee method might be different from the caller method, we need to get the correct semantic model when they differ. --- .../Orchestration/OrchestrationAnalyzer.cs | 7 ++++- .../DateTimeOrchestrationAnalyzerTests.cs | 26 +++++++++++++++++++ .../CSharpAnalyzerVerifier.Durable.cs | 7 +++++ 3 files changed, 39 insertions(+), 1 deletion(-) diff --git a/src/Analyzers/Orchestration/OrchestrationAnalyzer.cs b/src/Analyzers/Orchestration/OrchestrationAnalyzer.cs index ca36af86..a299d577 100644 --- a/src/Analyzers/Orchestration/OrchestrationAnalyzer.cs +++ b/src/Analyzers/Orchestration/OrchestrationAnalyzer.cs @@ -316,7 +316,12 @@ void FindInvokedMethods( IEnumerable calleeSyntaxes = calleeMethodSymbol.GetSyntaxNodes(); foreach (MethodDeclarationSyntax calleeSyntax in calleeSyntaxes) { - this.FindInvokedMethods(semanticModel, calleeSyntax, calleeMethodSymbol, rootOrchestration, reportDiagnostic); + // Since the syntax tree of the callee method might be different from the caller method, we need to get the correct semantic model, + // avoiding the exception 'Syntax node is not within syntax tree'. + SemanticModel sm = semanticModel.SyntaxTree == calleeSyntax.SyntaxTree ? + semanticModel : semanticModel.Compilation.GetSemanticModel(calleeSyntax.SyntaxTree); + + this.FindInvokedMethods(sm, calleeSyntax, calleeMethodSymbol, rootOrchestration, reportDiagnostic); } } } diff --git a/test/Analyzers.Tests/Orchestration/DateTimeOrchestrationAnalyzerTests.cs b/test/Analyzers.Tests/Orchestration/DateTimeOrchestrationAnalyzerTests.cs index 77bfc515..18a90349 100644 --- a/test/Analyzers.Tests/Orchestration/DateTimeOrchestrationAnalyzerTests.cs +++ b/test/Analyzers.Tests/Orchestration/DateTimeOrchestrationAnalyzerTests.cs @@ -222,6 +222,32 @@ public class MyOrchestrator : ITaskOrchestrator await VerifyCS.VerifyDurableTaskAnalyzerAsync(code, expected); } + [Fact] + public async Task TaskOrchestratorUsingDifferentSyntaxTreesHasDiag() + { + string mainCode = Wrapper.WrapTaskOrchestrator(@" +public class MyOrchestrator : TaskOrchestrator +{ + public override Task RunAsync(TaskOrchestrationContext context, string input) + { + var dependency = new Dependency(); + return Task.FromResult(dependency.Method()); + } +} +"); + string codeInAnotherSyntaxTree = Wrapper.WrapTaskOrchestrator(@" +public class Dependency{ + public DateTime Method() => {|#0:DateTime.Now|}; +} +"); + + void configureTest(VerifyCS.Test test) => test.TestState.Sources.Add(codeInAnotherSyntaxTree); + + DiagnosticResult expected = BuildDiagnostic().WithLocation(0).WithArguments("Method", "System.DateTime.Now", "MyOrchestrator"); + + await VerifyCS.VerifyDurableTaskAnalyzerAsync(mainCode, configureTest, expected); + } + [Fact] public async Task FuncOrchestratorWithLambdaHasDiag() diff --git a/test/Analyzers.Tests/Verifiers/CSharpAnalyzerVerifier.Durable.cs b/test/Analyzers.Tests/Verifiers/CSharpAnalyzerVerifier.Durable.cs index 89a1178a..6d035e77 100644 --- a/test/Analyzers.Tests/Verifiers/CSharpAnalyzerVerifier.Durable.cs +++ b/test/Analyzers.Tests/Verifiers/CSharpAnalyzerVerifier.Durable.cs @@ -12,6 +12,11 @@ public static partial class CSharpAnalyzerVerifier { /// public static async Task VerifyDurableTaskAnalyzerAsync(string source, params DiagnosticResult[] expected) + { + await VerifyDurableTaskAnalyzerAsync(source, null, expected); + } + + public static async Task VerifyDurableTaskAnalyzerAsync(string source, Action? configureTest = null, params DiagnosticResult[] expected) { Test test = new() { @@ -24,6 +29,8 @@ public static async Task VerifyDurableTaskAnalyzerAsync(string source, params Di test.ExpectedDiagnostics.AddRange(expected); + configureTest?.Invoke(test); + await test.RunAsync(CancellationToken.None); } }