Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1741,8 +1741,7 @@ static class Test
[InlineData("object")]
[InlineData("int")]
public Task TestModernExtension_TypeParameter(string sourceType)
// Will work once we get an API from https://github.com/dotnet/roslyn/issues/80273
=> TestMissingAsync(
=> TestInRegularAndScriptAsync(
$$"""
namespace M
{
Expand All @@ -1756,6 +1755,34 @@ void X()
}
}

namespace N
{
static class Test
{
extension<T>(T t)
{
public void M1()
{
}
}
}
}
""",
$$"""
using N;

namespace M
{
class C
{
void X()
{
{{sourceType}} o = new();
[|o.M1();|]
}
}
}

namespace N
{
static class Test
Expand Down
14 changes: 2 additions & 12 deletions src/Features/Core/Portable/AddImport/SymbolReferenceFinder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Linq.Expressions;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageService;
Expand Down Expand Up @@ -616,21 +615,12 @@ private bool IsViableModernExtensionMember(
if (!member.ContainingType.IsExtension)
return false;

if (member.ContainingType.ExtensionParameter is not { Type: { } extensionParameterType })
return false;

if (!member.IsAccessibleWithin(_semanticModel.Compilation.Assembly))
return false;

// TODO: https://github.com/dotnet/roslyn/issues/80273
// There is not api yet to know for certain if a modern extension is compatible with a receiver type.
// For now, put in a poor man's approach for this.

receiver = receiver.OriginalDefinition;
extensionParameterType = extensionParameterType.OriginalDefinition;
var reducedMember = member.ReduceExtensionMember(receiver);

var conversion = _semanticModel.Compilation.ClassifyCommonConversion(receiver, extensionParameterType);
return conversion.Exists && conversion.IsImplicit;
return reducedMember != null;
}

private bool ExpressionBinds(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,4 +40,19 @@ public static DeclarationModifiers GetSymbolModifiers(this ISymbol symbol)
.WithIsRequired(symbol.IsRequired())
.WithPartial(symbol.IsPartial());
}

#if !ROSLYN_4_12_OR_LOWER
public static ISymbol? ReduceExtensionMember(this ISymbol? member, ITypeSymbol? receiverType)
{
if (member is null || receiverType is null)
return null;

return member switch
{
IPropertySymbol propertySymbol => propertySymbol.ReduceExtensionMember(receiverType),
IMethodSymbol method => method.ReduceExtensionMember(receiverType),
_ => null,
};
}
#endif
}
Loading