diff --git a/CodeConverter/CSharp/VbNameExpander.cs b/CodeConverter/CSharp/VbNameExpander.cs index c43c4c814..dcaf0d210 100644 --- a/CodeConverter/CSharp/VbNameExpander.cs +++ b/CodeConverter/CSharp/VbNameExpander.cs @@ -80,7 +80,7 @@ private static bool IsReceiverTypeOrDerivedTypeEnclosingType(SyntaxNode node, IM { var classType = (ITypeSymbol)node.GetEnclosingDeclaredTypeSymbol(semanticModel); - return classType.InheritsFromOrEquals(symbol.ReceiverType); + return classType.InheritsFromOrEquals(symbol.ReceiverType, includeInterfaces: true); } /// @@ -122,9 +122,13 @@ private static bool NameCanBeExpanded(SyntaxNode node) private static INamedTypeSymbol GetDefaultImplicitInstance(SimpleNameSyntax node, ISymbol symbol, SemanticModel semanticModel, CancellationToken cancellationToken = default) => IsQualifiableInstanceReference(symbol) && IsLeftMostQualifier(node) ? semanticModel.GetEnclosingSymbol(node.SpanStart, cancellationToken) : null; + /// + /// Reduced extension methods are never members of the qualifying type, but that's not type promotion. + /// Treating them as such replaces the whole access with its receiver, skipping the expansion of an implicit Me receiver within it. + /// private static bool IsTypePromotion(SyntaxNode node, ISymbol symbol, SemanticModel semanticModel) { - if (IsQualifiableInstanceReference(symbol) && node is MemberAccessExpressionSyntax maes && maes.Expression != null) { + if (!symbol.IsReducedExtension() && IsQualifiableInstanceReference(symbol) && node is MemberAccessExpressionSyntax maes && maes.Expression != null) { var qualifyingType = semanticModel.GetTypeInfo(maes.Expression).Type; return qualifyingType == null || !qualifyingType.ContainsMember(symbol); } diff --git a/Tests/CSharp/MemberTests/ExtensionMethodTests.cs b/Tests/CSharp/MemberTests/ExtensionMethodTests.cs index 56ea17f0d..1e70b147e 100644 --- a/Tests/CSharp/MemberTests/ExtensionMethodTests.cs +++ b/Tests/CSharp/MemberTests/ExtensionMethodTests.cs @@ -31,6 +31,32 @@ public static void TestMethod2Parameters(this string str, string other) }"); } + [Fact] + public async Task ImplicitMeExtensionCallKeepsReceiverAsync() + { + await TestConversionVisualBasicToCSharpAsync( + @"Imports System.Collections.Generic +Imports System.Linq + +Public Class MyList + Inherits List(Of Integer) + + Public Function Uniques() As List(Of Integer) + Return Distinct().ToList() + End Function +End Class", @"using System.Collections.Generic; +using System.Linq; + +public partial class MyList : List +{ + + public List Uniques() + { + return this.Distinct().ToList(); + } +}"); + } + [Fact] public async Task TestExtensionMethodWithExistingImportAsync() {