From 6215312905948a37859df795a2aa153275069868 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 03:08:29 +0000 Subject: [PATCH 1/2] Keep implicit Me receiver for extension calls inside a reduced extension access A reduced extension method access such as Distinct().ToList() was treated as type promotion, so the whole access was replaced by its receiver and the implicit Me of the inner Distinct() was never expanded, giving Enumerable.Distinct(). Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_019FEr8Ewvos6pJ4xv426Vsc --- CodeConverter/CSharp/VbNameExpander.cs | 6 ++++- .../MemberTests/ExtensionMethodTests.cs | 26 +++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/CodeConverter/CSharp/VbNameExpander.cs b/CodeConverter/CSharp/VbNameExpander.cs index c43c4c814..8f3697f36 100644 --- a/CodeConverter/CSharp/VbNameExpander.cs +++ b/CodeConverter/CSharp/VbNameExpander.cs @@ -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..5f8b7698f 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() { From f0e6d0971528a1674c3305ffa6ac20c5728faedb Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 10 Nov 2026 03:28:19 +0000 Subject: [PATCH 2/2] Treat interface receivers of reduced extensions as implicit Me receivers The enclosing-type check for a reduced extension used a base-class-only InheritsFromOrEquals, so extensions on interfaces such as IEnumerable(Of T).Distinct() inside a class deriving List(Of T) were not given Me. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_019FEr8Ewvos6pJ4xv426Vsc --- CodeConverter/CSharp/VbNameExpander.cs | 2 +- Tests/CSharp/MemberTests/ExtensionMethodTests.cs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CodeConverter/CSharp/VbNameExpander.cs b/CodeConverter/CSharp/VbNameExpander.cs index 8f3697f36..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); } /// diff --git a/Tests/CSharp/MemberTests/ExtensionMethodTests.cs b/Tests/CSharp/MemberTests/ExtensionMethodTests.cs index 5f8b7698f..1e70b147e 100644 --- a/Tests/CSharp/MemberTests/ExtensionMethodTests.cs +++ b/Tests/CSharp/MemberTests/ExtensionMethodTests.cs @@ -44,12 +44,12 @@ Inherits List(Of Integer) Public Function Uniques() As List(Of Integer) Return Distinct().ToList() End Function -End Class", @" -using System.Collections.Generic; +End Class", @"using System.Collections.Generic; using System.Linq; public partial class MyList : List { + public List Uniques() { return this.Distinct().ToList();