From 238203261c674fa76ff3765dcb21ff46e4a3d96b Mon Sep 17 00:00:00 2001 From: tpodolak Date: Wed, 3 Apr 2019 22:09:45 +0200 Subject: [PATCH] [GH-76] - removing code duplication for finding substitution node --- .../DiagnosticAnalyzers/CallInfoAnalyzer.cs | 12 +-------- .../DiagnosticAnalyzers/CallInfoCallFinder.cs | 4 +-- .../ConflictingArgumentAssignmentsAnalyzer.cs | 7 +---- .../NonSubstitutableMemberWhenAnalyzer.cs | 7 +---- .../ReEntrantSetupAnalyzer.cs | 7 +---- .../SubstitutionNodeFinder.cs | 12 ++++----- .../AbstractCallInfoAnalyzer.cs | 26 +++++++------------ .../AbstractCallInfoFinder.cs | 9 ------- ...tConflictingArgumentAssignmentsAnalyzer.cs | 9 ++++--- ...tractNonSubstitutableMemberWhenAnalyzer.cs | 14 ++++------ .../AbstractReEntrantCallFinder.cs | 2 +- .../AbstractReEntrantSetupAnalyzer.cs | 14 ++++------ .../AbstractSubstitutionNodeFinder.cs | 10 +++---- .../DiagnosticAnalyzers/ICallInfoFinder.cs | 9 +++++++ .../IReEntrantCallFinder.cs | 10 +++++++ .../ISubstitutionNodeFinder.cs | 17 ++++++++++++ .../DiagnosticAnalyzers/CallInfoAnalyzer.cs | 12 +-------- .../DiagnosticAnalyzers/CallInfoCallFinder.cs | 4 +-- .../ConflictingArgumentAssignmentsAnalyzer.cs | 7 +---- .../NonSubstitutableMemberWhenAnalyzer.cs | 7 +---- .../ReEntrantSetupAnalyzer.cs | 7 +---- .../SubstitutionNodeFinder.cs | 12 ++++----- 22 files changed, 91 insertions(+), 127 deletions(-) delete mode 100644 src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoFinder.cs create mode 100644 src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ICallInfoFinder.cs create mode 100644 src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/IReEntrantCallFinder.cs create mode 100644 src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ISubstitutionNodeFinder.cs diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoAnalyzer.cs index 89eb53eb..4e6b21a2 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoAnalyzer.cs @@ -13,7 +13,7 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers internal class CallInfoAnalyzer : AbstractCallInfoAnalyzer { public CallInfoAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new CallInfoCallFinder(), new SubstitutionNodeFinder()) { } @@ -24,16 +24,6 @@ protected override IEnumerable GetArgumentExpressions(Invocati return invocationExpressionSyntax.ArgumentList.Arguments.Select(arg => arg.Expression); } - protected override AbstractCallInfoFinder GetCallInfoFinder() - { - return new CallInfoCallFinder(); - } - - protected override AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder() - { - return new SubstitutionNodeFinder(); - } - protected override SyntaxNode GetCastTypeExpression(ElementAccessExpressionSyntax indexerExpressionSyntax) { switch (indexerExpressionSyntax.Parent) diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoCallFinder.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoCallFinder.cs index a27436c1..c6c1e14a 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoCallFinder.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoCallFinder.cs @@ -7,9 +7,9 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers { - internal class CallInfoCallFinder : AbstractCallInfoFinder + internal class CallInfoCallFinder : ICallInfoFinder { - public override CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode) + public CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode) { var visitor = new CallInfoVisitor(semanticModel); visitor.Visit(syntaxNode); diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs index e2d78a83..e9100f96 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs @@ -14,7 +14,7 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers internal class ConflictingArgumentAssignmentsAnalyzer : AbstractConflictingArgumentAssignmentsAnalyzer { public ConflictingArgumentAssignmentsAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new CallInfoCallFinder()) { } @@ -30,11 +30,6 @@ protected override SyntaxNode GetSubstituteCall(SyntaxNodeAnalysisContext syntax return invocationExpressionSyntax.GetParentInvocationExpression(); } - protected override AbstractCallInfoFinder GetCallInfoFinder() - { - return new CallInfoCallFinder(); - } - protected override int? GetIndexerPosition(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, ElementAccessExpressionSyntax indexerExpressionSyntax) { var position = syntaxNodeAnalysisContext.SemanticModel.GetConstantValue(indexerExpressionSyntax.ArgumentList.Arguments.First().Expression); diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs index bb4daf67..fe683de3 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs @@ -13,15 +13,10 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers internal class NonSubstitutableMemberWhenAnalyzer : AbstractNonSubstitutableMemberWhenAnalyzer { public NonSubstitutableMemberWhenAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new SubstitutionNodeFinder()) { } protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; - - protected override AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder() - { - return new SubstitutionNodeFinder(); - } } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs index 219561e2..e7ed366e 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs @@ -13,15 +13,10 @@ namespace NSubstitute.Analyzers.CSharp.DiagnosticAnalyzers internal class ReEntrantSetupAnalyzer : AbstractReEntrantSetupAnalyzer { public ReEntrantSetupAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new ReEntrantCallFinder()) { } - protected override AbstractReEntrantCallFinder GetReEntrantCallFinder() - { - return new ReEntrantCallFinder(); - } - protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; protected override IEnumerable ExtractArguments(InvocationExpressionSyntax invocationExpressionSyntax) diff --git a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/SubstitutionNodeFinder.cs b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/SubstitutionNodeFinder.cs index 3d40d6c1..18737878 100644 --- a/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/SubstitutionNodeFinder.cs +++ b/src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/SubstitutionNodeFinder.cs @@ -51,12 +51,7 @@ public override SyntaxNode FindForAndDoesExpression(SyntaxNodeAnalysisContext sy : parentInvocationExpression.Expression.DescendantNodes().First(); } - protected override InvocationExpressionSyntax GetParentInvocationExpression(InvocationExpressionSyntax invocationExpressionSyntax) - { - return invocationExpressionSyntax.GetParentInvocationExpression(); - } - - protected override SyntaxNode FindForStandardSubstitution(InvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol) + public override SyntaxNode FindForStandardExpression(InvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol) { switch (invocationExpressionSymbol.MethodKind) { @@ -69,6 +64,11 @@ protected override SyntaxNode FindForStandardSubstitution(InvocationExpressionSy } } + protected override InvocationExpressionSyntax GetParentInvocationExpression(InvocationExpressionSyntax invocationExpressionSyntax) + { + return invocationExpressionSyntax.GetParentInvocationExpression(); + } + private IEnumerable FindForWhenExpression(SyntaxNodeAnalysisContext syntaxNodeContext, SyntaxNode argumentSyntax) { SyntaxNode body = null; diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoAnalyzer.cs index b6c5a1b9..4a2a9f3e 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoAnalyzer.cs @@ -14,19 +14,17 @@ internal abstract class AbstractCallInfoAnalyzer> _callInfoFinderProxy; + private readonly ICallInfoFinder _callInfoFinder; + private readonly ISubstitutionNodeFinder _substitutionNodeFinder; - private readonly Lazy> _substitutionNodeFinderProxy; - - private AbstractCallInfoFinder CallInfoFinder => _callInfoFinderProxy.Value; - - private AbstractSubstitutionNodeFinder SubstitutionNodeFinder => _substitutionNodeFinderProxy.Value; - - protected AbstractCallInfoAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider) + protected AbstractCallInfoAnalyzer( + IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider, + ICallInfoFinder callInfoFinder, + ISubstitutionNodeFinder substitutionNodeFinder) : base(diagnosticDescriptorsProvider) { - _callInfoFinderProxy = new Lazy>(GetCallInfoFinder); - _substitutionNodeFinderProxy = new Lazy>(GetSubstitutionNodeFinder); + _callInfoFinder = callInfoFinder; + _substitutionNodeFinder = substitutionNodeFinder; } private static readonly ImmutableDictionary MethodNames = new Dictionary() @@ -56,10 +54,6 @@ public override void Initialize(AnalysisContext context) protected abstract IEnumerable GetArgumentExpressions(TInvocationExpressionSyntax invocationExpressionSyntax); - protected abstract AbstractCallInfoFinder GetCallInfoFinder(); - - protected abstract AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder(); - protected abstract SyntaxNode GetCastTypeExpression(TIndexerExpressionSyntax indexerExpressionSyntax); protected abstract SyntaxNode GetAssignmentExpression(TIndexerExpressionSyntax indexerExpressionSyntax); @@ -130,7 +124,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) foreach (var argumentExpressionSyntax in GetArgumentExpressions(invocationExpression)) { - var callInfoContext = CallInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentExpressionSyntax); + var callInfoContext = _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentExpressionSyntax); AnalyzeArgAtInvocations(syntaxNodeContext, callInfoContext, substituteCallParameters); @@ -303,7 +297,7 @@ private bool AnalyzeAssignment(SyntaxNodeAnalysisContext syntaxNodeContext, ILis private IList GetSubstituteCallParameters(SyntaxNodeAnalysisContext syntaxNodeContext, IMethodSymbol methodSymbol, TInvocationExpressionSyntax invocationExpression) { - var parentMethodCallSyntax = SubstitutionNodeFinder.Find(syntaxNodeContext, invocationExpression, methodSymbol).FirstOrDefault(); + var parentMethodCallSyntax = _substitutionNodeFinder.Find(syntaxNodeContext, invocationExpression, methodSymbol).FirstOrDefault(); if (parentMethodCallSyntax == null) { diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoFinder.cs deleted file mode 100644 index 28e0f20e..00000000 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractCallInfoFinder.cs +++ /dev/null @@ -1,9 +0,0 @@ -using Microsoft.CodeAnalysis; - -namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers -{ - internal abstract class AbstractCallInfoFinder - { - public abstract CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode); - } -} \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractConflictingArgumentAssignmentsAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractConflictingArgumentAssignmentsAnalyzer.cs index 69fbc237..f4cf8e76 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractConflictingArgumentAssignmentsAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractConflictingArgumentAssignmentsAnalyzer.cs @@ -14,9 +14,12 @@ internal abstract class AbstractConflictingArgumentAssignmentsAnalyzer _callInfoFinder; + + protected AbstractConflictingArgumentAssignmentsAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider, ICallInfoFinder callInfoFinder) : base(diagnosticDescriptorsProvider) { + _callInfoFinder = callInfoFinder; SupportedDiagnostics = ImmutableArray.Create(DiagnosticDescriptorsProvider.ConflictingArgumentAssignments); } @@ -38,8 +41,6 @@ public override void Initialize(AnalysisContext context) protected abstract SyntaxNode GetSubstituteCall(SyntaxNodeAnalysisContext syntaxNodeContext, IMethodSymbol methodSymbol, TInvocationExpressionSyntax invocationExpressionSyntax); - protected abstract AbstractCallInfoFinder GetCallInfoFinder(); - protected abstract int? GetIndexerPosition(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, TIndexerExpressionSyntax indexerExpressionSyntax); protected abstract ISymbol GetIndexerSymbol(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, TIndexerExpressionSyntax indexerExpressionSyntax); @@ -110,7 +111,7 @@ private bool IsAssigned(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, TIn private IEnumerable FindCallInfoIndexers(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpressionSyntax) { - return GetArgumentExpressions(invocationExpressionSyntax).SelectMany(argument => GetCallInfoFinder().GetCallInfoContext(syntaxNodeContext.SemanticModel, argument).IndexerAccesses) + return GetArgumentExpressions(invocationExpressionSyntax).SelectMany(argument => _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argument).IndexerAccesses) .Where(indexerExpression => IsAssigned(syntaxNodeContext, indexerExpression)); } } diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberWhenAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberWhenAnalyzer.cs index 5cc197d8..4c1e376f 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberWhenAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractNonSubstitutableMemberWhenAnalyzer.cs @@ -12,6 +12,8 @@ internal abstract class AbstractNonSubstitutableMemberWhenAnalyzer _substitutionNodeFinder; + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create( DiagnosticDescriptorsProvider.NonVirtualWhenSetupSpecification, DiagnosticDescriptorsProvider.InternalSetupSpecification); @@ -22,14 +24,10 @@ internal abstract class AbstractNonSubstitutableMemberWhenAnalyzer> _substitutionNodeFinderProxy; - - private AbstractSubstitutionNodeFinder SubstitutionNodeFinderProxy => _substitutionNodeFinderProxy.Value; - - protected AbstractNonSubstitutableMemberWhenAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider) + protected AbstractNonSubstitutableMemberWhenAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider, ISubstitutionNodeFinder substitutionNodeFinder) : base(diagnosticDescriptorsProvider) { - _substitutionNodeFinderProxy = new Lazy>(GetSubstitutionNodeFinder); + _substitutionNodeFinder = substitutionNodeFinder; } public override void Initialize(AnalysisContext context) @@ -37,8 +35,6 @@ public override void Initialize(AnalysisContext context) context.RegisterSyntaxNodeAction(AnalyzeInvocation, InvocationExpressionKind); } - protected abstract AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder(); - private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) { var invocationExpression = (TInvocationExpressionSyntax)syntaxNodeContext.Node; @@ -60,7 +56,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) return; } - var expressionsForAnalysys = SubstitutionNodeFinderProxy.FindForWhenExpression(syntaxNodeContext, invocationExpression, methodSymbol); + var expressionsForAnalysys = _substitutionNodeFinder.FindForWhenExpression(syntaxNodeContext, invocationExpression, methodSymbol); var typeSymbol = methodSymbol.TypeArguments.FirstOrDefault() ?? methodSymbol.ReceiverType; foreach (var analysedSyntax in expressionsForAnalysys) { diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantCallFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantCallFinder.cs index c28cf09d..b393413e 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantCallFinder.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantCallFinder.cs @@ -7,7 +7,7 @@ namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers { - internal abstract class AbstractReEntrantCallFinder + internal abstract class AbstractReEntrantCallFinder : IReEntrantCallFinder { private static readonly ImmutableDictionary MethodNames = new Dictionary() { diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantSetupAnalyzer.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantSetupAnalyzer.cs index 1a28c982..2f074cd6 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantSetupAnalyzer.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractReEntrantSetupAnalyzer.cs @@ -11,25 +11,21 @@ internal abstract class AbstractReEntrantSetupAnalyzer MethodNames = ImmutableHashSet.Create( MetadataNames.NSubstituteReturnsMethod, MetadataNames.NSubstituteReturnsForAnyArgsMethod); - private AbstractReEntrantCallFinder ReEntrantCallFinder => _reEntrantCallFinderProxy.Value; - - private readonly Lazy _reEntrantCallFinderProxy; - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(DiagnosticDescriptorsProvider.ReEntrantSubstituteCall); - protected AbstractReEntrantSetupAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider) + protected AbstractReEntrantSetupAnalyzer(IDiagnosticDescriptorsProvider diagnosticDescriptorsProvider, IReEntrantCallFinder reEntrantCallFinder) : base(diagnosticDescriptorsProvider) { - _reEntrantCallFinderProxy = new Lazy(GetReEntrantCallFinder); + _reEntrantCallFinder = reEntrantCallFinder; } - protected abstract AbstractReEntrantCallFinder GetReEntrantCallFinder(); - protected abstract TSyntaxKind InvocationExpressionKind { get; } public override void Initialize(AnalysisContext context) @@ -61,7 +57,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext) foreach (var argument in argumentsForAnalysis) { - var reentrantSymbol = ReEntrantCallFinder.GetReEntrantCalls(syntaxNodeContext.Compilation, argument).FirstOrDefault(); + var reentrantSymbol = _reEntrantCallFinder.GetReEntrantCalls(syntaxNodeContext.Compilation, argument).FirstOrDefault(); if (reentrantSymbol != null) { var diagnostic = Diagnostic.Create( diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstitutionNodeFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstitutionNodeFinder.cs index e5d88dc0..32e5af67 100644 --- a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstitutionNodeFinder.cs +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/AbstractSubstitutionNodeFinder.cs @@ -6,7 +6,7 @@ namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers { - internal abstract class AbstractSubstitutionNodeFinder + internal abstract class AbstractSubstitutionNodeFinder : ISubstitutionNodeFinder where TInvocationExpressionSyntax : SyntaxNode { public IEnumerable Find(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpression, IMethodSymbol invocationExpressionSymbol = null) @@ -36,17 +36,17 @@ public IEnumerable Find(SyntaxNodeAnalysisContext syntaxNodeContext, return substitution != null ? new[] { substitution } : Enumerable.Empty(); } - var standardSubstitution = FindForStandardSubstitution(invocationExpression, invocationExpressionSymbol); + var standardSubstitution = FindForStandardExpression(invocationExpression, invocationExpressionSymbol); return standardSubstitution != null ? new[] { standardSubstitution } : Enumerable.Empty(); } public abstract IEnumerable FindForWhenExpression(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax whenInvocationExpression, IMethodSymbol whenInvocationSymbol = null); - public abstract SyntaxNode FindForAndDoesExpression(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpression, IMethodSymbol invocationExpressionSymbol); + public abstract SyntaxNode FindForAndDoesExpression(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpression, IMethodSymbol invocationExpressionSymbol = null); - protected abstract TInvocationExpressionSyntax GetParentInvocationExpression(TInvocationExpressionSyntax invocationExpressionSyntax); + public abstract SyntaxNode FindForStandardExpression(TInvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol = null); - protected abstract SyntaxNode FindForStandardSubstitution(TInvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol methodSymbol); + protected abstract TInvocationExpressionSyntax GetParentInvocationExpression(TInvocationExpressionSyntax invocationExpressionSyntax); } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ICallInfoFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ICallInfoFinder.cs new file mode 100644 index 00000000..32472528 --- /dev/null +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ICallInfoFinder.cs @@ -0,0 +1,9 @@ +using Microsoft.CodeAnalysis; + +namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers +{ + internal interface ICallInfoFinder + { + CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode); + } +} \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/IReEntrantCallFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/IReEntrantCallFinder.cs new file mode 100644 index 00000000..157cd09a --- /dev/null +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/IReEntrantCallFinder.cs @@ -0,0 +1,10 @@ +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; + +namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers +{ + internal interface IReEntrantCallFinder + { + ImmutableList GetReEntrantCalls(Compilation compilation, SyntaxNode rootNode); + } +} \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ISubstitutionNodeFinder.cs b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ISubstitutionNodeFinder.cs new file mode 100644 index 00000000..5d80d6b8 --- /dev/null +++ b/src/NSubstitute.Analyzers.Shared/DiagnosticAnalyzers/ISubstitutionNodeFinder.cs @@ -0,0 +1,17 @@ +using System.Collections.Generic; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers +{ + internal interface ISubstitutionNodeFinder where TInvocationExpressionSyntax : SyntaxNode + { + IEnumerable Find(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpression, IMethodSymbol invocationExpressionSymbol = null); + + IEnumerable FindForWhenExpression(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax whenInvocationExpression, IMethodSymbol whenInvocationSymbol = null); + + SyntaxNode FindForAndDoesExpression(SyntaxNodeAnalysisContext syntaxNodeContext, TInvocationExpressionSyntax invocationExpression, IMethodSymbol invocationExpressionSymbol = null); + + SyntaxNode FindForStandardExpression(TInvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol = null); + } +} \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoAnalyzer.cs index 8a656c9d..4abae668 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoAnalyzer.cs @@ -13,7 +13,7 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers internal class CallInfoAnalyzer : AbstractCallInfoAnalyzer { public CallInfoAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new CallInfoCallFinder(), new SubstitutionNodeFinder()) { } @@ -24,16 +24,6 @@ protected override IEnumerable GetArgumentExpressions(Invocati return invocationExpressionSyntax.ArgumentList.Arguments.Select(arg => arg.GetExpression()); } - protected override AbstractCallInfoFinder GetCallInfoFinder() - { - return new CallInfoCallFinder(); - } - - protected override AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder() - { - return new SubstitutionNodeFinder(); - } - protected override SyntaxNode GetCastTypeExpression(InvocationExpressionSyntax indexerExpressionSyntax) { if (indexerExpressionSyntax.Parent is CastExpressionSyntax castExpressionSyntax) diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoCallFinder.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoCallFinder.cs index a9f6841f..3f3cd8d4 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoCallFinder.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoCallFinder.cs @@ -7,9 +7,9 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers { - internal class CallInfoCallFinder : AbstractCallInfoFinder + internal class CallInfoCallFinder : ICallInfoFinder { - public override CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode) + public CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode) { var visitor = new CallInfoVisitor(semanticModel); visitor.Visit(syntaxNode); diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs index 26a941db..675a1642 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ConflictingArgumentAssignmentsAnalyzer.cs @@ -13,7 +13,7 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers internal class ConflictingArgumentAssignmentsAnalyzer : AbstractConflictingArgumentAssignmentsAnalyzer { public ConflictingArgumentAssignmentsAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new CallInfoCallFinder()) { } @@ -29,11 +29,6 @@ protected override SyntaxNode GetSubstituteCall(SyntaxNodeAnalysisContext syntax return invocationExpressionSyntax.GetParentInvocationExpression(); } - protected override AbstractCallInfoFinder GetCallInfoFinder() - { - return new CallInfoCallFinder(); - } - protected override int? GetIndexerPosition(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, InvocationExpressionSyntax indexerExpressionSyntax) { var position = syntaxNodeAnalysisContext.SemanticModel.GetConstantValue(indexerExpressionSyntax.ArgumentList.Arguments.First().GetExpression()); diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs index 5029b031..3baf83d4 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/NonSubstitutableMemberWhenAnalyzer.cs @@ -13,15 +13,10 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers internal class NonSubstitutableMemberWhenAnalyzer : AbstractNonSubstitutableMemberWhenAnalyzer { public NonSubstitutableMemberWhenAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new SubstitutionNodeFinder()) { } protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; - - protected override AbstractSubstitutionNodeFinder GetSubstitutionNodeFinder() - { - return new SubstitutionNodeFinder(); - } } } \ No newline at end of file diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs index 1d2c2b43..1b0298e9 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/ReEntrantSetupAnalyzer.cs @@ -12,15 +12,10 @@ namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers internal class ReEntrantSetupAnalyzer : AbstractReEntrantSetupAnalyzer { public ReEntrantSetupAnalyzer() - : base(new DiagnosticDescriptorsProvider()) + : base(new DiagnosticDescriptorsProvider(), new ReEntrantCallFinder()) { } - protected override AbstractReEntrantCallFinder GetReEntrantCallFinder() - { - return new ReEntrantCallFinder(); - } - protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; protected override IEnumerable ExtractArguments(InvocationExpressionSyntax invocationExpressionSyntax) diff --git a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/SubstitutionNodeFinder.cs b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/SubstitutionNodeFinder.cs index 477b977a..87bf81c2 100644 --- a/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/SubstitutionNodeFinder.cs +++ b/src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/SubstitutionNodeFinder.cs @@ -47,12 +47,7 @@ public override SyntaxNode FindForAndDoesExpression(SyntaxNodeAnalysisContext sy : parentInvocationExpression.Expression.DescendantNodes().First(); } - protected override InvocationExpressionSyntax GetParentInvocationExpression(InvocationExpressionSyntax invocationExpressionSyntax) - { - return invocationExpressionSyntax.GetParentInvocationExpression(); - } - - protected override SyntaxNode FindForStandardSubstitution(InvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol) + public override SyntaxNode FindForStandardExpression(InvocationExpressionSyntax invocationExpressionSyntax, IMethodSymbol invocationExpressionSymbol) { switch (invocationExpressionSymbol.MethodKind) { @@ -65,6 +60,11 @@ protected override SyntaxNode FindForStandardSubstitution(InvocationExpressionSy } } + protected override InvocationExpressionSyntax GetParentInvocationExpression(InvocationExpressionSyntax invocationExpressionSyntax) + { + return invocationExpressionSyntax.GetParentInvocationExpression(); + } + private IEnumerable FindForWhenExpression(SyntaxNodeAnalysisContext syntaxNodeContext, SyntaxNode argumentSyntax) { SyntaxNode body = null;