From 89071513d214ff7ef3c7bbb63f511e2d6d9c5139 Mon Sep 17 00:00:00 2001 From: Manish Vasani Date: Thu, 13 Dec 2018 14:53:16 -0800 Subject: [PATCH] Do not report unused value assignment for VB static local assignment and unused parameter for VB Handles method parameters. --- .../RemoveUnusedParametersTests.vb | 12 ++++++++++++ .../RemoveUnusedValueAssignmentTests.vb | 16 ++++++++++++++++ ...nusedParametersAndValuesDiagnosticAnalyzer.cs | 3 +++ ...Analyzer.SymbolStartAnalyzer.BlockAnalyzer.cs | 9 ++++++++- ...luesDiagnosticAnalyzer.SymbolStartAnalyzer.cs | 3 ++- ...nusedParametersAndValuesDiagnosticAnalyzer.cs | 1 + ...nusedParametersAndValuesDiagnosticAnalyzer.vb | 6 ++++++ 7 files changed, 48 insertions(+), 2 deletions(-) diff --git a/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.vb b/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.vb index a0d86d842f5..1a96a6892bd 100644 --- a/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.vb +++ b/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedParametersTests.vb @@ -63,5 +63,17 @@ $"Class C End Class", parameters:=Nothing, Diagnostic(IDEDiagnosticIds.UnusedParameterDiagnosticId)) End Function + + + Public Async Function ParameterOfMethodThatHandlesEvent() As Task + Await TestDiagnosticMissingAsync( +$"Public Class C + Public Event E(p As Integer) + Dim WithEvents field As New C + + Public Sub M([|p|] As Integer) Handles field.E + End Sub +End Class") + End Function End Class End Namespace diff --git a/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.vb b/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.vb index f3a5025356c..b350ab62086 100644 --- a/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.vb +++ b/src/EditorFeatures/VisualBasicTest/RemoveUnusedParametersAndValues/RemoveUnusedValueAssignmentTests.vb @@ -339,6 +339,22 @@ Class C [|i|] = 1 Next End Sub +End Class") + End Function + + + Public Async Function StaticLocals() As Task + Await TestMissingInRegularAndScriptAsync( +$"Class C + Function Increment() As Boolean + Static count As Integer = 0 + If count > 10 Then + Return True + End If + + [|count|] = count + 1 + Return False + End Function End Class") End Function End Class diff --git a/src/Features/CSharp/Portable/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs b/src/Features/CSharp/Portable/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs index fafe5dca264..5aabe14795a 100644 --- a/src/Features/CSharp/Portable/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs +++ b/src/Features/CSharp/Portable/RemoveUnusedParametersAndValues/CSharpRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs @@ -22,6 +22,9 @@ protected override Option> UnusedValueAss protected override bool SupportsDiscard(SyntaxTree tree) => ((CSharpParseOptions)tree.Options).LanguageVersion >= LanguageVersion.CSharp7; + protected override bool MethodHasHandlesClause(IMethodSymbol method) + => false; + // C# does not have an explicit "call" statement syntax for invocations with explicit value discard. protected override bool IsCallStatement(IExpressionStatementOperation expressionStatement) => false; diff --git a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs index d1dc2d7580a..cd8d7156f45 100644 --- a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs +++ b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.BlockAnalyzer.cs @@ -366,8 +366,15 @@ private void AnalyzeOperationBlockEnd(OperationBlockAnalysisContext context) out ImmutableDictionary properties) { properties = null; + + // Bail out in following cases: + // 1. End user has configured the diagnostic to be suppressed. + // 2. Symbol has error type, hence the diagnostic could be noised + // 3. Symbol is static. For example, assignment to static locals in VB + // is not unnecessary as the assigned value can be used on the next invocation. if (_options.UnusedValueAssignmentSeverity == ReportDiagnostic.Suppress || - symbol.GetSymbolType().IsErrorType()) + symbol.GetSymbolType().IsErrorType() || + symbol.IsStatic) { return false; } diff --git a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs index c67768e58b0..02848e87473 100644 --- a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs +++ b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.SymbolStartAnalyzer.cs @@ -179,7 +179,8 @@ private bool IsUnusedParameterCandidate(IParameterSymbol parameter) method.IsOverride || !method.ExplicitOrImplicitInterfaceImplementations().IsEmpty || method.IsAccessor() || - method.IsAnonymousFunction()) + method.IsAnonymousFunction() || + _compilationAnalyzer.MethodHasHandlesClause(method)) { return false; } diff --git a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs index b4b85a2d993..a5ae2cec015 100644 --- a/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs +++ b/src/Features/Core/Portable/RemoveUnusedParametersAndValues/AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer.cs @@ -88,6 +88,7 @@ protected AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer() protected abstract Location GetDefinitionLocationToFade(IOperation unusedDefinition); protected abstract bool SupportsDiscard(SyntaxTree tree); + protected abstract bool MethodHasHandlesClause(IMethodSymbol method); protected abstract Option> UnusedValueExpressionStatementOption { get; } protected abstract Option> UnusedValueAssignmentOption { get; } diff --git a/src/Features/VisualBasic/Portable/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb b/src/Features/VisualBasic/Portable/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb index c0e505ea036..6a30d929c94 100644 --- a/src/Features/VisualBasic/Portable/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb +++ b/src/Features/VisualBasic/Portable/RemoveUnusedParametersAndValues/VisualBasicRemoveUnusedParametersAndValuesDiagnosticAnalyzer.vb @@ -29,6 +29,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedParametersAndValues Return False End Function + Protected Overrides Function MethodHasHandlesClause(method As IMethodSymbol) As Boolean + Return method.DeclaringSyntaxReferences().Any(Function(decl) + Return TryCast(decl.GetSyntax(), MethodStatementSyntax)?.HandlesClause IsNot Nothing + End Function) + End Function + Protected Overrides Function IsCallStatement(expressionStatement As IExpressionStatementOperation) As Boolean Return TryCast(expressionStatement.Syntax, CallStatementSyntax) IsNot Nothing End Function -- GitLab