protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { if (c.SemanticModel.Compilation.IsTest() || c.SemanticModel.Compilation.Options.OutputKind != OutputKind.DynamicallyLinkedLibrary) { //this rule only makes sense in libraries return; } var awaitExpression = (AwaitExpressionSyntax)c.Node; var expression = awaitExpression.Expression; if (expression == null) { return; } var type = c.SemanticModel.GetTypeInfo(expression).Type; if (type.Is(KnownType.System_Threading_Tasks_Task)) { c.ReportDiagnostic(Diagnostic.Create(Rule, expression.GetLocation())); } }, SyntaxKind.AwaitExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var equalsExpression = (BinaryExpressionSyntax) c.Node; var leftIsNull = EquivalenceChecker.AreEquivalent(equalsExpression.Left, NullExpression); var rightIsNull = EquivalenceChecker.AreEquivalent(equalsExpression.Right, NullExpression); if (!(leftIsNull ^ rightIsNull)) { return; } var expressionToTypeCheck = leftIsNull ? equalsExpression.Right : equalsExpression.Left; var typeInfo = c.SemanticModel.GetTypeInfo(expressionToTypeCheck).Type as ITypeParameterSymbol; if (typeInfo != null && !typeInfo.HasReferenceTypeConstraint && !typeInfo.ConstraintTypes.OfType<IErrorTypeSymbol>().Any() && !typeInfo.ConstraintTypes.Any(typeSymbol => typeSymbol.IsReferenceType && typeSymbol.IsClass())) { var expressionToReportOn = leftIsNull ? equalsExpression.Left : equalsExpression.Right; c.ReportDiagnostic(Diagnostic.Create(Rule, expressionToReportOn.GetLocation(), typeInfo.Name)); } }, SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var invocation = (InvocationExpressionSyntax)c.Node; var methodSymbol = c.SemanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (!IsSumOnInteger(methodSymbol) || !IsSumInsideUnchecked(invocation)) { return; } var expression = invocation.Expression; var memberAccess = expression as MemberAccessExpressionSyntax; if (memberAccess == null) { return; } c.ReportDiagnostic(Diagnostic.Create(Rule, memberAccess.Name.GetLocation())); }, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var assignment = (AssignmentExpressionSyntax)c.Node; if (!IsDelegateSubtraction(assignment, c.SemanticModel) || ExpressionIsSimple(assignment.Right)) { return; } c.ReportDiagnostic(Diagnostic.Create(Rule, assignment.GetLocation())); }, SyntaxKind.SubtractAssignmentExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => { var binary = (BinaryExpressionSyntax)c.Node; if (!IsDelegateSubtraction(binary, c.SemanticModel) || !IsTopLevelSubtraction(binary)) { return; } if (!BinaryIsValidSubstraction(binary)) { c.ReportDiagnostic(Diagnostic.Create(Rule, binary.GetLocation())); } }, SyntaxKind.SubtractExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => c.ReportDiagnostic(Diagnostic.Create(Rule, c.Node.GetLocation())), SyntaxKind.ExitForStatement, SyntaxKind.ExitFunctionStatement, SyntaxKind.ExitPropertyStatement, SyntaxKind.ExitSubStatement, SyntaxKind.ExitTryStatement, SyntaxKind.ExitWhileStatement); context.RegisterSyntaxNodeActionInNonGenerated( c => { var parent = c.Node.Parent; while(parent != null && !(parent is DoLoopBlockSyntax)) { parent = parent.Parent; } if (parent == null || parent.IsKind(SyntaxKind.SimpleDoLoopBlock)) { return; } c.ReportDiagnostic(Diagnostic.Create(Rule, c.Node.GetLocation())); }, SyntaxKind.ExitDoStatement); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var argumentList = (AttributeArgumentListSyntax)c.Node; if (!argumentList.Arguments.Any()) { c.ReportDiagnostic(Diagnostic.Create(Rule, argumentList.GetLocation())); } }, SyntaxKind.AttributeArgumentList); context.RegisterSyntaxNodeActionInNonGenerated( c => { var objectCreation = (ObjectCreationExpressionSyntax)c.Node; var argumentList = objectCreation.ArgumentList; if (argumentList != null && objectCreation.Initializer != null && !argumentList.Arguments.Any()) { c.ReportDiagnostic(Diagnostic.Create(Rule, argumentList.GetLocation())); } }, SyntaxKind.ObjectCreationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var invocation = (InvocationExpressionSyntax)c.Node; if (!IsOnBase(invocation) || invocation.ArgumentList == null) { return; } var calledMethod = c.SemanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (calledMethod == null || !calledMethod.IsVirtual || invocation.ArgumentList.Arguments.Count == calledMethod.Parameters.Length || !IsCallInsideOverride(invocation, calledMethod, c.SemanticModel)) { return; } var pluralize = calledMethod.Parameters.Length - invocation.ArgumentList.Arguments.Count > 1 ? "s" : string.Empty; c.ReportDiagnostic(Diagnostic.Create(Rule, invocation.GetLocation(), pluralize)); }, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var expressionStatement = (ExpressionStatementSyntax)c.Node; CheckExpressionForPureMethod(c, expressionStatement.Expression); }, SyntaxKind.ExpressionStatement); context.RegisterSyntaxNodeActionInNonGenerated( c => { var lambda = (LambdaExpressionSyntax)c.Node; var symbol = c.SemanticModel.GetSymbolInfo(lambda).Symbol as IMethodSymbol; if (symbol == null || !symbol.ReturnsVoid) { return; } var expression = lambda.Body as ExpressionSyntax; CheckExpressionForPureMethod(c, expression); }, SyntaxKind.ParenthesizedLambdaExpression, SyntaxKind.SimpleLambdaExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var division = (BinaryExpressionSyntax) c.Node; var symbol = c.SemanticModel.GetSymbolInfo(division).Symbol as IMethodSymbol; if (symbol == null || symbol.ContainingType == null || !symbol.ContainingType.IsAny(KnownType.IntegralNumbers)) { return; } ITypeSymbol assignedToType; if (TryGetTypeFromAssignmentToFloatType(division, c.SemanticModel, out assignedToType) || TryGetTypeFromArgumentMappedToFloatType(division, c.SemanticModel, out assignedToType) || TryGetTypeFromReturnMappedToFloatType(division, c.SemanticModel, out assignedToType)) { c.ReportDiagnostic(Diagnostic.Create( Rule, division.GetLocation(), assignedToType.ToMinimalDisplayString(c.SemanticModel, division.SpanStart))); } }, SyntaxKind.DivideExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var ifStatement = (IfStatementSyntax)c.Node; if (ifStatement.Else != null || ifStatement.Parent is ElseClauseSyntax) { return; } AssignmentExpressionSyntax assignment; BinaryExpressionSyntax condition; if (!TryGetNotEqualsCondition(ifStatement, out condition) || !TryGetSingleAssignment(ifStatement, out assignment)) { return; } var expression1Condition = condition.Left?.RemoveParentheses(); var expression2Condition = condition.Right?.RemoveParentheses(); var expression1Assignment = assignment.Left?.RemoveParentheses(); var expression2Assignment = assignment.Right?.RemoveParentheses(); if (AreMatchingExpressions(expression1Condition, expression2Condition, expression2Assignment, expression1Assignment) || AreMatchingExpressions(expression1Condition, expression2Condition, expression1Assignment, expression2Assignment)) { c.ReportDiagnostic(Diagnostic.Create(Rule, condition.GetLocation())); } }, SyntaxKind.IfStatement); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var catchClause = (CatchClauseSyntax)c.Node; if (catchClause.Declaration == null || catchClause.Declaration.Identifier.IsKind(SyntaxKind.None)) { return; } var exceptionIdentifier = c.SemanticModel.GetDeclaredSymbol(catchClause.Declaration); if (exceptionIdentifier == null) { return; } var throws = catchClause.DescendantNodes(n => n == catchClause || !n.IsKind(SyntaxKind.CatchClause)) .OfType<ThrowStatementSyntax>() .Where(t => t.Expression != null); foreach (var @throw in throws) { var thrown = c.SemanticModel.GetSymbolInfo(@throw.Expression).Symbol as ILocalSymbol; if (object.Equals(thrown, exceptionIdentifier)) { c.ReportDiagnostic(Diagnostic.Create(Rule, @throw.GetLocation())); } } }, SyntaxKind.CatchClause); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var invocation = (InvocationExpressionSyntax)c.Node; var methodSymbol = c.SemanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (methodSymbol == null || methodSymbol.Name != "ToCharArray" || !methodSymbol.IsInType(KnownType.System_String) || methodSymbol.Parameters.Length != 0) { return; } if (!(invocation.Parent is ElementAccessExpressionSyntax) && !(invocation.Parent is ForEachStatementSyntax)) { return; } var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null) { return; } c.ReportDiagnostic(Diagnostic.Create(Rule, memberAccess.Name.GetLocation())); }, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var method = (MethodDeclarationSyntax)c.Node; var methodSymbol = c.SemanticModel.GetDeclaredSymbol(method); if (methodSymbol == null || !methodSymbol.IsOverride || methodSymbol.OverriddenMethod == null) { return; } var lastParameter = method.ParameterList.Parameters.LastOrDefault(); if (lastParameter == null) { return; } var paramsKeyword = lastParameter.Modifiers.FirstOrDefault( modifier => modifier.IsKind(SyntaxKind.ParamsKeyword)); if (paramsKeyword != default(SyntaxToken) && IsNotSemanticallyParams(lastParameter, c.SemanticModel)) { c.ReportDiagnostic(Diagnostic.Create(Rule, paramsKeyword.GetLocation())); } }, SyntaxKind.MethodDeclaration); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var invocation = (InvocationExpressionSyntax)c.Node; var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null || !IsDisposableField(memberAccess.Expression, c.SemanticModel) || !IsDisposeMethodCalled(invocation, c.SemanticModel)) { return; } var enclosingSymbol = c.SemanticModel.GetEnclosingSymbol(invocation.SpanStart); if (enclosingSymbol == null) { return; } var enclosingMethodSymbol = enclosingSymbol as IMethodSymbol; if (enclosingMethodSymbol == null || !IsMethodMatchingDisposeMethodName(enclosingMethodSymbol)) { c.ReportDiagnostic(Diagnostic.Create(Rule, memberAccess.Name.GetLocation())); } }, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var unaryExpression = (PrefixUnaryExpressionSyntax) c.Node; var op = unaryExpression.OperatorToken; var prevToken = op.GetPreviousToken(); var opLocation = op.GetLocation(); var opStartPosition = opLocation.GetLineSpan().StartLinePosition; var prevStartPosition = prevToken.GetLocation().GetLineSpan().StartLinePosition; if (prevToken.IsKind(SyntaxKind.EqualsToken) && prevStartPosition.Line == opStartPosition.Line && prevStartPosition.Character == opStartPosition.Character - 1) { c.ReportDiagnostic(Diagnostic.Create(Rule, opLocation, $"{op.Text}=")); } }, SyntaxKind.UnaryMinusExpression, SyntaxKind.UnaryPlusExpression, SyntaxKind.LogicalNotExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCodeBlockStartActionInNonGenerated<SyntaxKind>(cbc => { var unusedLocals = new List<ISymbol>(); cbc.RegisterSyntaxNodeAction(c => { unusedLocals.AddRange( ((LocalDeclarationStatementSyntax) c.Node).Declaration.Variables .Select(variable => c.SemanticModel.GetDeclaredSymbol(variable)) .Where(symbol => symbol != null)); }, SyntaxKind.LocalDeclarationStatement); cbc.RegisterSyntaxNodeAction(c => { var symbolsToNotReportOn = GetUsedSymbols(c.Node, c.SemanticModel); foreach (var symbol in symbolsToNotReportOn) { unusedLocals.Remove(symbol); } }, SyntaxKind.IdentifierName); cbc.RegisterCodeBlockEndAction(c => { foreach (var unused in unusedLocals) { c.ReportDiagnostic(Diagnostic.Create(Rule, unused.Locations.First(), unused.Name)); } }); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var outerInvocation = (InvocationExpressionSyntax)c.Node; if (!IsMethodOrderByExtension(outerInvocation, c.SemanticModel)) { return; } var memberAccess = outerInvocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null) { return; } var innerInvocation = memberAccess.Expression as InvocationExpressionSyntax; if (!IsMethodOrderByExtension(innerInvocation, c.SemanticModel) && !IsMethodThenByExtension(innerInvocation, c.SemanticModel)) { return; } c.ReportDiagnostic(Diagnostic.Create(Rule, memberAccess.Name.GetLocation())); }, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCodeBlockStartActionInNonGenerated<SyntaxKind>( cb => { var methodDeclaration = cb.CodeBlock as MethodDeclarationSyntax; if (methodDeclaration == null) { return; } var methodSymbol = cb.OwningSymbol as IMethodSymbol; if (methodSymbol == null || !GetHashCodeEqualsOverride.MethodIsRelevant(methodSymbol, MethodNames)) { return; } cb.RegisterSyntaxNodeAction( c => { CheckInvocationInsideMethod(c, methodSymbol); }, SyntaxKind.InvocationExpression); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var methodDeclaration = (MethodDeclarationSyntax)c.Node; var methodSymbol = c.SemanticModel.GetDeclaredSymbol(methodDeclaration); if (methodSymbol == null || methodSymbol.ReturnsVoid) { return; } AttributeData attribute; if (!TryGetOperationContract(methodSymbol, out attribute)) { return; } var asyncPattern = attribute.NamedArguments.FirstOrDefault(na => na.Key == "AsyncPattern").Value.Value as bool?; if (asyncPattern.HasValue && asyncPattern.Value) { return; } var isOneWay = attribute.NamedArguments.FirstOrDefault(na => na.Key == "IsOneWay").Value.Value as bool?; if (isOneWay.HasValue && isOneWay.Value) { c.ReportDiagnostic(Diagnostic.Create(Rule, methodDeclaration.ReturnType.GetLocation())); } }, SyntaxKind.MethodDeclaration); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var interfaceDeclaration = (InterfaceDeclarationSyntax)c.Node; if (interfaceDeclaration.BaseList == null || interfaceDeclaration.BaseList.Types.Count < 2) { return; } var interfaceSymbol = c.SemanticModel.GetDeclaredSymbol(interfaceDeclaration); if (interfaceSymbol == null) { return; } var collidingMembers = GetCollidingMembers(interfaceSymbol) .Take(MaxMemberDisplayCount + 1) .ToList(); if (collidingMembers.Any()) { var membersText = GetIssueMessageText(collidingMembers, c.SemanticModel, interfaceDeclaration.SpanStart); var pluralize = collidingMembers.Count > 1 ? "s" : string.Empty; c.ReportDiagnostic(Diagnostic.Create(Rule, interfaceDeclaration.Identifier.GetLocation(), membersText, pluralize)); } }, SyntaxKind.InterfaceDeclaration); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var declaration = (LocalDeclarationStatementSyntax) c.Node; var variables = declaration.Declaration.Variables; List<ISymbol> members = null; foreach (var variable in variables) { var variableSymbol = c.SemanticModel.GetDeclaredSymbol(variable); if (variableSymbol == null) { return; } if (members == null) { members = GetMembers(variableSymbol.ContainingType); } ReportOnVariableMatchingField(members, variable.Identifier, c); } }, SyntaxKind.LocalDeclarationStatement); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var expression = (BinaryExpressionSyntax) c.Node; var enclosingSymbol = c.SemanticModel.GetEnclosingSymbol(expression.SpanStart) as IMethodSymbol; if (enclosingSymbol != null && enclosingSymbol.MethodKind == MethodKind.UserDefinedOperator) { return; } var parenthesizedParent = expression.Parent; while (parenthesizedParent is ParenthesizedExpressionSyntax) { parenthesizedParent = parenthesizedParent.Parent; } var logicalNot = parenthesizedParent as PrefixUnaryExpressionSyntax; if (logicalNot != null && logicalNot.OperatorToken.IsKind(SyntaxKind.ExclamationToken)) { c.ReportDiagnostic(Diagnostic.Create(Rule, logicalNot.GetLocation(), OppositeTokens[expression.OperatorToken.Kind()])); } }, SyntaxKind.GreaterThanExpression, SyntaxKind.GreaterThanOrEqualExpression, SyntaxKind.LessThanExpression, SyntaxKind.LessThanOrEqualExpression, SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var invocation = (InvocationExpressionSyntax)c.Node; var memberAccess = invocation.Expression as MemberAccessExpressionSyntax; if (memberAccess == null || !invocation.HasExactlyNArguments(1)) { return; } var methodSymbol = c.SemanticModel.GetSymbolInfo(invocation).Symbol as IMethodSymbol; if (!methodSymbol.IsInType(KnownType.System_Type)) { return; } var argument = invocation.ArgumentList.Arguments.First().Expression; CheckForIsAssignableFrom(c, invocation, memberAccess, methodSymbol, argument); CheckForIsInstanceOfType(c, invocation, memberAccess, methodSymbol); }, SyntaxKind.InvocationExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => { var binary = (BinaryExpressionSyntax)c.Node; CheckGetTypeAndTypeOfEquality(binary.Left, binary.Right, binary.GetLocation(), c); CheckGetTypeAndTypeOfEquality(binary.Right, binary.Left, binary.GetLocation(), c); }, SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var lessThan = (BinaryExpressionSyntax) c.Node; int constValue; if (ExpressionNumericConverter.TryGetConstantIntValue(lessThan.Left, out constValue) && constValue == 0 && IsIndexOfCall(lessThan.Right, c.SemanticModel)) { c.ReportDiagnostic(Diagnostic.Create(Rule, Location.Create(lessThan.SyntaxTree, TextSpan.FromBounds(lessThan.Left.SpanStart, lessThan.OperatorToken.Span.End)))); } }, SyntaxKind.LessThanExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => { var greaterThan = (BinaryExpressionSyntax)c.Node; int constValue; if (ExpressionNumericConverter.TryGetConstantIntValue(greaterThan.Right, out constValue) && constValue == 0 && IsIndexOfCall(greaterThan.Left, c.SemanticModel)) { c.ReportDiagnostic(Diagnostic.Create(Rule, Location.Create(greaterThan.SyntaxTree, TextSpan.FromBounds(greaterThan.OperatorToken.SpanStart, greaterThan.Right.Span.End)))); } }, SyntaxKind.GreaterThanExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => CheckEquals(c), SyntaxKind.EqualsExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => CheckLogicalAnd(c), SyntaxKind.LogicalAndExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => CheckNotEquals(c), SyntaxKind.NotEqualsExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => CheckLogicalOr(c), SyntaxKind.LogicalOrExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => CheckLogicalNot(c), SyntaxKind.LogicalNotExpression); context.RegisterSyntaxNodeActionInNonGenerated( c => CheckConditional(c), SyntaxKind.ConditionalExpression); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var parameter = (ParameterSyntax)c.Node; if (!parameter.AttributeLists.Any()) { return; } var attributes = AttributeSyntaxSymbolMapping.GetAttributesForParameter(parameter, c.SemanticModel) .ToList(); var defaultParameterValueAttribute = attributes .FirstOrDefault(a => a.Symbol.IsInType(KnownType.System_Runtime_InteropServices_DefaultParameterValueAttribute)); if (defaultParameterValueAttribute == null) { return; } var optionalAttribute = attributes .FirstOrDefault(a => a.Symbol.IsInType(KnownType.System_Runtime_InteropServices_OptionalAttribute)); if (optionalAttribute == null) { c.ReportDiagnostic(Diagnostic.Create(Rule, defaultParameterValueAttribute.SyntaxNode.GetLocation())); } }, SyntaxKind.Parameter); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var ifNode = (IfStatementSyntax)c.Node; var isTrue = ifNode.Condition.IsKind(SyntaxKind.TrueLiteralExpression); var isFalse = ifNode.Condition.IsKind(SyntaxKind.FalseLiteralExpression); if (!isTrue && !isFalse) { return; } if (isTrue) { ReportIfTrue(ifNode, c); } else { ReportIfFalse(ifNode, c); } }, SyntaxKind.IfStatement); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction( c => { var symbol = c.Symbol as INamedTypeSymbol; if (!symbol.IsClass() || !symbol.IsAbstract || ClassHasInheritedAbstractMembers(symbol)) { return; } if (AbstractClassShouldBeInterface(symbol)) { ReportClass(symbol, MessageToInterface, c); return; } if (AbstractClassShouldBeConcreteClass(symbol)) { ReportClass(symbol, MessageToConcreteClass, c); return; } }, SymbolKind.NamedType); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var method = (MethodDeclarationSyntax)c.Node; var methodSymbol = c.SemanticModel.GetDeclaredSymbol(method); IMethodSymbol overriddenMember; if (methodSymbol == null || !methodSymbol.TryGetOverriddenOrInterfaceMember(out overriddenMember)) { return; } for (int i = 0; i < methodSymbol.Parameters.Length; i++) { var overridingParameter = methodSymbol.Parameters[i]; var overriddenParameter = overriddenMember.Parameters[i]; var parameterSyntax = method.ParameterList.Parameters[i]; ReportParameterIfNeeded(overridingParameter, overriddenParameter, parameterSyntax, isExplicitImplementation: methodSymbol.ExplicitInterfaceImplementations.Any(), context: c); } }, SyntaxKind.MethodDeclaration); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => { var methodCall = (InvocationExpressionSyntax) c.Node; var methodParameterLookup = new MethodParameterLookup(methodCall, c.SemanticModel); var argumentMappings = methodParameterLookup.GetAllArgumentParameterMappings() .ToList(); var methodSymbol = methodParameterLookup.MethodSymbol; if (methodSymbol == null) { return; } foreach (var argumentMapping in argumentMappings.Where(argumentMapping => ArgumentHasDefaultValue(argumentMapping, c.SemanticModel))) { var argument = argumentMapping.Argument; var parameter = argumentMapping.Parameter; c.ReportDiagnostic(Diagnostic.Create(Rule, argument.GetLocation(), parameter.Name)); } }, SyntaxKind.InvocationExpression); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterExplodedGraphBasedAnalysis((e, c) => CheckForRedundantConditions(e, c)); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( analysisContext => { var fieldsByNamedType = MultiValueDictionary <INamedTypeSymbol, IFieldSymbol> .Create <HashSet <IFieldSymbol> >(); var fieldsAssigned = new HashSet <IFieldSymbol>(); analysisContext.RegisterSymbolAction( c => { var namedTypeSymbol = (INamedTypeSymbol)c.Symbol; if (!namedTypeSymbol.IsClass() || namedTypeSymbol.Implements(KnownType.System_IDisposable)) { return; } var disposableFields = namedTypeSymbol.GetMembers() .OfType <IFieldSymbol>() .Where(IsNonStaticNonPublicDisposableField) .ToHashSet(); fieldsByNamedType.AddRangeWithKey(namedTypeSymbol, disposableFields); }, SymbolKind.NamedType); analysisContext.RegisterSyntaxNodeAction( c => { var assignment = (AssignmentExpressionSyntax)c.Node; var expression = assignment.Right; var fieldSymbol = c.SemanticModel.GetSymbolInfo(assignment.Left).Symbol as IFieldSymbol; AddFieldIfNeeded(fieldSymbol, expression, fieldsAssigned); }, SyntaxKind.SimpleAssignmentExpression); analysisContext.RegisterSyntaxNodeAction( c => { var field = (FieldDeclarationSyntax)c.Node; foreach (var variableDeclaratorSyntax in field.Declaration.Variables .Where(declaratorSyntax => declaratorSyntax.Initializer != null)) { var fieldSymbol = c.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax) as IFieldSymbol; AddFieldIfNeeded(fieldSymbol, variableDeclaratorSyntax.Initializer.Value, fieldsAssigned); } }, SyntaxKind.FieldDeclaration); analysisContext.RegisterCompilationEndAction( c => { foreach (var kv in fieldsByNamedType) { foreach (var classSyntax in kv.Key.DeclaringSyntaxReferences .Select(declaringSyntaxReference => declaringSyntaxReference.GetSyntax()) .OfType <ClassDeclarationSyntax>()) { var assignedFields = kv.Value.Intersect(fieldsAssigned).ToList(); if (!assignedFields.Any()) { continue; } var variableNames = string.Join(", ", assignedFields.Select(symbol => $"'{symbol.Name}'").OrderBy(s => s)); c.ReportDiagnosticIfNonGenerated( Diagnostic.Create(rule, classSyntax.Identifier.GetLocation(), variableNames), c.Compilation); } } }); }); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(CheckForIssue, SyntaxKind.ClassDeclaration, SyntaxKind.StructDeclaration); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(TreatNode, SyntaxKind.MultiLineIfBlock);
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => ReportReservedExceptionCreation(c, ((ThrowStatementSyntax)c.Node).Expression), SyntaxKind.ThrowStatement); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(CheckEnum, SyntaxKind.EnumDeclaration); context.RegisterSyntaxNodeActionInNonGenerated(CheckInterface, SyntaxKind.InterfaceDeclaration); context.RegisterSyntaxNodeActionInNonGenerated(CheckClass, SyntaxKind.ClassDeclaration); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterExplodedGraphBasedAnalysis(CheckForEmptyCollectionAccess); }
protected override void Initialize(SonarAnalysisContext context) { CheckToStringInvocationsOnStringAndInStringFormat(context); CheckSidesOfAddExpressionsForToStringCall(context); CheckRightSideOfAddAssignmentsForToStringCall(context); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated( AnalysisAction, SyntaxKind.ExpressionStatement);
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated( c => c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, c.Node.GetLocation())), SyntaxKind.EndStatement); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( c => { var shouldRaise = true; possibleUnusedInternalMembers = new ConcurrentBag <Diagnostic>(); c.RegisterSemanticModelAction( cc => { var isInternalsVisibleToAttributeFound = cc.SemanticModel.SyntaxTree.GetRoot() .DescendantNodes() .OfType <AttributeListSyntax>() .SelectMany(list => list.Attributes) .Any(a => IsInternalVisibleToAttribute(a, cc.SemanticModel)); if (isInternalsVisibleToAttributeFound) { shouldRaise = false; } }); c.RegisterSymbolAction( cc => { var namedType = (INamedTypeSymbol)cc.Symbol; if (!namedType.IsClassOrStruct() || namedType.ContainingType != null) { return; } var declarationCollector = new RemovableDeclarationCollector(namedType, cc.Compilation); var declaredPrivateSymbols = new HashSet <ISymbol>(); var fieldLikeSymbols = new BidirectionalDictionary <ISymbol, SyntaxNode>(); CollectRemovableNamedTypes(declarationCollector, declaredPrivateSymbols); CollectRemovableFieldLikeDeclarations(declarationCollector, declaredPrivateSymbols, fieldLikeSymbols); CollectRemovableEventsAndProperties(declarationCollector, declaredPrivateSymbols); CollectRemovableMethods(declarationCollector, declaredPrivateSymbols); if (!declaredPrivateSymbols.Any()) { return; } var usedSymbols = new HashSet <ISymbol>(); var emptyConstructors = new HashSet <ISymbol>(); var propertyAccessorAccess = new Dictionary <IPropertySymbol, AccessorAccess>(); CollectUsedSymbols(declarationCollector, usedSymbols, declaredPrivateSymbols, propertyAccessorAccess); CollectUsedSymbolsFromCtorInitializerAndCollectEmptyCtors(declarationCollector, usedSymbols, emptyConstructors); ReportIssues(cc, usedSymbols, declaredPrivateSymbols, emptyConstructors, fieldLikeSymbols); ReportUnusedPropertyAccessors(cc, usedSymbols, declaredPrivateSymbols, propertyAccessorAccess); }, SymbolKind.NamedType); c.RegisterCompilationEndAction( cc => { if (!shouldRaise) { return; } foreach (var diagnostic in possibleUnusedInternalMembers) { cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation); } }); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction( c => { var namedType = (INamedTypeSymbol)c.Symbol; if (!namedType.IsClassOrStruct() || HasStructLayoutAttribute(namedType) || namedType.ContainingType != null) { return; } var removableDeclarationCollector = new CSharpRemovableDeclarationCollector(namedType, c.Compilation); var candidateFields = removableDeclarationCollector.GetRemovableFieldLikeDeclarations( new HashSet <SyntaxKind> { SyntaxKind.FieldDeclaration }, maxAccessibility) .Where(tuple => !IsInitializedOrFixed((VariableDeclaratorSyntax)tuple.SyntaxNode) && !HasStructLayoutAttribute(tuple.Symbol.ContainingType)); var candidateProperties = removableDeclarationCollector.GetRemovableDeclarations( new HashSet <SyntaxKind> { SyntaxKind.PropertyDeclaration }, maxAccessibility) .Where(tuple => IsAutoPropertyWithNoInitializer((PropertyDeclarationSyntax)tuple.SyntaxNode) && !HasStructLayoutAttribute(tuple.Symbol.ContainingType)); var allCandidateMembers = candidateFields.Concat(candidateProperties).ToList(); if (!allCandidateMembers.Any()) { return; } var usedMembers = GetMemberUsages(removableDeclarationCollector, new HashSet <ISymbol>(allCandidateMembers.Select(t => t.Symbol))); var usedMemberSymbols = new HashSet <ISymbol>(usedMembers.Select(tuple => tuple.Symbol)); var assignedMemberSymbols = GetAssignedMemberSymbols(usedMembers); foreach (var candidateMember in allCandidateMembers) { if (!usedMemberSymbols.Contains(candidateMember.Symbol)) { /// reported by <see cref="UnusedPrivateMember"/> continue; } if (!assignedMemberSymbols.Contains(candidateMember.Symbol)) { var field = candidateMember.SyntaxNode as VariableDeclaratorSyntax; var property = candidateMember.SyntaxNode as PropertyDeclarationSyntax; var memberType = field != null ? "field" : "auto-property"; var location = field != null ? field.Identifier.GetLocation() : property.Identifier.GetLocation(); c.ReportDiagnosticIfNonGenerated(Diagnostic.Create(rule, location, memberType, candidateMember.Symbol.Name)); } } }, SymbolKind.NamedType); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(RaiseOnInvalidCatch, SyntaxKind.TryStatement); }
protected override void Initialize(SonarAnalysisContext context) { }
protected override void Initialize(SonarAnalysisContext context) { // Special case - Assembly.Load InvocationTracker.Track(context, InvocationTracker.MatchMethod( new MemberDescriptor(KnownType.System_Reflection_Assembly, "Load"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "LoadFile"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "LoadFrom"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "LoadWithPartialName")), InvocationTracker.MethodIsStatic()); // Special case - Type.GetType() without paramters is ok, but // and Type.GetType(...) with parameters is not ok InvocationTracker.Track(context, InvocationTracker.MatchMethod( new MemberDescriptor(KnownType.System_Type, "GetType")), InvocationTracker.MethodIsStatic(), InvocationTracker.MethodHasParameters(), Conditions.ExceptWhen( Conditions.And( InvocationTracker.ArgumentAtIndexIs(0, KnownType.System_String), InvocationTracker.ArgumentAtIndexIsConstant(0)))); // Special case - Activator.CreateXXX InvocationTracker.Track(context, InvocationTracker.MatchMethod( new MemberDescriptor(KnownType.System_Activator, "CreateComInstanceFrom"), new MemberDescriptor(KnownType.System_Activator, "CreateInstance"), new MemberDescriptor(KnownType.System_Activator, "CreateInstanceFrom")), InvocationTracker.MethodIsStatic(), InvocationTracker.MethodHasParameters(), Conditions.ExceptWhen( InvocationTracker.ArgumentAtIndexIs(0, KnownType.System_Type))); // All other method invocations InvocationTracker.Track(context, Conditions.ExceptWhen( InvocationTracker.IsTypeOfExpression()), InvocationTracker.MatchMethod( // Methods on assembly that are safe to call with constants new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetType"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetTypes"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetModule"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetLoadedModules"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetModules"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "CreateInstance"), new MemberDescriptor(KnownType.System_Reflection_Assembly, "GetExportedTypes"), new MemberDescriptor(KnownType.System_Type, "GetInterface"), new MemberDescriptor(KnownType.System_Type, "GetNestedType"), new MemberDescriptor(KnownType.System_Type, "GetNestedTypes"), new MemberDescriptor(KnownType.System_Type, "GetInterfaces"), new MemberDescriptor(KnownType.System_Type, "GetMethod"), new MemberDescriptor(KnownType.System_Type, "GetField"), new MemberDescriptor(KnownType.System_Type, "GetProperty"), new MemberDescriptor(KnownType.System_Type, "GetMember"), new MemberDescriptor(KnownType.System_Type, "GetMethods"), new MemberDescriptor(KnownType.System_Type, "GetFields"), new MemberDescriptor(KnownType.System_Type, "GetProperties"), new MemberDescriptor(KnownType.System_Type, "GetMembers"), new MemberDescriptor(KnownType.System_Type, "GetDefaultMembers"), new MemberDescriptor(KnownType.System_Type, "InvokeMember")), Conditions.ExceptWhen( Conditions.And( InvocationTracker.ArgumentAtIndexIs(0, KnownType.System_String), InvocationTracker.ArgumentAtIndexIsConstant(0)))); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(CheckForFormatStringIssues, SyntaxKind.InvocationExpression); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterCodeBlockStartActionInNonGenerated <SyntaxKind>(
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(c => { if (c.IsTest()) { return; } var baseMethodDeclaration = (BaseMethodDeclarationSyntax)c.Node; var methodSymbol = c.SemanticModel.GetDeclaredSymbol(baseMethodDeclaration); if (methodSymbol == null || !methodSymbol.IsPubliclyAccessible() || methodSymbol.IsOverride || !IsOrdinaryMethodOrConstructor(methodSymbol)) { return; } var methodType = methodSymbol.IsConstructor() ? "constructor" : "method"; if (baseMethodDeclaration is MethodDeclarationSyntax methodDeclaration) { ReportIfListT(methodDeclaration.ReturnType, c, methodType); } baseMethodDeclaration .ParameterList? .Parameters .ToList() .ForEach(p => ReportIfListT(p.Type, c, methodType)); }, SyntaxKind.MethodDeclaration, SyntaxKind.ConstructorDeclaration); context.RegisterSyntaxNodeActionInNonGenerated(c => { if (c.IsTest()) { return; } var propertyDeclaration = (PropertyDeclarationSyntax)c.Node; var propertySymbol = c.SemanticModel.GetDeclaredSymbol(propertyDeclaration); if (propertySymbol != null && propertySymbol.IsPubliclyAccessible() && !propertySymbol.IsOverride) { ReportIfListT(propertyDeclaration.Type, c, "property"); } }, SyntaxKind.PropertyDeclaration); context.RegisterSyntaxNodeActionInNonGenerated(c => { if (c.IsTest()) { return; } var fieldDeclaration = (FieldDeclarationSyntax)c.Node; var variableDeclaration = fieldDeclaration.Declaration?.Variables.FirstOrDefault(); if (variableDeclaration == null) { return; } var fieldSymbol = c.SemanticModel.GetDeclaredSymbol(variableDeclaration); if (fieldSymbol != null && fieldSymbol.IsPubliclyAccessible() && !fieldSymbol.IsOverride) { ReportIfListT(fieldDeclaration.Declaration.Type, c, "field"); } }, SyntaxKind.FieldDeclaration); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(GeneratedCodeRecognizer, AnalyzeSyntax, SyntaxKind);
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction( c => { var methodSymbol = c.Symbol as IMethodSymbol; if (methodSymbol == null || methodSymbol.IsInterfaceImplementationOrMemberOverride() || !methodSymbol.Parameters.Any(p => p.IsOptional)) { return; } var methods = methodSymbol.ContainingType.GetMembers(methodSymbol.Name) .OfType <IMethodSymbol>(); var hidingInfos = new List <ParameterHidingMethodInfo>(); var matchingNamedMethods = methods .Where(m => m.Parameters.Length < methodSymbol.Parameters.Length) .Where(m => !m.Parameters.Any(p => p.IsParams)); foreach (var candidateHidingMethod in matchingNamedMethods .Where(candidateHidingMethod => IsMethodHidingOriginal(candidateHidingMethod, methodSymbol)) .Where(candidateHidingMethod => methodSymbol.Parameters[candidateHidingMethod.Parameters.Length].IsOptional)) { hidingInfos.Add( new ParameterHidingMethodInfo { ParameterToReportOn = methodSymbol.Parameters[candidateHidingMethod.Parameters.Length], HiddenMethod = methodSymbol, HidingMethod = candidateHidingMethod }); } foreach (var hidingInfo in hidingInfos) { var syntax = hidingInfo.ParameterToReportOn.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); if (syntax == null) { continue; } var hidingMethod = hidingInfo.HidingMethod; if (hidingMethod.PartialImplementationPart != null) { hidingMethod = hidingMethod.PartialImplementationPart; } var hidingMethodSyntax = hidingMethod.DeclaringSyntaxReferences.FirstOrDefault()?.GetSyntax(); if (hidingMethodSyntax == null) { continue; } var defaultCanBeUsed = IsMoreParameterAvailableInConflicting(hidingInfo) || !MethodsUsingSameParameterNames(hidingInfo); var isOtherFile = syntax.SyntaxTree.FilePath != hidingMethodSyntax.SyntaxTree.FilePath; c.ReportDiagnosticIfNonGenerated(Diagnostic.Create(Rule, syntax.GetLocation(), hidingMethodSyntax.GetLocation().GetLineSpan().StartLinePosition.Line + 1, isOtherFile ? $" in file \"{new FileInfo(hidingMethodSyntax.SyntaxTree.FilePath).Name}\"" : string.Empty, defaultCanBeUsed ? "can only be used with named arguments" : "can't be used")); } }, SymbolKind.Method); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(TreatNode, SyntaxKind.IfStatement);
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( c => { // Collect potentially removable internal types from the project to evaluate when // the compilation is over, depending on whether InternalsVisibleTo attribute is present // or not. var removableInternalTypes = new ConcurrentBag <ISymbol>(); c.RegisterSymbolAction( cc => { var namedType = (INamedTypeSymbol)cc.Symbol; if (namedType.TypeKind != TypeKind.Struct && namedType.TypeKind != TypeKind.Class && namedType.TypeKind != TypeKind.Delegate && namedType.TypeKind != TypeKind.Enum && namedType.TypeKind != TypeKind.Interface) { return; } if (namedType.ContainingType != null || namedType.DerivesFromAny(IgnoredTypes)) { return; } // Collect symbols of private members that could potentially be removed var removableSymbolsCollector = new CSharpRemovableSymbolWalker(c.Compilation.GetSemanticModel); if (!VisitDeclaringReferences(namedType, removableSymbolsCollector, c.Compilation, includeGeneratedFile: false)) { return; } // Keep the removable internal types for when the compilation ends foreach (var internalSymbol in removableSymbolsCollector.InternalSymbols.OfType <INamedTypeSymbol>()) { removableInternalTypes.Add(internalSymbol); } var usageCollector = new CSharpSymbolUsageCollector( c.Compilation.GetSemanticModel, removableSymbolsCollector.PrivateSymbols.Select(s => s.Name).ToHashSet()); if (!VisitDeclaringReferences(namedType, usageCollector, c.Compilation, includeGeneratedFile: true)) { return; } var diagnostics = GetDiagnosticsForUnusedPrivateMembers(usageCollector, removableSymbolsCollector.PrivateSymbols, "private", removableSymbolsCollector.FieldLikeSymbols) .Concat(GetDiagnosticsForUsedButUnreadFields(usageCollector, removableSymbolsCollector.PrivateSymbols)); foreach (var diagnostic in diagnostics) { cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation); } }, SymbolKind.NamedType); c.RegisterCompilationEndAction( cc => { var foundInternalsVisibleTo = cc.Compilation.Assembly .GetAttributes(KnownType.System_Runtime_CompilerServices_InternalsVisibleToAttribute) .Any(); if (foundInternalsVisibleTo || removableInternalTypes.Count == 0) { return; } var usageCollector = new CSharpSymbolUsageCollector( c.Compilation.GetSemanticModel, removableInternalTypes.Select(s => s.Name).ToHashSet()); foreach (var syntaxTree in c.Compilation.SyntaxTrees .Where(tree => !tree.IsGenerated(CSharpGeneratedCodeRecognizer.Instance, c.Compilation))) { usageCollector.SafeVisit(syntaxTree.GetRoot()); } var diagnostics = GetDiagnosticsForUnusedPrivateMembers(usageCollector, removableInternalTypes.ToHashSet(), "internal", new BidirectionalDictionary <ISymbol, SyntaxNode>()); foreach (var diagnostic in diagnostics) { cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation); } }); }); }
protected sealed override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(Language.GeneratedCodeRecognizer, c => { if (c.Node.HasFlagsAttribute(c.SemanticModel) && !AreAllRequiredMembersInitialized(c.Node) && Language.Syntax.NodeIdentifier(c.Node) is { } identifier) {
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(Action, SyntaxKind.MethodDeclaration);
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction(CheckClassWithOnlyUnusedPrivateConstructors, SymbolKind.NamedType); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction(RaiseOnUninvokedEventDeclaration, SymbolKind.NamedType); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterSyntaxNodeActionInNonGenerated(AnalyzeInvocation, SyntaxKind.InvocationExpression);
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterExplodedGraphBasedAnalysis((e, c) => CheckForNullDereference(e, c)); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCodeBlockStartActionInNonGenerated <SyntaxKind>( cbc => { if (!IsValidCodeBlockContext(cbc.CodeBlock, cbc.OwningSymbol)) { return; } var locationsForFields = new Dictionary <IFieldSymbol, List <Location> >(); cbc.RegisterSyntaxNodeAction( c => { var assignment = (AssignmentExpressionSyntax)c.Node; var expression = assignment.Left; var fieldSymbol = c.SemanticModel.GetSymbolInfo(expression).Symbol as IFieldSymbol; if (fieldSymbol?.IsStatic == true) { AddFieldLocation(fieldSymbol, expression.CreateLocation(assignment.OperatorToken), locationsForFields); } }, SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression, SyntaxKind.SubtractAssignmentExpression, SyntaxKind.MultiplyAssignmentExpression, SyntaxKind.DivideAssignmentExpression, SyntaxKind.ModuloAssignmentExpression, SyntaxKind.AndAssignmentExpression, SyntaxKind.ExclusiveOrAssignmentExpression, SyntaxKind.OrAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression, SyntaxKind.RightShiftAssignmentExpression, SyntaxKindEx.CoalesceAssignmentExpression); cbc.RegisterSyntaxNodeAction( c => { var unary = (PrefixUnaryExpressionSyntax)c.Node; CollectLocationOfStaticField(unary.Operand, locationsForFields, c); }, SyntaxKind.PreDecrementExpression, SyntaxKind.PreIncrementExpression); cbc.RegisterSyntaxNodeAction( c => { var unary = (PostfixUnaryExpressionSyntax)c.Node; CollectLocationOfStaticField(unary.Operand, locationsForFields, c); }, SyntaxKind.PostDecrementExpression, SyntaxKind.PostIncrementExpression); cbc.RegisterCodeBlockEndAction(c => { foreach (var fieldWithLocations in locationsForFields) { var firstPosition = fieldWithLocations.Value.Select(loc => loc.SourceSpan.Start).Min(); var location = fieldWithLocations.Value.First(loc => loc.SourceSpan.Start == firstPosition); var message = GetDiagnosticMessageArgument(cbc.CodeBlock, cbc.OwningSymbol, fieldWithLocations.Key); var secondaryLocations = fieldWithLocations.Key.DeclaringSyntaxReferences .Select(x => x.GetSyntax().GetLocation()); c.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], location, additionalLocations: secondaryLocations, messageArgs: message)); } }); }); }