protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(c => { if (!ReportsOnTestSource && c.Compilation.IsTest()) { return; } var shouldRaise = true; c.RegisterSemanticModelAction(cc => { var requiredAttributeFound = cc.SemanticModel.SyntaxTree.GetRoot() .DescendantNodes() .OfType <AttributeListSyntax>() .SelectMany(list => list.Attributes) .Any(a => IsRequiredAttribute(a, cc.SemanticModel)); if (requiredAttributeFound) { shouldRaise = false; } }); c.RegisterCompilationEndAction(cc => { if (shouldRaise) { cc.ReportDiagnostic(Diagnostic.Create(Rule, null)); } }); }); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterCompilationStartAction(analysisContext => { analysisContext.RegisterSyntaxNodeAction(c => { var declarationSymbol = c.SemanticModel.GetDeclaredSymbol(c.Node); if (declarationSymbol == null) { return; } CheckGenericTypeParameters(declarationSymbol, c); }, SyntaxKind.MethodDeclaration, SyntaxKindEx.LocalFunctionStatement); analysisContext.RegisterSyntaxNodeAction(c => { if (c.ContainingSymbol.Kind != SymbolKind.NamedType) { return; } CheckGenericTypeParameters(c.ContainingSymbol, c); }, SyntaxKind.ClassDeclaration, SyntaxKindEx.RecordDeclaration); });
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( ccc => { if (!IsEnabled(ccc.Options)) { return; } ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var objectCreation = (ObjectCreationExpressionSyntax)c.Node; if (objectInitializationTracker.ShouldBeReported(objectCreation, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], objectCreation.GetLocation())); } }, SyntaxKind.ObjectCreationExpression); ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var assignment = (AssignmentExpressionSyntax)c.Node; if (objectInitializationTracker.ShouldBeReported(assignment, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], assignment.GetLocation())); } }, SyntaxKind.SimpleAssignmentExpression); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( cc => { if (!TryReadConfiguration(cc.Options)) { return; } protobufFileIndex = 0; cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <BaseMethodDeclarationSyntax>(c, x => x.Body), SyntaxKind.ConstructorDeclaration, SyntaxKind.OperatorDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <MethodDeclarationSyntax>(c, x => (CSharpSyntaxNode)x.Body ?? x.ExpressionBody?.Expression), SyntaxKind.MethodDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <AccessorDeclarationSyntax>(c, node => node.Body), SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <PropertyDeclarationSyntax>(c, node => node.ExpressionBody?.Expression), SyntaxKind.PropertyDeclaration); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( c => { var hasResx = false; c.RegisterSyntaxNodeAction( cc => { if (IsResxGeneratedFile(cc.SemanticModel, (ClassDeclarationSyntax)cc.Node)) { hasResx = true; } }, SyntaxKind.ClassDeclaration); c.RegisterCompilationEndAction( cc => { if (!hasResx || HasNeutralResourcesLanguageAttribute(cc.Compilation.Assembly)) { return; } cc.ReportDiagnosticWhenActive(Diagnostic.Create(rule, null)); }); }); }
protected override void Initialize(SonarAnalysisContext context) { base.Initialize(context); context.RegisterCompilationStartAction(compilationContext => { if (IsEnabled(compilationContext.Options)) { context.RegisterSyntaxNodeActionInNonGenerated(VisitAttribute, SyntaxKind.Attribute); } }); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterCompilationStartAction(c => { if (!IsEnabled(c.Options)) { return; } c.RegisterSyntaxNodeActionInNonGenerated(Language.GeneratedCodeRecognizer, VisitInvocations, Language.SyntaxKind.InvocationExpression); c.RegisterSyntaxNodeActionInNonGenerated(Language.GeneratedCodeRecognizer, VisitAssignments, Language.SyntaxKind.IdentifierName); });
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( compilationStartContext => { var allNamedTypeSymbols = compilationStartContext.Compilation.GlobalNamespace.GetAllNamedTypes(); var typeInterfaceMappings = allNamedTypeSymbols.Select(type => new { Type = type.OriginalDefinition, Interfaces = type.OriginalDefinition.AllInterfaces.Select(i => i.OriginalDefinition) }); var interfaceImplementerMappings = new Dictionary <INamedTypeSymbol, HashSet <INamedTypeSymbol> >(); foreach (var typeInterfaceMapping in typeInterfaceMappings) { if (typeInterfaceMapping.Type.IsInterface()) { if (!interfaceImplementerMappings.ContainsKey(typeInterfaceMapping.Type)) { interfaceImplementerMappings.Add(typeInterfaceMapping.Type, new HashSet <INamedTypeSymbol>()); } interfaceImplementerMappings[typeInterfaceMapping.Type].Add(typeInterfaceMapping.Type); } foreach (var @interface in typeInterfaceMapping.Interfaces) { if (!interfaceImplementerMappings.ContainsKey(@interface)) { interfaceImplementerMappings.Add(@interface, new HashSet <INamedTypeSymbol>()); } interfaceImplementerMappings[@interface].Add(typeInterfaceMapping.Type); } } compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var cast = (CastExpressionSyntax)c.Node; var interfaceType = c.SemanticModel.GetTypeInfo(cast.Type).Type as INamedTypeSymbol; var expressionType = c.SemanticModel.GetTypeInfo(cast.Expression).Type as INamedTypeSymbol; CheckTypesForInvalidCast(interfaceType, expressionType, interfaceImplementerMappings, cast.Type.GetLocation(), c); }, SyntaxKind.CastExpression); }); context.RegisterExplodedGraphBasedAnalysis((e, c) => CheckEmptyNullableCast(e, c)); }
protected override void Initialize(SonarAnalysisContext context) => context.RegisterCompilationStartAction( compilationStartContext => { var symbolsWhereTypeIsCreated = new ConcurrentBag <SyntaxNodeWithSymbol <SyntaxNode, ISymbol> >(); var symbolsWhereLocaleIsSet = new ConcurrentBag <ISymbol>(); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated(ProcessObjectCreations(symbolsWhereTypeIsCreated), SyntaxKind.ObjectCreationExpression, SyntaxKindEx.ImplicitObjectCreationExpression); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated(ProcessSimpleAssignments(symbolsWhereLocaleIsSet), SyntaxKind.SimpleAssignmentExpression); compilationStartContext.RegisterCompilationEndAction(ProcessCollectedSymbols(symbolsWhereTypeIsCreated, symbolsWhereLocaleIsSet)); });
protected override void Initialize(SonarAnalysisContext context) => context.RegisterCompilationStartAction( ccc => { if (!IsEnabled(ccc.Options)) { return; } context.RegisterSyntaxNodeActionInNonGenerated(CheckIgnoreAntiforgeryTokenAttribute, SyntaxKind.Attribute, SyntaxKind.ObjectCreationExpression, ImplicitObjectCreationExpression); });
protected sealed override void Initialize(SonarAnalysisContext context) { var analysisContext = new ParameterLoadingAnalysisContext(context); Initialize(analysisContext); context.RegisterCompilationStartAction( cac => { ParameterLoader.SetParameterValues(this, cac.Options); foreach (var compilationStartActions in analysisContext.CompilationStartActions) { compilationStartActions(cac); } }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( ccc => { if (!IsEnabled(ccc.Options)) { return; } context.RegisterSyntaxNodeActionInNonGenerated( GetAnalysisAction(rule), SyntaxKind.StringLiteralExpression); }); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( c => { c.RegisterCompilationEndAction( cc => { var requiredAttributeFound = cc.Compilation.Assembly.GetAttributes(AttributeToFind).Any(); if (!requiredAttributeFound) { cc.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], null)); } }); }); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(analysisContext => { analysisContext.RegisterSyntaxNodeAction( c => { var methodDeclaration = c.Node as MethodDeclarationSyntax; var classDeclaration = c.Node as ClassDeclarationSyntax; if (methodDeclaration != null && !IsMethodCandidate(methodDeclaration, c.SemanticModel)) { return; } var declarationSymbol = c.SemanticModel.GetDeclaredSymbol(c.Node); if (declarationSymbol == null) { return; } var helper = GetTypeParameterHelper(methodDeclaration, classDeclaration); if (helper.TypeParameterList == null || helper.TypeParameterList.Parameters.Count == 0) { return; } var declarations = declarationSymbol.DeclaringSyntaxReferences .Select(reference => reference.GetSyntax()); var usedTypeParameters = GetUsedTypeParameters(declarations, c, analysisContext.Compilation); foreach (var typeParameter in helper.TypeParameterList.Parameters .Select(typeParameter => typeParameter.Identifier.Text) .Where(typeParameter => !usedTypeParameters.Contains(typeParameter))) { c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, helper.TypeParameterList.Parameters.First(tp => tp.Identifier.Text == typeParameter) .GetLocation(), typeParameter, helper.ContainerSyntaxTypeName)); } }, SyntaxKind.MethodDeclaration, SyntaxKind.ClassDeclaration); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( csac => { var nodesWithSecuritySafeCritical = new Dictionary <SyntaxNode, AttributeSyntax>(); var nodesWithSecurityCritical = new Dictionary <SyntaxNode, AttributeSyntax>(); csac.RegisterSyntaxNodeActionInNonGenerated( snac => CollectSecurityAttributes(snac, nodesWithSecuritySafeCritical, nodesWithSecurityCritical), SyntaxKind.Attribute); csac.RegisterCompilationEndAction( cac => ReportOnConflictingTransparencyAttributes(cac, nodesWithSecuritySafeCritical, nodesWithSecurityCritical)); }); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(c => { if (c.Compilation.IsTest()) { return; } c.RegisterCompilationEndAction(cc => { var requiredAttributeFound = cc.Compilation.Assembly.GetAttributes().Any(a => a.AttributeClass.Is(AttributeToFind)); if (!requiredAttributeFound) { cc.ReportDiagnostic(Diagnostic.Create(Rule, null)); } }); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( ccc => { if (!IsEnabled(ccc.Options)) { return; } ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var objectCreation = (ObjectCreationExpressionSyntax)c.Node; if (IsTrackedType(objectCreation, c.SemanticModel) && !ObjectCreatedWithAllowedValue(objectCreation, c.SemanticModel) && !IsLaterAssignedWithAllowedValue(objectCreation, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], objectCreation.GetLocation())); } }, SyntaxKind.ObjectCreationExpression); ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var assignment = (AssignmentExpressionSyntax)c.Node; // Ignore assignments within object initializers, they are // reported in the ObjectCreationExpression handler if (assignment.FirstAncestorOrSelf <InitializerExpressionSyntax>() == null && IsTrackedPropertyName(assignment.Left) && IsPropertyOnTrackedType(assignment.Left, c.SemanticModel) && !IsAllowedValue(assignment.Right, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(SupportedDiagnostics[0], assignment.GetLocation())); } }, SyntaxKind.SimpleAssignmentExpression); }); }
protected sealed override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( compilationStartContext => { var allNamedTypeSymbols = compilationStartContext.Compilation.GlobalNamespace.GetAllNamedTypes(); var allInterfacesWithImplementationsOverriddenEquals = allNamedTypeSymbols .Where(t => t.AllInterfaces.Any() && HasEqualsOverride(t)) .SelectMany(t => t.AllInterfaces) .ToImmutableHashSet(); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var binary = (BinaryExpressionSyntax)c.Node; if (!IsBinaryCandidateForReporting(binary, c.SemanticModel)) { return; } var typeLeft = c.SemanticModel.GetTypeInfo(binary.Left).Type; var typeRight = c.SemanticModel.GetTypeInfo(binary.Right).Type; if (typeLeft == null || typeRight == null || IsAllowedType(typeLeft) || IsAllowedType(typeRight)) { return; } if (MightOverrideEquals(typeLeft, allInterfacesWithImplementationsOverriddenEquals) || MightOverrideEquals(typeRight, allInterfacesWithImplementationsOverriddenEquals)) { c.ReportDiagnostic(Diagnostic.Create(rule, binary.OperatorToken.GetLocation())); } }, SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression); }); }
protected override void Initialize(SonarAnalysisContext context) { base.Initialize(context); context.RegisterCompilationStartAction( c => { if (!IsEnabled(c.Options)) { return; } c.RegisterSyntaxNodeActionInNonGenerated( new VariableDeclarationBannedWordsFinder(this).GetAnalysisAction(rule), SyntaxKind.VariableDeclarator); c.RegisterSyntaxNodeActionInNonGenerated( new AssignmentExpressionBannedWordsFinder(this).GetAnalysisAction(rule), SyntaxKind.SimpleAssignmentStatement); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSyntaxNodeActionInNonGenerated(c => { var statement = (OptionStatementSyntax)c.Node; if (statement.NameKeyword.IsKind(SyntaxKind.StrictKeyword) && !statement.ValueKeyword.IsKind(SyntaxKind.OnKeyword)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(Rule, statement.GetLocation(), StatementMessage)); } }, SyntaxKind.OptionStatement); context.RegisterCompilationStartAction(cStart => cStart.RegisterCompilationEndAction(c => { if (c.Compilation.VB().Options.OptionStrict != OptionStrict.On) { c.ReportDiagnosticWhenActive(Diagnostic.Create(Rule, null, string.Format(AssemblyMessageFormat, c.Compilation.AssemblyName))); } })); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(analysisContext => { analysisContext.RegisterSyntaxNodeAction( c => { var declarationSymbol = c.SemanticModel.GetDeclaredSymbol(c.Node); if (declarationSymbol == null) { return; } var helper = CreateParametersInfo(c.Node, c.SemanticModel); if (helper.Parameters == null || helper.Parameters.Parameters.Count == 0) { return; } var declarations = declarationSymbol.DeclaringSyntaxReferences .Select(reference => reference.GetSyntax()); var typeParameterNames = helper.Parameters.Parameters.Select(typeParameter => typeParameter.Identifier.Text).ToArray(); var usedTypeParameters = GetUsedTypeParameters(declarations, typeParameterNames, c, analysisContext.Compilation); foreach (var typeParameter in typeParameterNames .Where(typeParameter => !usedTypeParameters.Contains(typeParameter))) { c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, helper.Parameters.Parameters.First(tp => tp.Identifier.Text == typeParameter) .GetLocation(), typeParameter, helper.ContainerName)); } }, SyntaxKind.MethodDeclaration, SyntaxKind.ClassDeclaration, SyntaxKindEx.LocalFunctionStatement); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( cc => { configuration.Read(cc.Options); if (string.IsNullOrEmpty(configuration.ProjectOutputPath) || !configuration.EnabledRules.Any(SecurityRules.Contains)) { return; } InitProtobufDirectory(); protobufFileIndex = 0; cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <ConstructorDeclarationSyntax>(c, x => x.Body), SyntaxKind.ConstructorDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <MethodDeclarationSyntax>(c, x => (CSharpSyntaxNode)x.Body ?? x.ExpressionBody?.Expression), SyntaxKind.MethodDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <OperatorDeclarationSyntax>(c, x => (CSharpSyntaxNode)x.Body ?? x.ExpressionBody?.Expression), SyntaxKind.OperatorDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <AccessorDeclarationSyntax>(c, node => node.Body), SyntaxKind.GetAccessorDeclaration, SyntaxKind.SetAccessorDeclaration); cc.RegisterSyntaxNodeActionInNonGenerated( c => WriteUCFG <PropertyDeclarationSyntax>(c, node => node.ExpressionBody?.Expression), SyntaxKind.PropertyDeclaration); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( ccc => { ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var objectCreation = (ObjectCreationExpressionSyntax)c.Node; var trackers = TrackerFactory.Create(c.Compilation, VersionProvider); if (trackers.xmlDocumentTracker.ShouldBeReported(objectCreation, c.SemanticModel) || trackers.xmlTextReaderTracker.ShouldBeReported(objectCreation, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, objectCreation.GetLocation())); } VerifyXPathDocumentConstructor(c); }, SyntaxKind.ObjectCreationExpression); ccc.RegisterSyntaxNodeActionInNonGenerated( c => { var assignment = (AssignmentExpressionSyntax)c.Node; var trackers = TrackerFactory.Create(c.Compilation, VersionProvider); if (trackers.xmlDocumentTracker.ShouldBeReported(assignment, c.SemanticModel) || trackers.xmlTextReaderTracker.ShouldBeReported(assignment, c.SemanticModel)) { c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, assignment.GetLocation())); } }, SyntaxKind.SimpleAssignmentExpression); ccc.RegisterSyntaxNodeActionInNonGenerated(VerifyXmlReaderInvocations, SyntaxKind.InvocationExpression); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(analysisContext => { var fieldsByNamedType = MultiValueDictionary<INamedTypeSymbol, IFieldSymbol>.Create<HashSet<IFieldSymbol>>(); var fieldsAssigned = ImmutableHashSet<IFieldSymbol>.Empty; 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) .ToImmutableHashSet(); 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; fieldsAssigned = 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; fieldsAssigned = 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 override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(analysisContext => { if (analysisContext.Compilation.IsTest()) { return; } var fieldsByNamedType = MultiValueDictionary <INamedTypeSymbol, IFieldSymbol> .Create <HashSet <IFieldSymbol> >(); var fieldsAssigned = ImmutableHashSet <IFieldSymbol> .Empty; 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) .ToImmutableHashSet(); 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; fieldsAssigned = 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; fieldsAssigned = 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.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.RegisterCompilationStartAction(analysisContext => { analysisContext.RegisterSyntaxNodeAction( c => { var methodDeclaration = c.Node as MethodDeclarationSyntax; var classDeclaration = c.Node as ClassDeclarationSyntax; if (methodDeclaration != null && !IsMethodCandidate(methodDeclaration, c.SemanticModel)) { return; } var declarationSymbol = c.SemanticModel.GetDeclaredSymbol(c.Node); if (declarationSymbol == null) { return; } var helper = GetTypeParameterHelper(methodDeclaration, classDeclaration); if (helper.TypeParameterList == null || helper.TypeParameterList.Parameters.Count == 0) { return; } var declarations = declarationSymbol.DeclaringSyntaxReferences .Select(reference => reference.GetSyntax()); var usedTypeParameters = GetUsedTypeParameters(declarations, c, analysisContext.Compilation); foreach (var typeParameter in helper.TypeParameterList.Parameters .Select(typeParameter => typeParameter.Identifier.Text) .Where(typeParameter => !usedTypeParameters.Contains(typeParameter))) { c.ReportDiagnostic(Diagnostic.Create(Rule, helper.TypeParameterList.Parameters.First(tp => tp.Identifier.Text == typeParameter) .GetLocation(), typeParameter, helper.ContainerSyntaxTypeName)); } }, SyntaxKind.MethodDeclaration, SyntaxKind.ClassDeclaration); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction(analysisContext => { var candidateFields = ImmutableHashSet<IFieldSymbol>.Empty; var assignedAsReadonly = ImmutableHashSet<IFieldSymbol>.Empty; var nonCandidateFields = ImmutableHashSet<IFieldSymbol>.Empty; analysisContext.RegisterSyntaxNodeAction(c => { var fieldDeclaration = (FieldDeclarationSyntax) c.Node; foreach (var field in fieldDeclaration.Declaration.Variables .Select(variableDeclaratorSyntax => new { Syntax = variableDeclaratorSyntax, Symbol = c.SemanticModel.GetDeclaredSymbol(variableDeclaratorSyntax) as IFieldSymbol }) .Where(f => f.Symbol != null) .Where(f => FieldIsRelevant(f.Symbol))) { candidateFields = candidateFields.Add(field.Symbol); if (field.Syntax.Initializer != null) { assignedAsReadonly = assignedAsReadonly.Add(field.Symbol); } } }, SyntaxKind.FieldDeclaration); analysisContext.RegisterSyntaxNodeAction( c => { var assignment = (AssignmentExpressionSyntax) c.Node; var expression = assignment.Left; ProcessExpressionChange(expression, c.SemanticModel, ref nonCandidateFields, ref assignedAsReadonly); }, SyntaxKind.SimpleAssignmentExpression, SyntaxKind.AddAssignmentExpression, SyntaxKind.SubtractAssignmentExpression, SyntaxKind.MultiplyAssignmentExpression, SyntaxKind.DivideAssignmentExpression, SyntaxKind.ModuloAssignmentExpression, SyntaxKind.AndAssignmentExpression, SyntaxKind.ExclusiveOrAssignmentExpression, SyntaxKind.OrAssignmentExpression, SyntaxKind.LeftShiftAssignmentExpression, SyntaxKind.RightShiftAssignmentExpression); analysisContext.RegisterSyntaxNodeAction( c => { var unary = (PrefixUnaryExpressionSyntax)c.Node; var expression = unary.Operand; ProcessExpressionChange(expression, c.SemanticModel, ref nonCandidateFields, ref assignedAsReadonly); }, SyntaxKind.PreDecrementExpression, SyntaxKind.PreIncrementExpression); analysisContext.RegisterSyntaxNodeAction( c => { var unary = (PostfixUnaryExpressionSyntax)c.Node; var expression = unary.Operand; ProcessExpressionChange(expression, c.SemanticModel, ref nonCandidateFields, ref assignedAsReadonly); }, SyntaxKind.PostDecrementExpression, SyntaxKind.PostIncrementExpression); analysisContext.RegisterSyntaxNodeAction(c => { var argument = (ArgumentSyntax) c.Node; if (argument.RefOrOutKeyword.IsKind(SyntaxKind.None)) { return; } var fieldSymbol = c.SemanticModel.GetSymbolInfo(argument.Expression).Symbol as IFieldSymbol; if (FieldIsRelevant(fieldSymbol)) { nonCandidateFields = nonCandidateFields.Add(fieldSymbol); } }, SyntaxKind.Argument); analysisContext.RegisterCompilationEndAction(c => { var fields = candidateFields.Except(nonCandidateFields); fields = fields.Intersect(assignedAsReadonly); foreach (var field in fields) { var declarationReference = field.DeclaringSyntaxReferences.FirstOrDefault(); var fieldSyntax = declarationReference?.GetSyntax() as VariableDeclaratorSyntax; if (fieldSyntax == null) { continue; } c.ReportDiagnosticIfNonGenerated( Diagnostic.Create(Rule, fieldSyntax.Identifier.GetLocation(), fieldSyntax.Identifier.ValueText), c.Compilation); } }); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( analysisContext => { var disposeMethod = GetDisposeMethod(analysisContext.Compilation); if (disposeMethod == null) { return; } var disposeMethodsCalledFromDispose = MultiValueDictionary<INamedTypeSymbol, IMethodSymbol>.Create<HashSet<IMethodSymbol>>(); var implementingDisposeMethods = ImmutableHashSet<IMethodSymbol>.Empty; var allDisposeMethods = ImmutableHashSet<IMethodSymbol>.Empty; analysisContext.RegisterSymbolAction(c => CollectDisposeMethods(c, disposeMethod, ref allDisposeMethods, ref implementingDisposeMethods), SymbolKind.Method); analysisContext.RegisterCodeBlockStartAction<SyntaxKind>( cbc => { var methodDeclaration = cbc.CodeBlock as MethodDeclarationSyntax; if (methodDeclaration == null || methodDeclaration.Identifier.ValueText != DisposeMethodName) { return; } var declaredMethodSymbol = cbc.SemanticModel.GetDeclaredSymbol(methodDeclaration); if (declaredMethodSymbol == null || !MethodIsDisposeImplementation(declaredMethodSymbol, disposeMethod)) { return; } var disposableType = declaredMethodSymbol.ContainingType; cbc.RegisterSyntaxNodeAction( c => CollectDisposeMethodsCalledFromDispose((InvocationExpressionSyntax) c.Node, c.SemanticModel, disposableType, disposeMethodsCalledFromDispose), SyntaxKind.InvocationExpression); }); analysisContext.RegisterCompilationEndAction( c => ReportDisposeMethods(allDisposeMethods, implementingDisposeMethods, disposeMethodsCalledFromDispose, c)); }); }
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>(); // Collect here all named types from the project to look for internal member usages. var allNamedTypes = new ConcurrentBag <INamedTypeSymbol>(); c.RegisterSymbolAction( cc => { var namedType = (INamedTypeSymbol)cc.Symbol; if (!namedType.IsClassOrStruct() || namedType.ContainingType != null || namedType.DerivesFromAny(IgnoredTypes)) { return; } // Collect all symbols to try to look for used internal members when the compilation ends allNamedTypes.Add(namedType); // Collect symbols of private members that could potentially be removed var removableSymbolsCollector = new RemovableSymbolCollector(c.Compilation.GetSemanticModel); VisitDeclaringReferences(namedType, removableSymbolsCollector); // Keep the removable internal types for when the compilation ends foreach (var internalSymbol in removableSymbolsCollector.InternalSymbols.OfType <INamedTypeSymbol>()) { removableInternalTypes.Add(internalSymbol); } var usageCollector = new SymbolUsageCollector( c.Compilation.GetSemanticModel, removableSymbolsCollector.PrivateSymbols.Select(s => s.Name).ToHashSet()); VisitDeclaringReferences(namedType, usageCollector); var diagnostics = GetDiagnostics(usageCollector, removableSymbolsCollector.PrivateSymbols, "private", removableSymbolsCollector.FieldLikeSymbols); 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 SymbolUsageCollector( c.Compilation.GetSemanticModel, removableInternalTypes.Select(s => s.Name).ToHashSet()); foreach (var symbol in allNamedTypes) { VisitDeclaringReferences(symbol, usageCollector); } var diagnostics = GetDiagnostics(usageCollector, removableInternalTypes.ToHashSet(), "internal", new BidirectionalDictionary <ISymbol, SyntaxNode>()); foreach (var diagnostic in diagnostics) { cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation); } }); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( compilationStartContext => { var allNamedTypeSymbols = compilationStartContext.Compilation.GlobalNamespace.GetAllNamedTypes(); var typeInterfaceMappings = allNamedTypeSymbols.Select(type => new { Type = type.OriginalDefinition, Interfaces = type.OriginalDefinition.AllInterfaces.Select(i => i.OriginalDefinition) }); var interfaceImplementerMappings = new Dictionary<INamedTypeSymbol, HashSet<INamedTypeSymbol>>(); foreach (var typeInterfaceMapping in typeInterfaceMappings) { if (typeInterfaceMapping.Type.IsInterface()) { if (!interfaceImplementerMappings.ContainsKey(typeInterfaceMapping.Type)) { interfaceImplementerMappings.Add(typeInterfaceMapping.Type, new HashSet<INamedTypeSymbol>()); } interfaceImplementerMappings[typeInterfaceMapping.Type].Add(typeInterfaceMapping.Type); } foreach (var @interface in typeInterfaceMapping.Interfaces) { if (!interfaceImplementerMappings.ContainsKey(@interface)) { interfaceImplementerMappings.Add(@interface, new HashSet<INamedTypeSymbol>()); } interfaceImplementerMappings[@interface].Add(typeInterfaceMapping.Type); } } compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var cast = (CastExpressionSyntax)c.Node; var interfaceType = c.SemanticModel.GetTypeInfo(cast.Type).Type as INamedTypeSymbol; var expressionType = c.SemanticModel.GetTypeInfo(cast.Expression).Type as INamedTypeSymbol; CheckTypesForInvalidCast(interfaceType, expressionType, interfaceImplementerMappings, cast.Type.GetLocation(), c); }, SyntaxKind.CastExpression); compilationStartContext.RegisterSyntaxNodeAction( c => { var cast = (BinaryExpressionSyntax)c.Node; var interfaceType = c.SemanticModel.GetTypeInfo(cast.Right).Type as INamedTypeSymbol; var expressionType = c.SemanticModel.GetTypeInfo(cast.Left).Type as INamedTypeSymbol; CheckTypesForInvalidCast(interfaceType, expressionType, interfaceImplementerMappings, cast.Right.GetLocation(), c); }, SyntaxKind.AsExpression, SyntaxKind.IsExpression); }); context.RegisterExplodedGraphBasedAnalysis((e, c) => CheckEmptyNullableCast(e, c)); }
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, removableSymbolsCollector.PrivateSymbols); 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.HasAttribute(KnownType.System_Runtime_CompilerServices_InternalsVisibleToAttribute); if (foundInternalsVisibleTo || removableInternalTypes.Count == 0) { return; } var usageCollector = new CSharpSymbolUsageCollector(c.Compilation, removableInternalTypes.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 override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( compilationStartContext => { var allNamedTypeSymbols = compilationStartContext.Compilation.GlobalNamespace.GetAllNamedTypes(); var allInterfacesWithImplementationsOverridenEquals = allNamedTypeSymbols .Where(t => t.AllInterfaces.Any() && HasEqualsOverride(t)) .SelectMany(t => t.AllInterfaces) .ToImmutableHashSet(); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var binary = (BinaryExpressionSyntax)c.Node; if (!IsBinaryCandidateForReporting(binary, c.SemanticModel)) { return; } var typeLeft = c.SemanticModel.GetTypeInfo(binary.Left).Type; var typeRight = c.SemanticModel.GetTypeInfo(binary.Right).Type; if (typeLeft == null || typeRight == null || IsAllowedType(typeLeft) || IsAllowedType(typeRight)) { return; } if (MightOverrideEquals(typeLeft, allInterfacesWithImplementationsOverridenEquals) || MightOverrideEquals(typeRight, allInterfacesWithImplementationsOverridenEquals)) { c.ReportDiagnostic(Diagnostic.Create(Rule, binary.OperatorToken.GetLocation())); } }, SyntaxKind.EqualsExpression, SyntaxKind.NotEqualsExpression); }); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterCompilationStartAction( compilationStartContext => { var symbolsWhereTypeIsCreated = new ConcurrentBag <SyntaxNodeWithSymbol <ObjectCreationExpressionSyntax, ISymbol> >(); var symbolsWhereLocaleIsSet = new ConcurrentBag <ISymbol>(); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var objectCreation = (ObjectCreationExpressionSyntax)c.Node; var objectType = c.SemanticModel.GetSymbolInfo(objectCreation.Type).Symbol as ITypeSymbol; if (objectType == null || !objectType.IsAny(checkedTypes)) { return; } var variableSyntax = GetAssignmentTargetVariable(objectCreation); if (variableSyntax == null) { return; } var variableSymbol = variableSyntax is IdentifierNameSyntax ? c.SemanticModel.GetSymbolInfo(variableSyntax).Symbol : c.SemanticModel.GetDeclaredSymbol(variableSyntax); if (variableSymbol != null) { symbolsWhereTypeIsCreated.Add(variableSymbol.ToSymbolWithSyntax(objectCreation)); } }, SyntaxKind.ObjectCreationExpression); compilationStartContext.RegisterSyntaxNodeActionInNonGenerated( c => { var assignmentExpression = (AssignmentExpressionSyntax)c.Node; var propertySymbol = GetPropertySymbol(assignmentExpression, c.SemanticModel); if (propertySymbol != null && propertySymbol.ContainingType.IsAny(checkedTypes) && propertySymbol.Name == "Locale") { var variableSymbol = GetAccessedVariable(assignmentExpression, c.SemanticModel); if (variableSymbol != null) { symbolsWhereLocaleIsSet.Add(variableSymbol); } } }, SyntaxKind.SimpleAssignmentExpression); compilationStartContext.RegisterCompilationEndAction( c => { var invalidDataTypeCreation = symbolsWhereTypeIsCreated .Where(x => !symbolsWhereLocaleIsSet.Contains(x.Symbol)); foreach (var invalidCreation in invalidDataTypeCreation) { var typeName = invalidCreation.Symbol.GetSymbolType()?.Name; if (typeName == null) { continue; } c.ReportDiagnosticWhenActive(Diagnostic.Create(rule, invalidCreation.Syntax.GetLocation(), typeName)); } }); }); }