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

Merge pull request #32929 from mavasani/Issue32903

Bail out on delegate creation wrapped a in tuple operation
......@@ -6079,6 +6079,30 @@ int Method()
[|target|] = 1;
return data[0];
}
}", optionName);
}
[WorkItem(32903, "https://github.com/dotnet/roslyn/issues/32903")]
[Theory, Trait(Traits.Feature, Traits.Features.CodeActionsRemoveUnusedValues)]
[InlineData(nameof(PreferDiscard))]
[InlineData(nameof(PreferUnusedLocal))]
public async Task DelegateCreationWrappedInATuple_UsedInReturnedLambda(string optionName)
{
await TestMissingInRegularAndScriptAsync(
@"using System;
public class C
{
private (int, int) createTuple() => (1, 1);
public (Func<int>, bool) M()
{
var ([|value1, value2|]) = createTuple();
int LocalFunction() => value1 + value2;
return (LocalFunction, true);
}
}", optionName);
}
}
......
......@@ -42,6 +42,12 @@ private sealed partial class BlockAnalyzer
/// </summary>
private bool _delegateAssignedToFieldOrProperty;
/// <summary>
/// Indicates if a delegate was wrapped within an <see cref="ITupleOperation"/>.
/// We use this value in <see cref="ShouldAnalyze(IOperation, ISymbol)"/> to determine whether to bail from analysis or not.
/// </summary>
private bool _delegateWrappedInTuple;
/// <summary>
/// Indicates if the operation block has an <see cref="IConversionOperation"/> with a delegate type or an anonymous function
/// as it's source and a non-delegate type as it's target.
......@@ -93,6 +99,7 @@ public static void Analyze(OperationBlockStartAnalysisContext context, SymbolSta
context.RegisterOperationAction(blockAnalyzer.AnalyzeDelegateCreationOrAnonymousFunction, OperationKind.DelegateCreation, OperationKind.AnonymousFunction);
context.RegisterOperationAction(blockAnalyzer.AnalyzeArgument, OperationKind.Argument);
context.RegisterOperationAction(blockAnalyzer.AnalyzeConversion, OperationKind.Conversion);
context.RegisterOperationAction(blockAnalyzer.AnalyzeTuple, OperationKind.Tuple);
context.RegisterOperationAction(blockAnalyzer.AnalyzeFieldOrPropertyReference, OperationKind.FieldReference, OperationKind.PropertyReference);
context.RegisterOperationAction(blockAnalyzer.AnalyzeParameterReference, OperationKind.ParameterReference);
context.RegisterOperationBlockEndAction(blockAnalyzer.AnalyzeOperationBlockEnd);
......@@ -204,6 +211,16 @@ private void AnalyzeConversion(OperationAnalysisContext operationAnalysisContext
}
}
private void AnalyzeTuple(OperationAnalysisContext operationAnalysisContext)
{
var tupleOperation = (ITupleOperation)operationAnalysisContext.Operation;
if (!_delegateWrappedInTuple &&
tupleOperation.Elements.Any(o => o.Type.IsDelegateType()))
{
_delegateWrappedInTuple = true;
}
}
private void AnalyzeFieldOrPropertyReference(OperationAnalysisContext operationAnalysisContextContext)
{
var fieldOrPropertyReference = operationAnalysisContextContext.Operation;
......@@ -285,7 +302,17 @@ private bool ShouldAnalyze(IOperation operationBlock, ISymbol owningSymbol)
return false;
}
// 6. Otherwise, we execute analysis by walking the reaching symbol write chain to attempt to
// 6. Bail out if we have a delegate wrapped in a tuple.
// This indicates the delegate targets (such as lambda/local functions) have been wrapped
// within a tuple and passed around and invoked, and these invocations can read values written
// to any local/parameter in the current method. We cannot reliably flag any write to a
// local/parameter as unused for such cases.
if (_delegateWrappedInTuple)
{
return false;
}
// 7. Otherwise, we execute analysis by walking the reaching symbol write chain to attempt to
// find the target method being invoked.
// This works for most common and simple cases where a local is assigned a lambda and invoked later.
// If we are unable to find a target, we will conservatively mark all current symbol writes as read.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册