private void AnalyzeLockStatement(SyntaxNodeAnalysisContext context) { var lockStatement = (LockStatementSyntax)context.Node; var semanticModel = context.SemanticModel; foreach (var token in lockStatement.DescendantTokens().Where(_ => _.IsKind(SyntaxKind.IdentifierToken))) { var identifier = token.Parent; var type = identifier.GetTypeSymbol(semanticModel); if (type?.TypeKind == TypeKind.Delegate) { if (token.GetSymbol(semanticModel) is IEventSymbol) { // found by rule MiKo 3092 continue; } // only warn if it is an invocation switch (identifier.Parent.Kind()) { case SyntaxKind.ConditionalAccessExpression: case SyntaxKind.InvocationExpression: { var method = context.GetEnclosingMethod(); var issue = Issue(method.Name, token); context.ReportDiagnostic(issue); break; } } } } }
private void AnalyzeConstructor(SyntaxNodeAnalysisContext context) { var method = (ConstructorDeclarationSyntax)context.Node; var parameters = method.ParameterList.Parameters; if (parameters.Count == 0) { return; } var methodBody = method.Body ?? (SyntaxNode)method.ExpressionBody?.Expression; if (methodBody is null) { return; // unfinished code or code that has no body (such as interface methods or abstract methods) } var methodSymbol = context.GetEnclosingMethod(); if (methodSymbol is null) { return; } var results = Analyze(context, methodBody, methodSymbol); foreach (var diagnostic in results) { context.ReportDiagnostic(diagnostic); } }
private void AnalyzeSimpleMemberAccessExpression(SyntaxNodeAnalysisContext context) { var node = (MemberAccessExpressionSyntax)context.Node; if (node.Expression is IdentifierNameSyntax invokedClass) { if (AllowedAssertionMethods.Contains(node.GetName())) { return; } if (Constants.Names.AssertionTypes.Contains(invokedClass.GetName()) is false) { return; } var testFrameworkNamespace = invokedClass.GetTypeSymbol(context.SemanticModel)?.ContainingNamespace.FullyQualifiedName(); if (Constants.Names.AssertionNamespaces.Contains(testFrameworkNamespace) is false) { return; // ignore other test frameworks } var method = context.GetEnclosingMethod(); if (method is null) { // nameof() is also a SimpleMemberAccessExpression, so assignments of lists etc. may cause an NRE to be thrown return; } context.ReportDiagnostic(Issue(method.Name, node)); } }
private void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) { var finallyBlock = ((FinallyClauseSyntax)context.Node).Block; if (finallyBlock is null) { return; } foreach (var statement in finallyBlock.DescendantNodesAndSelf().OfType <ThrowStatementSyntax>()) { var location = statement.GetLocation(); var method = context.GetEnclosingMethod(); var issue = Issue(method, location); context.ReportDiagnostic(issue); } }
private void AnalyzeLockStatement(SyntaxNodeAnalysisContext context) { var lockStatement = (LockStatementSyntax)context.Node; var method = context.GetEnclosingMethod(); var events = method.ContainingType.GetMembersIncludingInherited <IEventSymbol>().Select(_ => _.Name).ToHashSet(); foreach (var token in lockStatement.DescendantTokens().Where(_ => _.IsKind(SyntaxKind.IdentifierToken))) { var eventName = token.ValueText; if (events.Contains(eventName) && token.GetSymbol(context.SemanticModel) is IEventSymbol) { var issue = Issue(method.Name, token); context.ReportDiagnostic(issue); } } }
private void AnalyzeSimpleMemberAccessExpression(SyntaxNodeAnalysisContext context) { var node = (MemberAccessExpressionSyntax)context.Node; if (NodeHasIssue(node, context.SemanticModel)) { var methodSymbol = context.GetEnclosingMethod(); if (methodSymbol is null) { // nameof() is also a SimpleMemberAccessExpression, so assignments of lists etc. may cause an NRE to be thrown return; } var issue = Issue(methodSymbol.Name, node); context.ReportDiagnostic(issue); } }
private void Analyze(SyntaxNodeAnalysisContext context, SyntaxNode methodBody, SeparatedSyntaxList <ParameterSyntax> parameters) { if (methodBody is null) { return; } if (parameters.Count == 0) { return; } var methodSymbol = context.GetEnclosingMethod(); if (CanBeIgnored(methodSymbol)) { return; } var used = GetAllUsedVariables(context, methodBody); foreach (var parameter in parameters) { var parameterName = parameter.GetName(); if (used.Contains(parameterName)) { continue; } // TODO: RKN check if the documentation contains the phrase 'Unused.' and Do not report an issue in such case if (methodSymbol.IsEnhancedByPostSharpAdvice()) { continue; } var diagnostic = Issue(parameterName, parameter.Identifier); context.ReportDiagnostic(diagnostic); } }
private void AnalyzeFinallyClause(SyntaxNodeAnalysisContext context) { var finallyBlock = ((FinallyClauseSyntax)context.Node).Block; if (finallyBlock is null) { return; } var method = context.GetEnclosingMethod(); var events = method.ContainingType.GetMembersIncludingInherited <IEventSymbol>().Select(_ => _.Name).ToHashSet(); foreach (var token in finallyBlock.DescendantTokens().Where(_ => _.IsKind(SyntaxKind.IdentifierToken))) { var eventName = token.ValueText; if (events.Contains(eventName) && token.GetSymbol(context.SemanticModel) is IEventSymbol) { var issue = Issue(method.Name, token, eventName); context.ReportDiagnostic(issue); } } }
private new void AnalyzeLocalDeclarationStatement(SyntaxNodeAnalysisContext context) { var node = (LocalDeclarationStatementSyntax)context.Node; var declaration = node.Declaration; if (declaration.Variables.Any(_ => _.IsTypeUnderTestVariable())) { // inspect associated test method var method = context.GetEnclosingMethod(); if (method.IsTestMethod()) { var testClass = method.ContainingType; var typeUnderTest = declaration.GetTypeSymbol(context.SemanticModel); var typeUnderTestName = GetTypeUnderTestName(testClass, typeUnderTest); if (TestClassStartsWithName(testClass, typeUnderTestName) is false) { var diagnostic = Issue(testClass, typeUnderTestName + Constants.TestsSuffix); context.ReportDiagnostic(diagnostic); } } } }
private bool CanBeIgnored(SyntaxNodeAnalysisContext context) => ShallAnalyze(context.GetEnclosingMethod()) is false;