提交 25fb200d 编写于 作者: C CyrusNajmabadi 提交者: GitHub

Merge pull request #18557 from kcnygaard/fix-18556

Fixes #18556 - Invalid code when implementing interface through explicitly-implemented property
......@@ -2349,6 +2349,56 @@ public int M2()
index: 1);
}
[WorkItem(18556, "https://github.com/dotnet/roslyn/issues/18556")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
public async Task TestImplementInterfaceThroughExplicitProperty()
{
await TestActionCountAsync(
@"interface IA
{
IB B { get; }
}
interface IB
{
int M();
}
class AB : IA, [|IB|]
{
IB IA.B => null;
}",
count: 3);
await TestWithAllCodeStyleOptionsOffAsync(
@"interface IA
{
IB B { get; }
}
interface IB
{
int M();
}
class AB : IA, [|IB|]
{
IB IA.B => null;
}",
@"interface IA
{
IB B { get; }
}
interface IB
{
int M();
}
class AB : IA, [|IB|]
{
IB IA.B => null;
public int M()
{
return ((IA)this).B.M();
}
}", index: 1);
}
[WorkItem(768799, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/768799")]
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)]
public async Task TestNoImplementThroughIndexer()
......
......@@ -159,8 +159,8 @@ protected override Task<Document> GetChangedDocumentAsync(CancellationToken canc
public Task<Document> GetUpdatedDocumentAsync(CancellationToken cancellationToken)
{
var unimplementedMembers = Explicitly
? State.UnimplementedExplicitMembers
var unimplementedMembers = Explicitly
? State.UnimplementedExplicitMembers
: State.UnimplementedMembers;
return GetUpdatedDocumentAsync(Document, unimplementedMembers, State.ClassOrStructType, State.ClassOrStructDecl, cancellationToken);
}
......@@ -441,14 +441,14 @@ private static bool IsUnexpressibleTypeParameter(ITypeParameterSymbol typeParame
return generateInvisibly ? accessor : null;
}
private SyntaxNode CreateThroughExpression(SyntaxGenerator factory)
private SyntaxNode CreateThroughExpression(SyntaxGenerator generator)
{
var through = ThroughMember.IsStatic
? GenerateName(factory, State.ClassOrStructType.IsGenericType)
: factory.ThisExpression();
? GenerateName(generator, State.ClassOrStructType.IsGenericType)
: generator.ThisExpression();
through = factory.MemberAccessExpression(
through, factory.IdentifierName(ThroughMember.Name));
through = generator.MemberAccessExpression(
through, generator.IdentifierName(ThroughMember.Name));
var throughMemberType = ThroughMember.GetMemberType();
if ((State.InterfaceTypes != null) && (throughMemberType != null))
......@@ -476,13 +476,32 @@ private SyntaxNode CreateThroughExpression(SyntaxGenerator factory)
// uncommon case and optimize for the common one - in other words, we only apply the cast
// in cases where we can unambiguously figure out which interface we are trying to implement.
var interfaceBeingImplemented = State.InterfaceTypes.SingleOrDefault();
if ((interfaceBeingImplemented != null) && (!throughMemberType.Equals(interfaceBeingImplemented)))
if (interfaceBeingImplemented != null)
{
through = factory.CastExpression(interfaceBeingImplemented,
through.WithAdditionalAnnotations(Simplifier.Annotation));
var facts = this.Document.GetLanguageService<ISyntaxFactsService>();
through = facts.Parenthesize(through);
if (!throughMemberType.Equals(interfaceBeingImplemented))
{
through = generator.CastExpression(interfaceBeingImplemented,
through.WithAdditionalAnnotations(Simplifier.Annotation));
}
else if (!ThroughMember.IsStatic &&
ThroughMember is IPropertySymbol throughMemberProperty &&
throughMemberProperty.ExplicitInterfaceImplementations.Any())
{
// If we are implementing through an explicitly implemented property, we need to cast 'this' to
// the explicitly implemented interface type before calling the member, as in:
// ((IA)this).Prop.Member();
//
var explicitlyImplementedProperty = throughMemberProperty.ExplicitInterfaceImplementations[0];
var explicitImplementationCast = generator.CastExpression(
explicitlyImplementedProperty.ContainingType,
generator.ThisExpression());
through = generator.MemberAccessExpression(explicitImplementationCast,
generator.IdentifierName(explicitlyImplementedProperty.Name));
through = through.WithAdditionalAnnotations(Simplifier.Annotation);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册