Skip to content

Commit 84c1b80

Browse files
Fixup add-using to support more modern extension cases
1 parent 2f9fb8d commit 84c1b80

File tree

3 files changed

+46
-14
lines changed

3 files changed

+46
-14
lines changed

src/EditorFeatures/CSharpTest/CodeActions/AddUsing/AddUsingTests_ExtensionMethods.cs

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1741,8 +1741,7 @@ static class Test
17411741
[InlineData("object")]
17421742
[InlineData("int")]
17431743
public Task TestModernExtension_TypeParameter(string sourceType)
1744-
// Will work once we get an API from https://github.com/dotnet/roslyn/issues/80273
1745-
=> TestMissingAsync(
1744+
=> TestInRegularAndScriptAsync(
17461745
$$"""
17471746
namespace M
17481747
{
@@ -1756,6 +1755,34 @@ void X()
17561755
}
17571756
}
17581757
1758+
namespace N
1759+
{
1760+
static class Test
1761+
{
1762+
extension<T>(T t)
1763+
{
1764+
public void M1()
1765+
{
1766+
}
1767+
}
1768+
}
1769+
}
1770+
""",
1771+
$$"""
1772+
using N;
1773+
1774+
namespace M
1775+
{
1776+
class C
1777+
{
1778+
void X()
1779+
{
1780+
{{sourceType}} o = new();
1781+
[|o.M1();|]
1782+
}
1783+
}
1784+
}
1785+
17591786
namespace N
17601787
{
17611788
static class Test

src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
using System.Collections.Generic;
99
using System.Collections.Immutable;
1010
using System.Linq;
11-
using System.Linq.Expressions;
1211
using System.Threading;
1312
using System.Threading.Tasks;
1413
using Microsoft.CodeAnalysis.LanguageService;
@@ -616,21 +615,12 @@ private bool IsViableModernExtensionMember(
616615
if (!member.ContainingType.IsExtension)
617616
return false;
618617

619-
if (member.ContainingType.ExtensionParameter is not { Type: { } extensionParameterType })
620-
return false;
621-
622618
if (!member.IsAccessibleWithin(_semanticModel.Compilation.Assembly))
623619
return false;
624620

625-
// TODO: https://github.com/dotnet/roslyn/issues/80273
626-
// There is not api yet to know for certain if a modern extension is compatible with a receiver type.
627-
// For now, put in a poor man's approach for this.
628-
629-
receiver = receiver.OriginalDefinition;
630-
extensionParameterType = extensionParameterType.OriginalDefinition;
621+
var reducedMember = member.ReduceExtensionMember(receiver);
631622

632-
var conversion = _semanticModel.Compilation.ClassifyCommonConversion(receiver, extensionParameterType);
633-
return conversion.Exists && conversion.IsImplicit;
623+
return reducedMember != null;
634624
}
635625

636626
private bool ExpressionBinds(

src/Workspaces/SharedUtilitiesAndExtensions/Workspace/Core/Extensions/ISymbolExtensions.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,19 @@ public static DeclarationModifiers GetSymbolModifiers(this ISymbol symbol)
4040
.WithIsRequired(symbol.IsRequired())
4141
.WithPartial(symbol.IsPartial());
4242
}
43+
44+
#if !ROSLYN_4_12_OR_LOWER
45+
public static ISymbol? ReduceExtensionMember(this ISymbol? member, ITypeSymbol? receiverType)
46+
{
47+
if (member is null || receiverType is null)
48+
return null;
49+
50+
return member switch
51+
{
52+
IPropertySymbol propertySymbol => propertySymbol.ReduceExtensionMember(receiverType),
53+
IMethodSymbol method => method.ReduceExtensionMember(receiverType),
54+
_ => null,
55+
};
56+
}
57+
#endif
4358
}

0 commit comments

Comments
 (0)