From 92f21e5c3d9a0a6d4eea74d666e57fa89b89f1b6 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Thu, 2 May 2024 16:07:51 -0300 Subject: [PATCH 1/5] attribute binding analyzers --- src/Analyzers/AnalyzerReleases.Unshipped.md | 5 +- src/Analyzers/AnalyzersCategories.cs | 5 ++ .../DurableClientBindingAnalyzer.cs | 51 ++++++++++++ .../EntityTriggerBindingAnalyzer.cs | 51 ++++++++++++ .../MatchingAttributeBindingAnalyzer.cs | 79 +++++++++++++++++++ .../OrchestrationTriggerBindingAnalyzer.cs | 51 ++++++++++++ src/Analyzers/KnownTypeSymbols.cs | 30 +++++++ src/Analyzers/Resources.resx | 18 +++++ .../DurableClientBindingAnalyzerTests.cs | 15 ++++ .../EntityTriggerBindingAnalyzerTests.cs | 15 ++++ ...chingAttributeBindingSpecificationTests.cs | 72 +++++++++++++++++ ...rchestrationTriggerBindingAnalyzerTests.cs | 15 ++++ 12 files changed, 406 insertions(+), 1 deletion(-) create mode 100644 src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs create mode 100644 src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs create mode 100644 src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs create mode 100644 src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs create mode 100644 test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs create mode 100644 test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs create mode 100644 test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs create mode 100644 test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs diff --git a/src/Analyzers/AnalyzerReleases.Unshipped.md b/src/Analyzers/AnalyzerReleases.Unshipped.md index cac23ffb..a0f1d8c6 100644 --- a/src/Analyzers/AnalyzerReleases.Unshipped.md +++ b/src/Analyzers/AnalyzerReleases.Unshipped.md @@ -1,4 +1,4 @@ -; Unshipped analyzer release +; Unshipped analyzer release ; https://github.com/dotnet/roslyn-analyzers/blob/main/src/Microsoft.CodeAnalysis.Analyzers/ReleaseTrackingAnalyzers.Help.md ### New Rules @@ -8,3 +8,6 @@ Rule ID | Category | Severity | Notes DURABLE0001 | Orchestration | Warning | DateTimeOrchestrationAnalyzer DURABLE0002 | Orchestration | Warning | GuidOrchestrationAnalyzer DURABLE0003 | Orchestration | Warning | DelayOrchestrationAnalyzer +DURABLE1001 | Attribute Binding | Error | OrchestrationTriggerBindingAnalyzer +DURABLE1002 | Attribute Binding | Error | DurableClientBindingAnalyzer +DURABLE1003 | Attribute Binding | Error | EntityTriggerBindingAnalyzer \ No newline at end of file diff --git a/src/Analyzers/AnalyzersCategories.cs b/src/Analyzers/AnalyzersCategories.cs index 2f2b1a6b..8bdae885 100644 --- a/src/Analyzers/AnalyzersCategories.cs +++ b/src/Analyzers/AnalyzersCategories.cs @@ -12,4 +12,9 @@ static class AnalyzersCategories /// The category for the orchestration related analyzers. /// public const string Orchestration = "Orchestration"; + + /// + /// The category for the attribute binding related analyzers. + /// + public const string AttributeBinding = "Attribute Binding"; } diff --git a/src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs b/src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs new file mode 100644 index 00000000..3fb7c666 --- /dev/null +++ b/src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.DurableTask.Analyzers.AttributeBinding; + +/// +/// Analyzer that matches 'DurableClientAttribute' with 'DurableTaskClient' parameters. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class DurableClientBindingAnalyzer : MatchingAttributeBindingAnalyzer +{ + /// + /// Diagnostic ID supported for the analyzer. + /// + public const string DiagnosticId = "DURABLE1002"; + + static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.DurableClientBindingAnalyzerTitle), Resources.ResourceManager, typeof(Resources)); + static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.DurableClientBindingAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); + + static readonly DiagnosticDescriptor Rule = new( + DiagnosticId, + Title, + MessageFormat, + AnalyzersCategories.AttributeBinding, + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + /// + public override ImmutableArray SupportedDiagnostics => [Rule]; + + /// + protected override ExpectedBinding GetExpectedBinding(KnownTypeSymbols knownTypeSymbols) + { + return new ExpectedBinding() + { + Attribute = knownTypeSymbols.DurableClientAttribute, + Type = knownTypeSymbols.DurableTaskClient, + }; + } + + /// + protected override void ReportDiagnostic(SymbolAnalysisContext ctx, ExpectedBinding expected, IParameterSymbol parameter) + { + string wrongType = parameter.Type.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat); + ctx.ReportDiagnostic(RoslynExtensions.BuildDiagnostic(Rule, parameter, wrongType)); + } +} diff --git a/src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs b/src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs new file mode 100644 index 00000000..6745be34 --- /dev/null +++ b/src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.DurableTask.Analyzers.AttributeBinding; + +/// +/// Analyzer that matches 'EntityTriggerAttribute' with 'TaskEntityDispatcher' parameters. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class EntityTriggerBindingAnalyzer : MatchingAttributeBindingAnalyzer +{ + /// + /// Diagnostic ID supported for the analyzer. + /// + public const string DiagnosticId = "DURABLE1003"; + + static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.EntityTriggerBindingAnalyzerTitle), Resources.ResourceManager, typeof(Resources)); + static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.EntityTriggerBindingAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); + + static readonly DiagnosticDescriptor Rule = new( + DiagnosticId, + Title, + MessageFormat, + AnalyzersCategories.AttributeBinding, + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + /// + public override ImmutableArray SupportedDiagnostics => [Rule]; + + /// + protected override ExpectedBinding GetExpectedBinding(KnownTypeSymbols knownTypeSymbols) + { + return new ExpectedBinding() + { + Attribute = knownTypeSymbols.EntityTriggerAttribute, + Type = knownTypeSymbols.TaskEntityDispatcher, + }; + } + + /// + protected override void ReportDiagnostic(SymbolAnalysisContext ctx, ExpectedBinding expected, IParameterSymbol parameter) + { + string wrongType = parameter.Type.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat); + ctx.ReportDiagnostic(RoslynExtensions.BuildDiagnostic(Rule, parameter, wrongType)); + } +} diff --git a/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs b/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs new file mode 100644 index 00000000..5ed02e94 --- /dev/null +++ b/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs @@ -0,0 +1,79 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.DurableTask.Analyzers.AttributeBinding; + +/// +/// Expected attribute binding for a given parameter type. +/// +public struct ExpectedBinding +{ + /// + /// Gets or sets the expected attribute. + /// + public INamedTypeSymbol? Attribute { get; set; } + + /// + /// Gets or sets the expected type. + /// + public INamedTypeSymbol? Type { get; set; } +} + +/// +/// Analyzer that inspects the parameter type of a method to ensure it matches the expected attribute binding. +/// It expects one parameter in the DiagnosticRule message template, so the analyzer can report the wrong type. +/// +public abstract class MatchingAttributeBindingAnalyzer : DiagnosticAnalyzer +{ + /// + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None); + + context.RegisterCompilationStartAction( + ctx => + { + KnownTypeSymbols knownTypeSymbols = new(ctx.Compilation); + + ExpectedBinding expectedBinding = this.GetExpectedBinding(knownTypeSymbols); + if (expectedBinding.Attribute is null || expectedBinding.Type is null) + { + return; + } + + ctx.RegisterSymbolAction(c => this.Analyze(c, expectedBinding), SymbolKind.Parameter); + }); + } + + /// + /// Gets the expected attribute binding and the related type to be used during parameters analysis. + /// + /// The set of well-known types. + /// The expected binding for this analyzer. + protected abstract ExpectedBinding GetExpectedBinding(KnownTypeSymbols knownTypeSymbols); + + /// + /// After an incorrect attribute/type matching is found, this method is called so the concrete implementation can report a diagnostic. + /// + /// Context for a symbol action. Allows reporting a diagnostic. + /// Expected binding for a attribute/type. + /// Analyzed parameter symbol. + protected abstract void ReportDiagnostic(SymbolAnalysisContext ctx, ExpectedBinding expected, IParameterSymbol parameter); + + void Analyze(SymbolAnalysisContext ctx, ExpectedBinding expected) + { + IParameterSymbol parameter = (IParameterSymbol)ctx.Symbol; + + if (parameter.GetAttributes().Any(a => expected.Attribute!.Equals(a.AttributeClass, SymbolEqualityComparer.Default))) + { + if (!parameter.Type.Equals(expected.Type, SymbolEqualityComparer.Default)) + { + this.ReportDiagnostic(ctx, expected, parameter); + } + } + } +} diff --git a/src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs b/src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs new file mode 100644 index 00000000..5eaecccc --- /dev/null +++ b/src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.DurableTask.Analyzers.AttributeBinding; + +/// +/// Analyzer that matches 'OrchestrationTriggerAttribute' with 'TaskOrchestrationContext' parameters. +/// +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class OrchestrationTriggerBindingAnalyzer : MatchingAttributeBindingAnalyzer +{ + /// + /// Diagnostic ID supported for the analyzer. + /// + public const string DiagnosticId = "DURABLE1001"; + + static readonly LocalizableString Title = new LocalizableResourceString(nameof(Resources.OrchestrationTriggerBindingAnalyzerTitle), Resources.ResourceManager, typeof(Resources)); + static readonly LocalizableString MessageFormat = new LocalizableResourceString(nameof(Resources.OrchestrationTriggerBindingAnalyzerMessageFormat), Resources.ResourceManager, typeof(Resources)); + + static readonly DiagnosticDescriptor Rule = new( + DiagnosticId, + Title, + MessageFormat, + AnalyzersCategories.AttributeBinding, + DiagnosticSeverity.Error, + isEnabledByDefault: true); + + /// + public override ImmutableArray SupportedDiagnostics => [Rule]; + + /// + protected override ExpectedBinding GetExpectedBinding(KnownTypeSymbols knownTypeSymbols) + { + return new ExpectedBinding() + { + Attribute = knownTypeSymbols.FunctionOrchestrationAttribute, + Type = knownTypeSymbols.TaskOrchestrationContext, + }; + } + + /// + protected override void ReportDiagnostic(SymbolAnalysisContext ctx, ExpectedBinding expected, IParameterSymbol parameter) + { + string wrongType = parameter.Type.ToDisplayString(SymbolDisplayFormat.CSharpShortErrorMessageFormat); + ctx.ReportDiagnostic(RoslynExtensions.BuildDiagnostic(Rule, parameter, wrongType)); + } +} diff --git a/src/Analyzers/KnownTypeSymbols.cs b/src/Analyzers/KnownTypeSymbols.cs index 109bd440..84debe2e 100644 --- a/src/Analyzers/KnownTypeSymbols.cs +++ b/src/Analyzers/KnownTypeSymbols.cs @@ -20,6 +20,11 @@ public sealed class KnownTypeSymbols(Compilation compilation) INamedTypeSymbol? taskOrchestratorInterface; INamedTypeSymbol? taskOrchestratorBaseClass; INamedTypeSymbol? durableTaskRegistry; + INamedTypeSymbol? taskOrchestrationContext; + INamedTypeSymbol? durableClientAttribute; + INamedTypeSymbol? durableTaskClient; + INamedTypeSymbol? entityTriggerAttribute; + INamedTypeSymbol? taskEntityDispatcher; INamedTypeSymbol? guid; INamedTypeSymbol? thread; INamedTypeSymbol? task; @@ -50,6 +55,31 @@ public sealed class KnownTypeSymbols(Compilation compilation) /// public INamedTypeSymbol? DurableTaskRegistry => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.DurableTaskRegistry", ref this.durableTaskRegistry); + /// + /// Gets a TaskOrchestrationContext type symbol. + /// + public INamedTypeSymbol? TaskOrchestrationContext => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.TaskOrchestrationContext", ref this.taskOrchestrationContext); + + /// + /// Gets a DurableClientAttribute type symbol. + /// + public INamedTypeSymbol? DurableClientAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.DurableClientAttribute", ref this.durableClientAttribute); + + /// + /// Gets a DurableTaskClient type symbol. + /// + public INamedTypeSymbol? DurableTaskClient => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.Client.DurableTaskClient", ref this.durableTaskClient); + + /// + /// Gets an EntityTriggerAttribute type symbol. + /// + public INamedTypeSymbol? EntityTriggerAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.EntityTriggerAttribute", ref this.entityTriggerAttribute); + + /// + /// Gets a TaskEntityDispatcher type symbol. + /// + public INamedTypeSymbol? TaskEntityDispatcher => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.TaskEntityDispatcher", ref this.taskEntityDispatcher); + /// /// Gets a Guid type symbol. /// diff --git a/src/Analyzers/Resources.resx b/src/Analyzers/Resources.resx index 96e7ca8b..d15e4b9b 100644 --- a/src/Analyzers/Resources.resx +++ b/src/Analyzers/Resources.resx @@ -135,4 +135,22 @@ Thread.Sleep and Task.Delay calls are not allowed inside an orchestrator + + [OrchestrationTrigger] is associated with the wrong type '{0}', it must be used with TaskOrchestrationContext + + + [OrchestrationTrigger] must be used with TaskOrchestrationContext + + + [EntityTrigger] is associated with the wrong type '{0}', it must be used with TaskEntityDispatcher + + + [EntityTrigger] must be used with TaskOrchestrationContext + + + [DurableClient] is associated with the wrong type '{0}', it must be used with DurableTaskClient + + + [DurableClient] must be used with DurableTaskClient + \ No newline at end of file diff --git a/test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs b/test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs new file mode 100644 index 00000000..a7e13152 --- /dev/null +++ b/test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.DurableTask.Analyzers.AttributeBinding; + +namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; + +public class DurableClientBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests +{ + protected override string ExpectedDiagnosticId => DurableClientBindingAnalyzer.DiagnosticId; + + protected override string ExpectedAttribute => "[DurableClient]"; + + protected override string ExpectedType => "DurableTaskClient"; +} diff --git a/test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs b/test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs new file mode 100644 index 00000000..dc2243dd --- /dev/null +++ b/test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.DurableTask.Analyzers.AttributeBinding; + +namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; + +public class EntityTriggerBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests +{ + protected override string ExpectedDiagnosticId => EntityTriggerBindingAnalyzer.DiagnosticId; + + protected override string ExpectedAttribute => "[EntityTrigger]"; + + protected override string ExpectedType => "TaskEntityDispatcher"; +} diff --git a/test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs b/test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs new file mode 100644 index 00000000..c41fe24a --- /dev/null +++ b/test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs @@ -0,0 +1,72 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.CodeAnalysis.Testing; +using Microsoft.DurableTask.Analyzers.AttributeBinding; +using Microsoft.DurableTask.Analyzers.Tests.Verifiers; + +namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; + +public abstract class MatchingAttributeBindingSpecificationTests where TAnalyzer : MatchingAttributeBindingAnalyzer, new() +{ + protected abstract string ExpectedDiagnosticId { get; } + protected abstract string ExpectedAttribute { get; } + protected abstract string ExpectedType { get; } + protected virtual string WrongType { get; } = "int"; + + [Fact] + public async Task EmptyCodeHasNoDiag() + { + string code = @""; + + await VerifyAsync(code); + } + + [Fact] + public async Task TypeWithoutExpectedAttributeHasNoDiag() + { + string code = Wrapper.WrapDurableFunctionOrchestration($@" +void Method({this.ExpectedType} paramName) +{{ +}} +"); + + await VerifyAsync(code); + } + + [Fact] + public async Task ExpectedAttributeWithExpectedTypeHasNoDiag() + { + string code = Wrapper.WrapDurableFunctionOrchestration($@" +void Method({this.ExpectedAttribute} {this.ExpectedType} paramName) +{{ +}} +"); + + await VerifyAsync(code); + } + + [Fact] + public async Task ExpectedAttributeWithWrongTypeHasDiag() + { + string code = Wrapper.WrapDurableFunctionOrchestration($@" +void Method({{|#0:{this.ExpectedAttribute} {this.WrongType} paramName|}}) +{{ +}} +"); + + DiagnosticResult expected = this.BuildDiagnostic().WithLocation(0).WithArguments(this.WrongType); + + await VerifyAsync(code, expected); + } + + static async Task VerifyAsync(string source, params DiagnosticResult[] expected) + { + await CSharpAnalyzerVerifier.VerifyDurableTaskAnalyzerAsync(source, expected); + } + + DiagnosticResult BuildDiagnostic() + { + return CSharpAnalyzerVerifier.Diagnostic(this.ExpectedDiagnosticId); + } +} diff --git a/test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs b/test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs new file mode 100644 index 00000000..bff0125b --- /dev/null +++ b/test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs @@ -0,0 +1,15 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.DurableTask.Analyzers.AttributeBinding; + +namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; + +public class OrchestrationTriggerBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests +{ + protected override string ExpectedDiagnosticId => OrchestrationTriggerBindingAnalyzer.DiagnosticId; + + protected override string ExpectedAttribute => "[OrchestrationTrigger]"; + + protected override string ExpectedType => "TaskOrchestrationContext"; +} From 9e38b740bdcb36fa636baa3c21165c7a156ef7ab Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Fri, 3 May 2024 09:59:21 -0300 Subject: [PATCH 2/5] moving attribute binding analyzers to Functions namespace --- .../AttributeBinding/DurableClientBindingAnalyzer.cs | 2 +- .../AttributeBinding/EntityTriggerBindingAnalyzer.cs | 2 +- .../AttributeBinding/MatchingAttributeBindingAnalyzer.cs | 2 +- .../OrchestrationTriggerBindingAnalyzer.cs | 2 +- .../AttributeBinding/DurableClientBindingAnalyzerTests.cs | 8 ++++++-- .../AttributeBinding/EntityTriggerBindingAnalyzerTests.cs | 8 ++++++-- .../MatchingAttributeBindingSpecificationTests.cs | 4 ++-- .../OrchestrationTriggerBindingAnalyzerTests.cs | 4 ++-- 8 files changed, 20 insertions(+), 12 deletions(-) rename src/Analyzers/{ => Functions}/AttributeBinding/DurableClientBindingAnalyzer.cs (96%) rename src/Analyzers/{ => Functions}/AttributeBinding/EntityTriggerBindingAnalyzer.cs (96%) rename src/Analyzers/{ => Functions}/AttributeBinding/MatchingAttributeBindingAnalyzer.cs (97%) rename src/Analyzers/{ => Functions}/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs (96%) rename test/Analyzers.Tests/{ => Functions}/AttributeBinding/DurableClientBindingAnalyzerTests.cs (67%) rename test/Analyzers.Tests/{ => Functions}/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs (67%) rename test/Analyzers.Tests/{ => Functions}/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs (93%) rename test/Analyzers.Tests/{ => Functions}/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs (77%) diff --git a/src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs b/src/Analyzers/Functions/AttributeBinding/DurableClientBindingAnalyzer.cs similarity index 96% rename from src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs rename to src/Analyzers/Functions/AttributeBinding/DurableClientBindingAnalyzer.cs index 3fb7c666..8089043e 100644 --- a/src/Analyzers/AttributeBinding/DurableClientBindingAnalyzer.cs +++ b/src/Analyzers/Functions/AttributeBinding/DurableClientBindingAnalyzer.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.DurableTask.Analyzers.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; /// /// Analyzer that matches 'DurableClientAttribute' with 'DurableTaskClient' parameters. diff --git a/src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs b/src/Analyzers/Functions/AttributeBinding/EntityTriggerBindingAnalyzer.cs similarity index 96% rename from src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs rename to src/Analyzers/Functions/AttributeBinding/EntityTriggerBindingAnalyzer.cs index 6745be34..8667cb32 100644 --- a/src/Analyzers/AttributeBinding/EntityTriggerBindingAnalyzer.cs +++ b/src/Analyzers/Functions/AttributeBinding/EntityTriggerBindingAnalyzer.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.DurableTask.Analyzers.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; /// /// Analyzer that matches 'EntityTriggerAttribute' with 'TaskEntityDispatcher' parameters. diff --git a/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs b/src/Analyzers/Functions/AttributeBinding/MatchingAttributeBindingAnalyzer.cs similarity index 97% rename from src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs rename to src/Analyzers/Functions/AttributeBinding/MatchingAttributeBindingAnalyzer.cs index 5ed02e94..de86b85d 100644 --- a/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs +++ b/src/Analyzers/Functions/AttributeBinding/MatchingAttributeBindingAnalyzer.cs @@ -4,7 +4,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.DurableTask.Analyzers.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; /// /// Expected attribute binding for a given parameter type. diff --git a/src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs b/src/Analyzers/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs similarity index 96% rename from src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs rename to src/Analyzers/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs index 5eaecccc..d6642043 100644 --- a/src/Analyzers/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs +++ b/src/Analyzers/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzer.cs @@ -5,7 +5,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -namespace Microsoft.DurableTask.Analyzers.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; /// /// Analyzer that matches 'OrchestrationTriggerAttribute' with 'TaskOrchestrationContext' parameters. diff --git a/test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs similarity index 67% rename from test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs rename to test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs index a7e13152..f609cb68 100644 --- a/test/Analyzers.Tests/AttributeBinding/DurableClientBindingAnalyzerTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs @@ -1,9 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.DurableTask.Analyzers.AttributeBinding; -namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; + +namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding; public class DurableClientBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests { diff --git a/test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs similarity index 67% rename from test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs rename to test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs index dc2243dd..2854f87c 100644 --- a/test/Analyzers.Tests/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs @@ -1,9 +1,13 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.DurableTask.Analyzers.AttributeBinding; -namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; + +namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding; public class EntityTriggerBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests { diff --git a/test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs similarity index 93% rename from test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs rename to test/Analyzers.Tests/Functions/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs index c41fe24a..35018340 100644 --- a/test/Analyzers.Tests/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/MatchingAttributeBindingSpecificationTests.cs @@ -2,10 +2,10 @@ // Licensed under the MIT License. using Microsoft.CodeAnalysis.Testing; -using Microsoft.DurableTask.Analyzers.AttributeBinding; +using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; using Microsoft.DurableTask.Analyzers.Tests.Verifiers; -namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding; public abstract class MatchingAttributeBindingSpecificationTests where TAnalyzer : MatchingAttributeBindingAnalyzer, new() { diff --git a/test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs similarity index 77% rename from test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs rename to test/Analyzers.Tests/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs index bff0125b..f1d020f9 100644 --- a/test/Analyzers.Tests/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/OrchestrationTriggerBindingAnalyzerTests.cs @@ -1,9 +1,9 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. -using Microsoft.DurableTask.Analyzers.AttributeBinding; +using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; -namespace Microsoft.DurableTask.Analyzers.Tests.AttributeBinding; +namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding; public class OrchestrationTriggerBindingAnalyzerTests : MatchingAttributeBindingSpecificationTests { From 8e871fb57e2faae2605ca52a8802b23f634a6074 Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Fri, 3 May 2024 15:04:59 -0300 Subject: [PATCH 3/5] splitting known type symbols into partial classes --- src/Analyzers/KnownTypeSymbols.Durable.cs | 47 +++++++++++ src/Analyzers/KnownTypeSymbols.Functions.cs | 46 +++++++++++ src/Analyzers/KnownTypeSymbols.Net.cs | 40 ++++++++++ src/Analyzers/KnownTypeSymbols.cs | 87 +-------------------- 4 files changed, 134 insertions(+), 86 deletions(-) create mode 100644 src/Analyzers/KnownTypeSymbols.Durable.cs create mode 100644 src/Analyzers/KnownTypeSymbols.Functions.cs create mode 100644 src/Analyzers/KnownTypeSymbols.Net.cs diff --git a/src/Analyzers/KnownTypeSymbols.Durable.cs b/src/Analyzers/KnownTypeSymbols.Durable.cs new file mode 100644 index 00000000..d314f564 --- /dev/null +++ b/src/Analyzers/KnownTypeSymbols.Durable.cs @@ -0,0 +1,47 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.DurableTask.Analyzers; + +/// +/// Provides a set of well-known types that are used by the analyzers. +/// Inspired by KnownTypeSymbols class in +/// System.Text.Json.SourceGeneration source code. +/// Lazy initialization is used to avoid the the initialization of all types during class construction, since not all symbols are used by all analyzers. +/// +public sealed partial class KnownTypeSymbols +{ + INamedTypeSymbol? taskOrchestratorInterface; + INamedTypeSymbol? taskOrchestratorBaseClass; + INamedTypeSymbol? durableTaskRegistry; + INamedTypeSymbol? taskOrchestrationContext; + INamedTypeSymbol? durableTaskClient; + + /// + /// Gets an ITaskOrchestrator type symbol. + /// + public INamedTypeSymbol? TaskOrchestratorInterface => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.ITaskOrchestrator", ref this.taskOrchestratorInterface); + + /// + /// Gets a TaskOrchestrator type symbol. + /// + public INamedTypeSymbol? TaskOrchestratorBaseClass => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.TaskOrchestrator`2", ref this.taskOrchestratorBaseClass); + + /// + /// Gets a DurableTaskRegistry type symbol. + /// + public INamedTypeSymbol? DurableTaskRegistry => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.DurableTaskRegistry", ref this.durableTaskRegistry); + + /// + /// Gets a TaskOrchestrationContext type symbol. + /// + public INamedTypeSymbol? TaskOrchestrationContext => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.TaskOrchestrationContext", ref this.taskOrchestrationContext); + + + /// + /// Gets a DurableTaskClient type symbol. + /// + public INamedTypeSymbol? DurableTaskClient => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.Client.DurableTaskClient", ref this.durableTaskClient); +} diff --git a/src/Analyzers/KnownTypeSymbols.Functions.cs b/src/Analyzers/KnownTypeSymbols.Functions.cs new file mode 100644 index 00000000..a0c106ba --- /dev/null +++ b/src/Analyzers/KnownTypeSymbols.Functions.cs @@ -0,0 +1,46 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.DurableTask.Analyzers; + +/// +/// Provides a set of well-known types that are used by the analyzers. +/// Inspired by KnownTypeSymbols class in +/// System.Text.Json.SourceGeneration source code. +/// Lazy initialization is used to avoid the the initialization of all types during class construction, since not all symbols are used by all analyzers. +/// +public sealed partial class KnownTypeSymbols +{ + INamedTypeSymbol? functionOrchestrationAttribute; + INamedTypeSymbol? functionNameAttribute; + INamedTypeSymbol? durableClientAttribute; + INamedTypeSymbol? entityTriggerAttribute; + INamedTypeSymbol? taskEntityDispatcher; + + /// + /// Gets an OrchestrationTriggerAttribute type symbol. + /// + public INamedTypeSymbol? FunctionOrchestrationAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.OrchestrationTriggerAttribute", ref this.functionOrchestrationAttribute); + + /// + /// Gets a FunctionNameAttribute type symbol. + /// + public INamedTypeSymbol? FunctionNameAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.FunctionAttribute", ref this.functionNameAttribute); + + /// + /// Gets a DurableClientAttribute type symbol. + /// + public INamedTypeSymbol? DurableClientAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.DurableClientAttribute", ref this.durableClientAttribute); + + /// + /// Gets an EntityTriggerAttribute type symbol. + /// + public INamedTypeSymbol? EntityTriggerAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.EntityTriggerAttribute", ref this.entityTriggerAttribute); + + /// + /// Gets a TaskEntityDispatcher type symbol. + /// + public INamedTypeSymbol? TaskEntityDispatcher => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.TaskEntityDispatcher", ref this.taskEntityDispatcher); +} diff --git a/src/Analyzers/KnownTypeSymbols.Net.cs b/src/Analyzers/KnownTypeSymbols.Net.cs new file mode 100644 index 00000000..5e7467a7 --- /dev/null +++ b/src/Analyzers/KnownTypeSymbols.Net.cs @@ -0,0 +1,40 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT License. + +using Microsoft.CodeAnalysis; + +namespace Microsoft.DurableTask.Analyzers; + +/// +/// Provides a set of well-known types that are used by the analyzers. +/// Inspired by KnownTypeSymbols class in +/// System.Text.Json.SourceGeneration source code. +/// Lazy initialization is used to avoid the the initialization of all types during class construction, since not all symbols are used by all analyzers. +/// +public sealed partial class KnownTypeSymbols +{ + INamedTypeSymbol? guid; + INamedTypeSymbol? thread; + INamedTypeSymbol? task; + INamedTypeSymbol? taskT; + + /// + /// Gets a Guid type symbol. + /// + public INamedTypeSymbol? GuidType => this.GetOrResolveFullyQualifiedType(typeof(Guid).FullName, ref this.guid); + + /// + /// Gets a Thread type symbol. + /// + public INamedTypeSymbol? Thread => this.GetOrResolveFullyQualifiedType(typeof(Thread).FullName, ref this.thread); + + /// + /// Gets a Task type symbol. + /// + public INamedTypeSymbol? Task => this.GetOrResolveFullyQualifiedType(typeof(Task).FullName, ref this.task); + + /// + /// Gets a Task<T> type symbol. + /// + public INamedTypeSymbol? TaskT => this.GetOrResolveFullyQualifiedType(typeof(Task<>).FullName, ref this.taskT); +} diff --git a/src/Analyzers/KnownTypeSymbols.cs b/src/Analyzers/KnownTypeSymbols.cs index 84debe2e..a4144fd2 100644 --- a/src/Analyzers/KnownTypeSymbols.cs +++ b/src/Analyzers/KnownTypeSymbols.cs @@ -11,95 +11,10 @@ namespace Microsoft.DurableTask.Analyzers; /// System.Text.Json.SourceGeneration source code. /// Lazy initialization is used to avoid the the initialization of all types during class construction, since not all symbols are used by all analyzers. /// -public sealed class KnownTypeSymbols(Compilation compilation) +public sealed partial class KnownTypeSymbols(Compilation compilation) { readonly Compilation compilation = compilation; - INamedTypeSymbol? functionOrchestrationAttribute; - INamedTypeSymbol? functionNameAttribute; - INamedTypeSymbol? taskOrchestratorInterface; - INamedTypeSymbol? taskOrchestratorBaseClass; - INamedTypeSymbol? durableTaskRegistry; - INamedTypeSymbol? taskOrchestrationContext; - INamedTypeSymbol? durableClientAttribute; - INamedTypeSymbol? durableTaskClient; - INamedTypeSymbol? entityTriggerAttribute; - INamedTypeSymbol? taskEntityDispatcher; - INamedTypeSymbol? guid; - INamedTypeSymbol? thread; - INamedTypeSymbol? task; - INamedTypeSymbol? taskT; - - /// - /// Gets an OrchestrationTriggerAttribute type symbol. - /// - public INamedTypeSymbol? FunctionOrchestrationAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.OrchestrationTriggerAttribute", ref this.functionOrchestrationAttribute); - - /// - /// Gets a FunctionNameAttribute type symbol. - /// - public INamedTypeSymbol? FunctionNameAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.FunctionAttribute", ref this.functionNameAttribute); - - /// - /// Gets an ITaskOrchestrator type symbol. - /// - public INamedTypeSymbol? TaskOrchestratorInterface => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.ITaskOrchestrator", ref this.taskOrchestratorInterface); - - /// - /// Gets a TaskOrchestrator type symbol. - /// - public INamedTypeSymbol? TaskOrchestratorBaseClass => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.TaskOrchestrator`2", ref this.taskOrchestratorBaseClass); - - /// - /// Gets a DurableTaskRegistry type symbol. - /// - public INamedTypeSymbol? DurableTaskRegistry => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.DurableTaskRegistry", ref this.durableTaskRegistry); - - /// - /// Gets a TaskOrchestrationContext type symbol. - /// - public INamedTypeSymbol? TaskOrchestrationContext => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.TaskOrchestrationContext", ref this.taskOrchestrationContext); - - /// - /// Gets a DurableClientAttribute type symbol. - /// - public INamedTypeSymbol? DurableClientAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.DurableClientAttribute", ref this.durableClientAttribute); - - /// - /// Gets a DurableTaskClient type symbol. - /// - public INamedTypeSymbol? DurableTaskClient => this.GetOrResolveFullyQualifiedType("Microsoft.DurableTask.Client.DurableTaskClient", ref this.durableTaskClient); - - /// - /// Gets an EntityTriggerAttribute type symbol. - /// - public INamedTypeSymbol? EntityTriggerAttribute => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.EntityTriggerAttribute", ref this.entityTriggerAttribute); - - /// - /// Gets a TaskEntityDispatcher type symbol. - /// - public INamedTypeSymbol? TaskEntityDispatcher => this.GetOrResolveFullyQualifiedType("Microsoft.Azure.Functions.Worker.TaskEntityDispatcher", ref this.taskEntityDispatcher); - - /// - /// Gets a Guid type symbol. - /// - public INamedTypeSymbol? GuidType => this.GetOrResolveFullyQualifiedType(typeof(Guid).FullName, ref this.guid); - - /// - /// Gets a Thread type symbol. - /// - public INamedTypeSymbol? Thread => this.GetOrResolveFullyQualifiedType(typeof(Thread).FullName, ref this.thread); - - /// - /// Gets a Task type symbol. - /// - public INamedTypeSymbol? Task => this.GetOrResolveFullyQualifiedType(typeof(Task).FullName, ref this.task); - - /// - /// Gets a Task<T> type symbol. - /// - public INamedTypeSymbol? TaskT => this.GetOrResolveFullyQualifiedType(typeof(Task<>).FullName, ref this.taskT); - INamedTypeSymbol? GetOrResolveFullyQualifiedType(string fullyQualifiedName, ref INamedTypeSymbol? field) { if (field != null) From 6df3a5246a5dd46e4d07cea6d07c849cf8d3717e Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Fri, 3 May 2024 17:03:07 -0300 Subject: [PATCH 4/5] Update src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs Co-authored-by: Varshitha Bachu --- .../AttributeBinding/MatchingAttributeBindingAnalyzer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs b/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs index 5ed02e94..cf9dfc8f 100644 --- a/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs +++ b/src/Analyzers/AttributeBinding/MatchingAttributeBindingAnalyzer.cs @@ -60,7 +60,7 @@ public override void Initialize(AnalysisContext context) /// After an incorrect attribute/type matching is found, this method is called so the concrete implementation can report a diagnostic. /// /// Context for a symbol action. Allows reporting a diagnostic. - /// Expected binding for a attribute/type. + /// Expected binding for an attribute/type. /// Analyzed parameter symbol. protected abstract void ReportDiagnostic(SymbolAnalysisContext ctx, ExpectedBinding expected, IParameterSymbol parameter); From 3ff4745eccebf003ba2a881c33cfb1e415c571cb Mon Sep 17 00:00:00 2001 From: Allan Targino <13934447+allantargino@users.noreply.github.com> Date: Fri, 3 May 2024 17:58:38 -0300 Subject: [PATCH 5/5] removing extra header --- .../AttributeBinding/DurableClientBindingAnalyzerTests.cs | 4 ---- .../AttributeBinding/EntityTriggerBindingAnalyzerTests.cs | 4 ---- 2 files changed, 8 deletions(-) diff --git a/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs index f609cb68..a44842fb 100644 --- a/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/DurableClientBindingAnalyzerTests.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding; diff --git a/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs b/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs index 2854f87c..bde399f4 100644 --- a/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs +++ b/test/Analyzers.Tests/Functions/AttributeBinding/EntityTriggerBindingAnalyzerTests.cs @@ -1,10 +1,6 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. - -// Copyright (c) Microsoft Corporation. -// Licensed under the MIT License. - using Microsoft.DurableTask.Analyzers.Functions.AttributeBinding; namespace Microsoft.DurableTask.Analyzers.Tests.Functions.AttributeBinding;