private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration, INamedTypeSymbol debuggerDisplayAttribute) { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return; } SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members; UnusedMemberWalker walker = null; foreach (MemberDeclarationSyntax member in members) { if (member.ContainsDiagnostics) { continue; } if (member.ContainsDirectives) { continue; } switch (member.Kind()) { case SyntaxKind.DelegateDeclaration: { var declaration = (DelegateDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddDelegate(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventDeclaration: { var declaration = (EventDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventFieldDeclaration: { var declaration = (EventFieldDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration); } break; } case SyntaxKind.FieldDeclaration: { var declaration = (FieldDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword)); } break; } case SyntaxKind.MethodDeclaration: { var declaration = (MethodDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (declaration.ExplicitInterfaceSpecifier == null && !declaration.AttributeLists.Any() && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { string methodName = declaration.Identifier.ValueText; if (!IsMainMethod(declaration, modifiers, methodName)) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(methodName, declaration); } } break; } case SyntaxKind.PropertyDeclaration: { var declaration = (PropertyDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } } } if (walker == null) { return; } if (debuggerDisplayAttribute != null && walker.Nodes.Any(f => f.CanBeInDebuggerDisplayAttribute) && ShouldAnalyzeDebuggerDisplayAttribute()) { string value = context.SemanticModel .GetDeclaredSymbol(typeDeclaration, context.CancellationToken) .GetAttribute(debuggerDisplayAttribute)? .ConstructorArguments .SingleOrDefault(shouldThrow: false) .Value? .ToString(); if (value != null) { RemoveMethodsAndPropertiesThatAreInDebuggerDisplayAttributeValue(walker.Nodes, value); } if (walker.Nodes.Count == 0) { return; } } walker.Visit(typeDeclaration); foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker)) { SyntaxNode node = info.Node; if (node is VariableDeclaratorSyntax variableDeclarator) { var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; if (variableDeclaration.Variables.Count == 1) { ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent)); } else { ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent)); } } else { ReportDiagnostic(context, node, CSharpFacts.GetTitle(node)); } } bool ShouldAnalyzeDebuggerDisplayAttribute() { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return(true); } foreach (AttributeListSyntax attributeList in typeDeclaration.AttributeLists) { foreach (AttributeSyntax attribute in attributeList.Attributes) { if (attribute.ArgumentList?.Arguments.Count(f => f.NameEquals == null) == 1) { return(true); } } } return(false); } }
private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration) { if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword)) { return; } SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members; UnusedMemberWalker walker = null; foreach (MemberDeclarationSyntax member in members) { if (member.ContainsDiagnostics) { continue; } if (member.ContainsDirectives) { continue; } switch (member.Kind()) { case SyntaxKind.DelegateDeclaration: { var declaration = (DelegateDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventDeclaration: { var declaration = (EventDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } case SyntaxKind.EventFieldDeclaration: { var declaration = (EventFieldDeclarationSyntax)member; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration); } break; } case SyntaxKind.FieldDeclaration: { var declaration = (FieldDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword)); } break; } case SyntaxKind.MethodDeclaration: { var declaration = (MethodDeclarationSyntax)member; SyntaxTokenList modifiers = declaration.Modifiers; if (declaration.ExplicitInterfaceSpecifier == null && !declaration.AttributeLists.Any() && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { string methodName = declaration.Identifier.ValueText; if (!IsMainMethod(declaration, modifiers, methodName)) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(methodName, declaration); } } break; } case SyntaxKind.PropertyDeclaration: { var declaration = (PropertyDeclarationSyntax)member; if (declaration.ExplicitInterfaceSpecifier == null && SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private) { if (walker == null) { walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken); } walker.AddNode(declaration.Identifier.ValueText, declaration); } break; } } } if (walker == null) { return; } walker.Visit(typeDeclaration); foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker)) { SyntaxNode node = info.Node; if (node is VariableDeclaratorSyntax variableDeclarator) { var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent; if (variableDeclaration.Variables.Count == 1) { ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent)); } else { ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent)); } } else { ReportDiagnostic(context, node, CSharpFacts.GetTitle(node)); } } }
public static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context) { var classDeclaration = (ClassDeclarationSyntax)context.Node; if (!classDeclaration.Identifier.ValueText.EndsWith("Extensions", StringComparison.Ordinal)) { return; } if (!classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { return; } if (!classDeclaration.IsParentKind(SyntaxKind.NamespaceDeclaration, SyntaxKind.CompilationUnit)) { return; } if (!SyntaxAccessibility.GetAccessibility(classDeclaration).Is(Accessibility.Public, Accessibility.Internal)) { return; } foreach (MemberDeclarationSyntax member in classDeclaration.Members) { if (!member.IsKind(SyntaxKind.MethodDeclaration)) { continue; } var methodDeclaration = (MethodDeclarationSyntax)member; if (!methodDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword)) { continue; } if (!SyntaxAccessibility.GetAccessibility(methodDeclaration).Is(Accessibility.Public, Accessibility.Internal)) { continue; } ParameterSyntax parameter = methodDeclaration.ParameterList?.Parameters.FirstOrDefault(); if (parameter == null) { continue; } bool isThis = false; bool isIn = false; bool isRef = false; foreach (SyntaxToken modifier in parameter.Modifiers) { SyntaxKind kind = modifier.Kind(); if (kind == SyntaxKind.ThisKeyword) { isThis = true; break; } else if (kind == SyntaxKind.InKeyword) { isIn = true; } else if (kind == SyntaxKind.RefKeyword) { isRef = true; } if (isThis) { break; } } if (isThis) { continue; } if (isIn) { IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); ITypeSymbol typeSymbol = parameterSymbol.Type; if (!typeSymbol.IsValueType) { continue; } if (typeSymbol.Kind == SymbolKind.TypeParameter) { continue; } } else if (isRef) { IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken); if (!parameterSymbol.Type.IsValueType) { continue; } } context.ReportDiagnostic(DiagnosticDescriptors.MakeMethodExtensionMethod, methodDeclaration.Identifier); } }