提交 7b0aaff7 编写于 作者: A Allison Chou

Implicit var switch expression fix

上级 725e3fc4
......@@ -2735,5 +2735,35 @@ static void Main(string[] args)
}",
options: ImplicitTypeEverywhere());
}
[WpfFact, Trait(Traits.Feature, Traits.Features.CodeActionsUseExplicitType)]
[WorkItem(44507, "https://github.com/dotnet/roslyn/issues/44507")]
public async Task DoNotSuggestVarInAmbiguousSwitchExpression()
{
await TestMissingAsync(
@"using System;
class C
{
void M()
{
var i = 1;
[||]C x = i switch
{
0 => new A(),
1 => new B(),
_ => throw new ArgumentException(),
};
}
}
class A : C
{
}
class B : C
{
}", parameters: new TestParameters(options: ImplicitTypeEverywhere()));
}
}
}
......@@ -560,10 +560,7 @@ private static bool IsParamsArrayExpanded(SemanticModel semanticModel, SyntaxNod
}
else
{
#pragma warning disable IDE0007 // Use implicit type - Using 'var' causes "error CS8506: No best type was found for the switch expression"
// TODO: File a bug on IDE0007 analyzer
BaseArgumentListSyntax? argumentList = node switch
#pragma warning restore IDE0007 // Use implicit type
{
InvocationExpressionSyntax invocation => invocation.ArgumentList,
ObjectCreationExpressionSyntax objectCreation => objectCreation.ArgumentList,
......
......@@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
#if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
......@@ -362,13 +363,15 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre
if (initializer.IsKind(SyntaxKind.SwitchExpression))
{
// We compare the variable declaration type to each arm's type to see if there is an exact match, or if the
// arm type inherits from the variable declaration type. If not, we must use the explicit type instead of var.
// arm type inherits from the variable declaration type. We also must verify that the arm types are all
// in the same line of inheritance. If not, we must use the explicit type instead of var.
// Even if 'true' is returned from this method, it is not guaranteed that we can use var. Further checks should occur
// after this method is called, such as checking if multiple implicit coversions exist.
var declarationType = semanticModel.GetTypeInfo(typeName).Type;
var noValidTypeExpressions = true;
if (declarationType != null)
{
using var _ = ArrayBuilder<ITypeSymbol>.GetInstance(out var seenTypes);
foreach (var arm in ((SwitchExpressionSyntax)initializer).Arms)
{
var expression = arm.Expression;
......@@ -381,10 +384,43 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre
{
noValidTypeExpressions = false;
var expressionType = semanticModel.GetTypeInfo(expression).Type;
if (expressionType != null && !expressionType.InheritsFromOrEquals(declarationType))
if (expressionType == null)
{
continue;
}
if (!expressionType.InheritsFromOrEquals(declarationType))
{
return true;
}
// All arms must be in the same direct line of inheritance.
// e.g. Given the tree:
// C
// / \
// A B
//
// We cannot substitute var for 'x' in the following switch expression,
// as it will introduce a compiler error.
// C x = i switch
// {
// 0 => new A(),
// 1 => new B(),
// _ => throw new ArgumentException(),
// };
if (expressionType.Equals(declarationType) || seenTypes.Contains(expressionType))
{
continue;
}
var invalidType = seenTypes.Any(
t => !t.InheritsFromOrEquals(expressionType) && !expressionType.InheritsFromOrEquals(t));
if (invalidType)
{
return true;
}
seenTypes.Add(expressionType);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册