提交 cd10095f 编写于 作者: N Neme12 提交者: Julien Couvreur

Fix for UseDeconstruction with default literal (#26140)

Merged on behalf of @Neme12. Thanks
上级 5e1c3344
......@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.UseDeconstruction;
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics;
......@@ -481,7 +482,7 @@ void M()
(string name, int age) [|person|] = default;
Console.WriteLine(person.name + "" "" + person.age);
}
}");
}", new TestParameters(parseOptions: CSharpParseOptions.Default.WithLanguageVersion(LanguageVersion.CSharp7_1)));
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseDeconstruction)]
......@@ -610,6 +611,28 @@ void M()
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseDeconstruction)]
public async Task TestWithTupleLiteralConversion()
{
await TestInRegularAndScriptAsync(
@"class C
{
void M()
{
(object name, double age) [|person|] = (null, 0);
Console.WriteLine(person.name + "" "" + person.age);
}
}",
@"class C
{
void M()
{
(object name, double age) = (null, 0);
Console.WriteLine(name + "" "" + age);
}
}");
}
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseDeconstruction)]
public async Task TestWithImplicitTupleConversion()
{
......
......@@ -125,10 +125,10 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
}
var local = (ILocalSymbol)semanticModel.GetDeclaredSymbol(declarator, cancellationToken);
var expressionType = semanticModel.GetTypeInfo(declarator.Initializer.Value, cancellationToken).Type;
var initializerConversion = semanticModel.GetConversion(declarator.Initializer.Value, cancellationToken);
return TryAnalyze(
semanticModel, local, variableDeclaration.Type, declarator.Identifier, expressionType,
semanticModel, local, variableDeclaration.Type, declarator.Identifier, initializerConversion,
variableDeclaration.Parent.Parent, out tupleType, out memberAccessExpressions, cancellationToken);
}
......@@ -140,10 +140,10 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
CancellationToken cancellationToken)
{
var local = semanticModel.GetDeclaredSymbol(forEachStatement, cancellationToken);
var elementType = semanticModel.GetForEachStatementInfo(forEachStatement).ElementType;
var elementConversion = semanticModel.GetForEachStatementInfo(forEachStatement).ElementConversion;
return TryAnalyze(
semanticModel, local, forEachStatement.Type, forEachStatement.Identifier, elementType,
semanticModel, local, forEachStatement.Type, forEachStatement.Identifier, elementConversion,
forEachStatement, out tupleType, out memberAccessExpressions, cancellationToken);
}
......@@ -152,7 +152,7 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
ILocalSymbol local,
TypeSyntax typeNode,
SyntaxToken identifier,
ITypeSymbol initializerType,
Conversion conversion,
SyntaxNode searchScope,
out INamedTypeSymbol tupleType,
out ImmutableArray<MemberAccessExpressionSyntax> memberAccessExpressions,
......@@ -171,9 +171,21 @@ private void AnalyzeNode(SyntaxNodeAnalysisContext context)
return false;
}
if (conversion.Exists &&
!conversion.IsIdentity &&
!conversion.IsTupleConversion &&
!conversion.IsTupleLiteralConversion)
{
// If there is any other conversion, we bail out because the source type might not be a tuple
// or it is a tuple but only thanks to target type inference, which won't occur in a deconstruction.
// Interesting case that illustrates this is initialization with a default literal:
// (int a, int b) t = default;
// This is classified as conversion.IsNullLiteral.
return false;
}
var type = semanticModel.GetTypeInfo(typeNode, cancellationToken).Type;
if (type == null || !type.IsTupleType ||
initializerType == null || !initializerType.IsTupleType)
if (type == null || !type.IsTupleType)
{
return false;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册