-
Notifications
You must be signed in to change notification settings - Fork 4.1k
Extensions: allow cref references to extension members #78735
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
@@ -181,7 +181,7 @@ public override object VisitNamedType(NamedTypeSymbol symbol, StringBuilder buil | |||
builder.Append('.'); | |||
} | |||
|
|||
builder.Append(symbol.IsExtension ? symbol.ExtensionName : symbol.Name); | |||
builder.Append(symbol.IsExtension ? escape(symbol.ExtensionName) : symbol.Name); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
📝 I debated whether to escape here, or push that responsibility to the caller of DocumentationCommentIDVisitor
. What do you think? #Resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since we replace <
/>
with {
/}
for type argument list below, it probably makes sense to avoid using them here as well.
<Field Name="DotToken" Type="SyntaxToken"> | ||
<Kind Name="DotToken"/> | ||
</Field> | ||
<Field Name="Member" Type="MemberCrefSyntax"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
} | ||
|
||
SyntaxToken dotToken = EatToken(SyntaxKind.DotToken); | ||
MemberCrefSyntax member = ParseMemberCref(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
TypeArgumentListSyntax? extensionTypeArguments = syntax.TypeArgumentList; | ||
int extensionArity = extensionTypeArguments?.Arguments.Count ?? 0; | ||
sortedSymbols = computeSortedAndFilteredCrefExtensionMembers(namedContainer, simpleName.Identifier.ValueText, extensionArity, arity, extensionTypeArguments, diagnostics, syntax); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (sortedSymbols.IsDefaultOrEmpty) | ||
{ | ||
ambiguityWinner = null; | ||
return []; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refCustomModifiers: [], | ||
explicitInterfaceImplementations: []); | ||
|
||
ImmutableArray<ParameterSymbol> extensionParameterSymbols = syntax.Parameters is { } extensionParameterListSyntax ? BindCrefParameters(extensionParameterListSyntax, diagnostics) : default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
var constructedNested = (NamedTypeSymbol)ConstructWithCrefTypeParameters(extensionArity, extensionTypeArguments, nested); | ||
|
||
var candidateExtensionSignature = new SignatureOnlyMethodSymbol( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
ImmutableArray<ParameterSymbol> extensionParameterSymbols = syntax.Parameters is { } extensionParameterListSyntax ? BindCrefParameters(extensionParameterListSyntax, diagnostics) : default; | ||
|
||
var providedExtensionSignature = new SignatureOnlyMethodSymbol( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
refCustomModifiers: [], | ||
explicitInterfaceImplementations: []); | ||
|
||
ImmutableArray<ParameterSymbol> extensionParameterSymbols = syntax.Parameters is { } extensionParameterListSyntax ? BindCrefParameters(extensionParameterListSyntax, diagnostics) : default; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -357,6 +357,8 @@ internal static bool HasParameterList(CrefSyntax crefSyntax) | |||
return ((OperatorMemberCrefSyntax)crefSyntax).Parameters != null; | |||
case SyntaxKind.ConversionOperatorMemberCref: | |||
return ((ConversionOperatorMemberCrefSyntax)crefSyntax).Parameters != null; | |||
case SyntaxKind.ExtensionMemberCref: | |||
return HasParameterList(((ExtensionMemberCrefSyntax)crefSyntax).Member); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parameters on extension
are intentionally not considered here.
The value from HasParameterList
affects the result kind from GetCrefSymbolInfo
below, to report "ambiguous" vs. "overload resolution failure". In E.extension(int).M...
we only allow the last parameter list to be omitted, so the presence/absence of the parameter list on extension
is not relevant to was result kind we report.
N(SyntaxKind.CloseParenToken); | ||
} | ||
N(SyntaxKind.DotToken); | ||
N(SyntaxKind.ExtensionMemberCref); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -1915,7 +1915,10 @@ void I.M() { } | |||
comp.VerifyEmitDiagnostics( | |||
// (10,16): error CS0541: 'Extensions.extension(object).M()': explicit interface declaration can only be declared in a class, record, struct or interface | |||
// void I.M() { } | |||
Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("Extensions.extension(object).M()").WithLocation(10, 16)); | |||
Diagnostic(ErrorCode.ERR_ExplicitInterfaceImplementationInNonClassOrStruct, "M").WithArguments("Extensions.extension(object).M()").WithLocation(10, 16), | |||
// (10,16): error CS9282: Extension declarations can include only methods or properties |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
public void Cref_44() | ||
{ | ||
var src = """ | ||
/// <see cref="extension(int).M"/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/// <see cref="E.extension(int).M2"/> | ||
static class E | ||
{ | ||
extension(int i) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done with review pass (commit 1) |
Relates to test plan #76130
Review of public API: #78738