-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[GH-30] - Visual Basic implementation
- Loading branch information
Showing
9 changed files
with
946 additions
and
76 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 0 additions & 59 deletions
59
src/NSubstitute.Analyzers.CSharp/DiagnosticAnalyzers/CallInfoVisitor.cs
This file was deleted.
Oops, something went wrong.
91 changes: 91 additions & 0 deletions
91
src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoAnalyzer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,91 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.Diagnostics; | ||
using Microsoft.CodeAnalysis.VisualBasic; | ||
using Microsoft.CodeAnalysis.VisualBasic.Syntax; | ||
using NSubstitute.Analyzers.Shared.DiagnosticAnalyzers; | ||
|
||
namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers | ||
{ | ||
[DiagnosticAnalyzer(LanguageNames.VisualBasic)] | ||
internal class CallInfoAnalyzer : AbstractCallInfoAnalyzer<SyntaxKind, InvocationExpressionSyntax, ExpressionSyntax, InvocationExpressionSyntax> | ||
{ | ||
public CallInfoAnalyzer() | ||
: base(new DiagnosticDescriptorsProvider()) | ||
{ | ||
} | ||
|
||
protected override SyntaxKind InvocationExpressionKind { get; } = SyntaxKind.InvocationExpression; | ||
|
||
protected override SyntaxNode GetParentMethodCall(InvocationExpressionSyntax invocationExpressionSyntax) | ||
{ | ||
return invocationExpressionSyntax.Expression.DescendantNodes().First(); | ||
} | ||
|
||
protected override IEnumerable<ExpressionSyntax> GetArgumentExpressions(InvocationExpressionSyntax invocationExpressionSyntax) | ||
{ | ||
return invocationExpressionSyntax.ArgumentList.Arguments.Select(arg => arg.GetExpression()); | ||
} | ||
|
||
protected override AbstractCallInfoFinder<InvocationExpressionSyntax, InvocationExpressionSyntax> GetCallInfoFinder() | ||
{ | ||
return new CallInfoCallFinder(); | ||
} | ||
|
||
protected override SyntaxNode GetSafeCastTypeExpression(InvocationExpressionSyntax indexerExpressionSyntax) | ||
{ | ||
if (indexerExpressionSyntax.Parent is TryCastExpressionSyntax directCastExpressionSyntax) | ||
{ | ||
return directCastExpressionSyntax.Type; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected override SyntaxNode GetUnsafeCastTypeExpression(InvocationExpressionSyntax indexerExpressionSyntax) | ||
{ | ||
if (indexerExpressionSyntax.Parent is DirectCastExpressionSyntax directCastExpressionSyntax) | ||
{ | ||
return directCastExpressionSyntax.Type; | ||
} | ||
|
||
if (indexerExpressionSyntax.Parent is CTypeExpressionSyntax cTypeExpressionSyntax) | ||
{ | ||
return cTypeExpressionSyntax.Type; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected override SyntaxNode GetAssignmentExpression(InvocationExpressionSyntax indexerExpressionSyntax) | ||
{ | ||
if (indexerExpressionSyntax.Parent is AssignmentStatementSyntax assignmentStatementSyntax) | ||
{ | ||
return assignmentStatementSyntax.Right; | ||
} | ||
|
||
return null; | ||
} | ||
|
||
protected override ISymbol GetIndexerSymbol(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, InvocationExpressionSyntax indexerExpressionSyntax) | ||
{ | ||
return syntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(indexerExpressionSyntax).Symbol ?? | ||
syntaxNodeAnalysisContext.SemanticModel.GetSymbolInfo(indexerExpressionSyntax.Expression).Symbol; | ||
} | ||
|
||
protected override int? GetArgAtPosition(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, InvocationExpressionSyntax invocationExpressionSyntax) | ||
{ | ||
var argAtPosition = syntaxNodeAnalysisContext.SemanticModel.GetConstantValue(invocationExpressionSyntax.ArgumentList.Arguments.First().GetExpression()); | ||
|
||
return (int?)(argAtPosition.HasValue ? argAtPosition.Value : null); | ||
} | ||
|
||
protected override int? GetIndexerPosition(SyntaxNodeAnalysisContext syntaxNodeAnalysisContext, InvocationExpressionSyntax indexerExpressionSyntax) | ||
{ | ||
var indexerPosition = syntaxNodeAnalysisContext.SemanticModel.GetConstantValue(indexerExpressionSyntax.ArgumentList.Arguments.First().GetExpression()); | ||
|
||
return (int?)(indexerPosition.HasValue ? indexerPosition.Value : null); | ||
} | ||
} | ||
} |
70 changes: 70 additions & 0 deletions
70
src/NSubstitute.Analyzers.VisualBasic/DiagnosticAnalyzers/CallInfoCallFinder.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
using System.Collections.Generic; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.VisualBasic; | ||
using Microsoft.CodeAnalysis.VisualBasic.Syntax; | ||
using NSubstitute.Analyzers.Shared; | ||
using NSubstitute.Analyzers.Shared.DiagnosticAnalyzers; | ||
|
||
namespace NSubstitute.Analyzers.VisualBasic.DiagnosticAnalyzers | ||
{ | ||
internal class CallInfoCallFinder : AbstractCallInfoFinder<InvocationExpressionSyntax, InvocationExpressionSyntax> | ||
{ | ||
public override CallInfoContext<InvocationExpressionSyntax, InvocationExpressionSyntax> GetCallInfoContext(SemanticModel semanticModel, SyntaxNode syntaxNode) | ||
{ | ||
var visitor = new CallInfoVisitor(semanticModel); | ||
visitor.Visit(syntaxNode); | ||
|
||
return new CallInfoContext<InvocationExpressionSyntax, InvocationExpressionSyntax>(visitor.ArgAtInvocations, visitor.ArgInvocations, visitor.DirectIndexerAccesses); | ||
} | ||
|
||
private class CallInfoVisitor : VisualBasicSyntaxWalker | ||
{ | ||
private readonly SemanticModel _semanticModel; | ||
|
||
public List<InvocationExpressionSyntax> ArgAtInvocations { get; } | ||
|
||
public List<InvocationExpressionSyntax> ArgInvocations { get; } | ||
|
||
public List<InvocationExpressionSyntax> DirectIndexerAccesses { get; } | ||
|
||
public CallInfoVisitor(SemanticModel semanticModel) | ||
{ | ||
_semanticModel = semanticModel; | ||
DirectIndexerAccesses = new List<InvocationExpressionSyntax>(); | ||
ArgAtInvocations = new List<InvocationExpressionSyntax>(); | ||
ArgInvocations = new List<InvocationExpressionSyntax>(); | ||
} | ||
|
||
public override void VisitInvocationExpression(InvocationExpressionSyntax node) | ||
{ | ||
var symbol = _semanticModel.GetSymbolInfo(node).Symbol; | ||
|
||
if (symbol != null && symbol.ContainingType.ToString().Equals(MetadataNames.NSubstituteCoreFullTypeName)) | ||
{ | ||
if (symbol.Name == MetadataNames.CallInfoArgAtMethod) | ||
{ | ||
ArgAtInvocations.Add(node); | ||
} | ||
|
||
if (symbol.Name == MetadataNames.CallInfoArgMethod) | ||
{ | ||
ArgInvocations.Add(node); | ||
} | ||
} | ||
|
||
var expressionSymbol = _semanticModel.GetSymbolInfo(node.Expression).Symbol; | ||
if (symbol == null && expressionSymbol != null && expressionSymbol.ContainingType.ToString().Equals(MetadataNames.NSubstituteCoreFullTypeName)) | ||
{ | ||
DirectIndexerAccesses.Add(node); | ||
} | ||
|
||
base.VisitInvocationExpression(node); | ||
} | ||
|
||
public override void VisitMemberAccessExpression(MemberAccessExpressionSyntax node) | ||
{ | ||
base.VisitMemberAccessExpression(node); | ||
} | ||
} | ||
} | ||
} |
36 changes: 35 additions & 1 deletion
36
....Tests.CSharp/DiagnosticAnalyzerTests/CallInfoAnalyzerTests/CallInfoDiagnosticVerifier.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.