Skip to content

Commit

Permalink
[GH-153] - using operation API to find callInfo usages
Browse files Browse the repository at this point in the history
  • Loading branch information
tpodolak committed Mar 7, 2021
1 parent e446585 commit 779f13f
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 14 deletions.
2 changes: 1 addition & 1 deletion global.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"sdk": {
"version": "3.1.201"
"version": "3.1.404"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ protected override IEnumerable<SyntaxNode> FindInvocations(SyntaxNodeAnalysisCon
foreach (var invocationExpressionSyntax in body.DescendantNodes().Where(node => node.IsKind(SyntaxKind.SimpleMemberAccessExpression) ||
node.IsKind(SyntaxKind.ElementAccessExpression)))
{
var parentNode = invocationExpressionSyntax.Parent;
if (parentNode.IsKind(SyntaxKind.ElementAccessExpression))
{
continue;
}

yield return invocationExpressionSyntax;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ private void AnalyzeInvocation(SyntaxNodeAnalysisContext syntaxNodeContext)

foreach (var argumentExpressionSyntax in invocationOperation.GetOrderedArgumentOperationsWithoutInstanceArgument())
{
var callInfoContext = _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentExpressionSyntax.Value.Syntax);
var callInfoContext = _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentExpressionSyntax);

AnalyzeArgAtInvocations(syntaxNodeContext, callInfoContext, substituteCallParameters);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Operations;
using NSubstitute.Analyzers.Shared.Extensions;

namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers
{
internal abstract class AbstractCallInfoFinder : ICallInfoFinder
{
public CallInfoContext GetCallInfoContext(
SemanticModel semanticModel, SyntaxNode syntaxNode)
public CallInfoContext GetCallInfoContext(SemanticModel semanticModel, IArgumentOperation argumentOperation)
{
var callInfoParameterSymbol = GetCallInfoParameterSymbol(semanticModel, syntaxNode);
if (callInfoParameterSymbol == null)
var callContext = CallInfoContext.Empty;
foreach (var syntaxNode in argumentOperation.GetSyntaxes())
{
return CallInfoContext.Empty;
var callInfoParameterSymbol = GetCallInfoParameterSymbol(semanticModel, syntaxNode);
var currentContext = GetCallInfoContextInternal(semanticModel, syntaxNode);
callContext = callContext.Merge(CreateFilteredCallInfoContext(semanticModel, currentContext, callInfoParameterSymbol));
}

var callContext = GetCallInfoContextInternal(semanticModel, syntaxNode);

return CreateFilteredCallInfoContext(semanticModel, callContext, callInfoParameterSymbol);
return callContext;
}

protected abstract CallInfoContext GetCallInfoContextInternal(SemanticModel semanticModel, SyntaxNode syntaxNode);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ private IEnumerable<SyntaxNode> FindCallInfoIndexers(SyntaxNodeAnalysisContext s
// perf - dont use linq in hotpaths
foreach (var argumentOperation in invocationOperation.GetOrderedArgumentOperationsWithoutInstanceArgument())
{
foreach (var indexerExpressionSyntax in _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentOperation.Value.Syntax).IndexerAccesses)
foreach (var indexerExpressionSyntax in _callInfoFinder.GetCallInfoContext(syntaxNodeContext.SemanticModel, argumentOperation).IndexerAccesses)
{
if (IsAssigned(syntaxNodeContext, indexerExpressionSyntax))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,11 +29,11 @@ protected AbstractNonSubstitutableMemberReceivedInOrderAnalyzer(
: base(diagnosticDescriptorsProvider, nonSubstitutableMemberAnalysis)
{
_substitutionNodeFinder = substitutionNodeFinder;
_analyzeInvocationAction = AnalyzeInvocation;
NonVirtualSetupDescriptor = diagnosticDescriptorsProvider.NonVirtualReceivedInOrderSetupSpecification;
SupportedDiagnostics = ImmutableArray.Create(
DiagnosticDescriptorsProvider.InternalSetupSpecification,
DiagnosticDescriptorsProvider.NonVirtualReceivedInOrderSetupSpecification);
_analyzeInvocationAction = AnalyzeInvocation;
NonVirtualSetupDescriptor = diagnosticDescriptorsProvider.NonVirtualReceivedInOrderSetupSpecification;
}

protected override DiagnosticDescriptor NonVirtualSetupDescriptor { get; }
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;

namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers
Expand All @@ -26,5 +27,13 @@ public CallInfoContext(
ArgAtInvocations = argAtInvocations;
ArgInvocations = argInvocations;
}

public CallInfoContext Merge(CallInfoContext callInfoContext)
{
return new CallInfoContext(
ArgAtInvocations.Concat(callInfoContext.ArgAtInvocations).ToList(),
ArgInvocations.Concat(callInfoContext.ArgInvocations).ToList(),
IndexerAccesses.Concat(callInfoContext.IndexerAccesses).ToList());
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Operations;

namespace NSubstitute.Analyzers.Shared.DiagnosticAnalyzers
{
internal interface ICallInfoFinder
{
CallInfoContext GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode);
CallInfoContext GetCallInfoContext(SemanticModel semanticModel, IArgumentOperation argumentOperation);
}
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -109,6 +110,23 @@ public static IOperation GetSubstituteOperation(this IInvocationOperation invoca
return (int)literal.ConstantValue.Value;
}

public static IEnumerable<SyntaxNode> GetSyntaxes(this IArgumentOperation argumentOperation)
{
if (argumentOperation.Parameter.IsParams)
{
var initializerElementValues = (argumentOperation.Value as IArrayCreationOperation)?.Initializer.ElementValues;

foreach (var operation in initializerElementValues ?? Enumerable.Empty<IOperation>())
{
yield return operation.Syntax;
}

yield break;
}

yield return argumentOperation.Value.Syntax;
}

private static bool IsImplicitlyProvidedArrayWithoutValues(IArgumentOperation arg)
{
return arg.IsImplicit &&
Expand Down

0 comments on commit 779f13f

Please sign in to comment.