private static List <SyntaxNodeSymbolSemanticModelTuple <SyntaxNode, ISymbol> > GetCandidateDeclarations(CSharpRemovableDeclarationCollector removableDeclarationCollector) { 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)); return(candidateFields.Concat(candidateProperties).ToList()); }
protected override void Initialize(SonarAnalysisContext context) { context.RegisterSymbolAction( c => { var namedType = (INamedTypeSymbol)c.Symbol; if (!namedType.IsClassOrStruct() || namedType.GetAttributes(KnownType.System_Runtime_InteropServices_StructLayoutAttribute).Any() || 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))); var candidateProperties = removableDeclarationCollector.GetRemovableDeclarations( new HashSet <SyntaxKind> { SyntaxKind.PropertyDeclaration }, maxAccessibility) .Where(tuple => IsAutoPropertyWithNoInitializer((PropertyDeclarationSyntax)tuple.SyntaxNode)); 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); }