提交 1ae8b5cf 编写于 作者: M Manish Vasani

Fix assert in UsePatternMatching.CSharpAsAndNullCheckDiagnosticAnalyzer

1. Bail out early if there is a reference to assigned local between the declaration and null check being replaced with pattern matching.
2. Remove assert for bail out in presence of errors/unhandled cases.

Fixes #31388
上级 f5178472
......@@ -1373,6 +1373,27 @@ C M(object e)
System.Func<C> f = () => c == null ? null : c;
return c;
}
}");
}
[WorkItem(31388, "https://github.com/dotnet/roslyn/issues/31388")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsInlineTypeCheck)]
public async Task TestUseBetweenAssignmentAndIfCondition()
{
await TestMissingInRegularAndScriptAsync(
@"class C
{
void M(object o)
{
[|var|] c = o as C;
M2(c != null);
if (c == null)
{
return;
}
}
void M2(bool b) { }
}");
}
}
......
......@@ -227,9 +227,7 @@ private bool CanSafelyConvertToPatternMatching()
return CheckStatement(statement);
}
// We shouldn't normally get here but if we do, it's
// either an error in the code or an unhandled case.
Debug.Assert(false, "unhandled case.");
// Bail out for error cases and unhandled cases.
break;
}
......
......@@ -145,30 +145,41 @@ private void SyntaxNodeAction(SyntaxNodeAnalysisContext syntaxContext)
// if (s != null) { ... }
//
// It's no longer safe to use pattern-matching because 'field is string s' would never be true.
//
// Additionally, also bail out if the assigned local is referenced (read or write) up to the point of null check.
// var s = field as string;
// MethodCall(flag: s == null);
// if (s != null) { ... }
//
var asOperand = semanticModel.GetSymbolInfo(asExpression.Left, cancellationToken).Symbol;
var symbolName = asOperand?.Name;
if (symbolName != null)
var localStatementStart = localStatement.SpanStart;
var comparisonSpanStart = comparison.SpanStart;
foreach (var descendentNode in enclosingBlock.DescendantNodes())
{
var localStatementStart = localStatement.SpanStart;
var comparisonSpanStart = comparison.SpanStart;
var descendentNodeSpanStart = descendentNode.SpanStart;
if (descendentNodeSpanStart <= localStatementStart)
{
continue;
}
foreach (var descendentNode in enclosingBlock.DescendantNodes())
if (descendentNodeSpanStart >= comparisonSpanStart)
{
var descendentNodeSpanStart = descendentNode.SpanStart;
if (descendentNodeSpanStart <= localStatementStart)
{
continue;
}
break;
}
if (descendentNodeSpanStart >= comparisonSpanStart)
if (descendentNode.IsKind(SyntaxKind.IdentifierName, out IdentifierNameSyntax identifierName))
{
// Check if this is a 'write' to the asOperand.
if (identifierName.Identifier.ValueText == asOperand?.Name &&
asOperand.Equals(semanticModel.GetSymbolInfo(identifierName, cancellationToken).Symbol) &&
identifierName.IsWrittenTo())
{
break;
return;
}
if (descendentNode.IsKind(SyntaxKind.IdentifierName, out IdentifierNameSyntax identifierName) &&
identifierName.Identifier.ValueText == symbolName &&
asOperand.Equals(semanticModel.GetSymbolInfo(identifierName, cancellationToken).Symbol) &&
identifierName.IsWrittenTo())
// Check if this is a reference to the assigned local.
if (identifierName.Identifier.ValueText == localSymbol.Name)
{
return;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册