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

Implicit var switch expression fix

上级 725e3fc4
...@@ -2735,5 +2735,35 @@ static void Main(string[] args) ...@@ -2735,5 +2735,35 @@ static void Main(string[] args)
}", }",
options: ImplicitTypeEverywhere()); 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 ...@@ -560,10 +560,7 @@ private static bool IsParamsArrayExpanded(SemanticModel semanticModel, SyntaxNod
} }
else 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 BaseArgumentListSyntax? argumentList = node switch
#pragma warning restore IDE0007 // Use implicit type
{ {
InvocationExpressionSyntax invocation => invocation.ArgumentList, InvocationExpressionSyntax invocation => invocation.ArgumentList,
ObjectCreationExpressionSyntax objectCreation => objectCreation.ArgumentList, ObjectCreationExpressionSyntax objectCreation => objectCreation.ArgumentList,
......
...@@ -15,6 +15,7 @@ ...@@ -15,6 +15,7 @@
using Microsoft.CodeAnalysis.Shared.Utilities; using Microsoft.CodeAnalysis.Shared.Utilities;
using Microsoft.CodeAnalysis.Simplification; using Microsoft.CodeAnalysis.Simplification;
using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Operations;
using Microsoft.CodeAnalysis.PooledObjects;
#if CODE_STYLE #if CODE_STYLE
using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions; using OptionSet = Microsoft.CodeAnalysis.Diagnostics.AnalyzerConfigOptions;
...@@ -362,13 +363,15 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre ...@@ -362,13 +363,15 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre
if (initializer.IsKind(SyntaxKind.SwitchExpression)) 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 // 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 // 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. // after this method is called, such as checking if multiple implicit coversions exist.
var declarationType = semanticModel.GetTypeInfo(typeName).Type; var declarationType = semanticModel.GetTypeInfo(typeName).Type;
var noValidTypeExpressions = true; var noValidTypeExpressions = true;
if (declarationType != null) if (declarationType != null)
{ {
using var _ = ArrayBuilder<ITypeSymbol>.GetInstance(out var seenTypes);
foreach (var arm in ((SwitchExpressionSyntax)initializer).Arms) foreach (var arm in ((SwitchExpressionSyntax)initializer).Arms)
{ {
var expression = arm.Expression; var expression = arm.Expression;
...@@ -381,10 +384,43 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre ...@@ -381,10 +384,43 @@ private static bool IsSwitchExpressionAndCannotUseVar(TypeSyntax typeName, Expre
{ {
noValidTypeExpressions = false; noValidTypeExpressions = false;
var expressionType = semanticModel.GetTypeInfo(expression).Type; var expressionType = semanticModel.GetTypeInfo(expression).Type;
if (expressionType != null && !expressionType.InheritsFromOrEquals(declarationType)) if (expressionType == null)
{
continue;
}
if (!expressionType.InheritsFromOrEquals(declarationType))
{ {
return true; 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.
先完成此消息的编辑!
想要评论请 注册