未验证 提交 bad6a861 编写于 作者: M Manish Vasani 提交者: GitHub

Merge pull request #31822 from mavasani/ConditionalDirectives

Add workaround to unused parameters/values analyzer for code with con…
...@@ -861,6 +861,21 @@ public async Task Parameter_IndexerMethod() ...@@ -861,6 +861,21 @@ public async Task Parameter_IndexerMethod()
}"); }");
} }
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
public async Task Parameter_ConditionalDirective()
{
await TestDiagnosticMissingAsync(
@"class C
{
void M(int [|p|])
{
#if DEBUG
System.Console.WriteLine(p);
#endif
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)] [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)]
public async Task Parameter_EventHandler_FirstParameter() public async Task Parameter_EventHandler_FirstParameter()
{ {
......
...@@ -5895,6 +5895,28 @@ void M() ...@@ -5895,6 +5895,28 @@ void M()
{ {
List<int> [|x|] = null; List<int> [|x|] = null;
} }
}", optionName);
}
[WorkItem(31583, "https://github.com/dotnet/roslyn/issues/31583")]
[Theory, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedValues)]
[InlineData(nameof(PreferDiscard))]
[InlineData(nameof(PreferUnusedLocal))]
public async Task UsedAssignment_ConditionalPreprocessorDirective(string optionName)
{
await TestMissingInRegularAndScriptAsync(
@"#define DEBUG
class C
{
int M()
{
int [|x|] = 0;
#if DEBUG
x = 1;
#endif
return x;
}
}", optionName); }", optionName);
} }
} }
......
...@@ -73,6 +73,18 @@ $"Public Class C ...@@ -73,6 +73,18 @@ $"Public Class C
Public Sub M([|p|] As Integer) Handles field.E Public Sub M([|p|] As Integer) Handles field.E
End Sub End Sub
End Class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedParameters)>
Public Async Function Parameter_ConditionalDirective() As Task
Await TestDiagnosticMissingAsync(
$"Public Class C
Public Sub M([|p|] As Integer)
#If DEBUG Then
System.Console.WriteLine(p)
#End If
End Sub
End Class") End Class")
End Function End Function
End Class End Class
......
...@@ -355,6 +355,20 @@ $"Class C ...@@ -355,6 +355,20 @@ $"Class C
[|count|] = count + 1 [|count|] = count + 1
Return False Return False
End Function End Function
End Class")
End Function
<Fact, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedValues)>
Public Async Function UsedAssignment_ConditionalPreprocessorDirective() As Task
Await TestMissingInRegularAndScriptAsync(
$"Class C
Function M() As Integer
Dim [|p|] = 0
#If DEBUG Then
p = 1
#End If
Return p
End Function
End Class") End Class")
End Function End Function
End Class End Class
......
...@@ -25,6 +25,9 @@ protected override bool SupportsDiscard(SyntaxTree tree) ...@@ -25,6 +25,9 @@ protected override bool SupportsDiscard(SyntaxTree tree)
protected override bool MethodHasHandlesClause(IMethodSymbol method) protected override bool MethodHasHandlesClause(IMethodSymbol method)
=> false; => false;
protected override bool IsIfConditionalDirective(SyntaxNode node)
=> node is IfDirectiveTriviaSyntax;
// C# does not have an explicit "call" statement syntax for invocations with explicit value discard. // C# does not have an explicit "call" statement syntax for invocations with explicit value discard.
protected override bool IsCallStatement(IExpressionStatementOperation expressionStatement) protected override bool IsCallStatement(IExpressionStatementOperation expressionStatement)
=> false; => false;
......
...@@ -68,6 +68,15 @@ public static void Analyze(OperationBlockStartAnalysisContext context, SymbolSta ...@@ -68,6 +68,15 @@ public static void Analyze(OperationBlockStartAnalysisContext context, SymbolSta
return; return;
} }
// Bail out in presence of conditional directives
// This is a workaround for https://github.com/dotnet/roslyn/issues/31820
// Issue https://github.com/dotnet/roslyn/issues/31821 tracks
// reverting this workaround.
if (HasConditionalDirectives())
{
return;
}
// All operation blocks for a symbol belong to the same tree. // All operation blocks for a symbol belong to the same tree.
var firstBlock = context.OperationBlocks[0]; var firstBlock = context.OperationBlocks[0];
if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree, if (!symbolStartAnalyzer._compilationAnalyzer.TryGetOptions(firstBlock.Syntax.SyntaxTree,
...@@ -103,6 +112,20 @@ bool HasSyntaxErrors() ...@@ -103,6 +112,20 @@ bool HasSyntaxErrors()
return false; return false;
} }
bool HasConditionalDirectives()
{
foreach (var operationBlock in context.OperationBlocks)
{
if (operationBlock.Syntax.DescendantNodes(descendIntoTrivia: true)
.Any(n => symbolStartAnalyzer._compilationAnalyzer.IsIfConditionalDirective(n)))
{
return true;
}
}
return false;
}
} }
private void AnalyzeExpressionStatement(OperationAnalysisContext context) private void AnalyzeExpressionStatement(OperationAnalysisContext context)
......
...@@ -89,6 +89,7 @@ protected AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer() ...@@ -89,6 +89,7 @@ protected AbstractRemoveUnusedParametersAndValuesDiagnosticAnalyzer()
protected abstract Location GetDefinitionLocationToFade(IOperation unusedDefinition); protected abstract Location GetDefinitionLocationToFade(IOperation unusedDefinition);
protected abstract bool SupportsDiscard(SyntaxTree tree); protected abstract bool SupportsDiscard(SyntaxTree tree);
protected abstract bool MethodHasHandlesClause(IMethodSymbol method); protected abstract bool MethodHasHandlesClause(IMethodSymbol method);
protected abstract bool IsIfConditionalDirective(SyntaxNode node);
protected abstract Option<CodeStyleOption<UnusedValuePreference>> UnusedValueExpressionStatementOption { get; } protected abstract Option<CodeStyleOption<UnusedValuePreference>> UnusedValueExpressionStatementOption { get; }
protected abstract Option<CodeStyleOption<UnusedValuePreference>> UnusedValueAssignmentOption { get; } protected abstract Option<CodeStyleOption<UnusedValuePreference>> UnusedValueAssignmentOption { get; }
......
...@@ -35,6 +35,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedParametersAndValues ...@@ -35,6 +35,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.RemoveUnusedParametersAndValues
End Function) End Function)
End Function End Function
Protected Overrides Function IsIfConditionalDirective(node As SyntaxNode) As Boolean
Return TryCast(node, IfDirectiveTriviaSyntax) IsNot Nothing
End Function
Protected Overrides Function IsCallStatement(expressionStatement As IExpressionStatementOperation) As Boolean Protected Overrides Function IsCallStatement(expressionStatement As IExpressionStatementOperation) As Boolean
Return TryCast(expressionStatement.Syntax, CallStatementSyntax) IsNot Nothing Return TryCast(expressionStatement.Syntax, CallStatementSyntax) IsNot Nothing
End Function End Function
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册