private static IImmutableList<IParameterSymbol> GetUnusedParameters(BaseMethodDeclarationSyntax declaration, IMethodSymbol methodSymbol, SemanticModel semanticModel) { var usedParameters = new HashSet<IParameterSymbol>(); SyntaxNode[] bodies; if (declaration.IsKind(SyntaxKind.MethodDeclaration)) { var methodDeclararion = (MethodDeclarationSyntax)declaration; bodies = new SyntaxNode[] { methodDeclararion.Body, methodDeclararion.ExpressionBody }; } else { var constructorDeclaration = (ConstructorDeclarationSyntax)declaration; bodies = new SyntaxNode[] { constructorDeclaration.Body, constructorDeclaration.Initializer }; } foreach (var body in bodies.Where(b => b != null)) { usedParameters.UnionWith(GetUsedParameters(methodSymbol.Parameters, body, semanticModel)); } var unusedParameter = methodSymbol.Parameters.Except(usedParameters); if (methodSymbol.IsExtensionMethod) { unusedParameter = unusedParameter.Except(new[] { methodSymbol.Parameters.First() }); } return unusedParameter.Except(usedParameters).ToImmutableArray(); }
private static void ReportOnDeadParametersAtEntry(BaseMethodDeclarationSyntax declaration, IMethodSymbol methodSymbol, IImmutableList<IParameterSymbol> noReportOnParameters, SyntaxNodeAnalysisContext context) { if (!declaration.IsKind(SyntaxKind.MethodDeclaration) || declaration.Body == null) { return; } var excludedParameters = noReportOnParameters; if (methodSymbol.IsExtensionMethod) { excludedParameters = excludedParameters.Add(methodSymbol.Parameters.First()); } excludedParameters = excludedParameters.AddRange(methodSymbol.Parameters.Where(p => p.RefKind != RefKind.None)); var candidateParameters = methodSymbol.Parameters.Except(excludedParameters); if (!candidateParameters.Any()) { return; } IControlFlowGraph cfg; if (!ControlFlowGraph.TryGet(declaration.Body, context.SemanticModel, out cfg)) { return; } var lva = LiveVariableAnalysis.Analyze(cfg, methodSymbol, context.SemanticModel); var liveParameters = lva.GetLiveIn(cfg.EntryBlock).OfType<IParameterSymbol>(); ReportOnUnusedParameters(declaration, candidateParameters.Except(liveParameters).Except(lva.CapturedVariables), MessageDead, context, isRemovable: false); }