-
Notifications
You must be signed in to change notification settings - Fork 4k
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
Adjust implement interface service to work with static abstract operators #53941
Adjust implement interface service to work with static abstract operators #53941
Conversation
...ures/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.CodeAction_Method.cs
Outdated
Show resolved
Hide resolved
...ures/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.CodeAction_Method.cs
Outdated
Show resolved
Hide resolved
...ures/Core/Portable/ImplementInterface/AbstractImplementInterfaceService.CodeAction_Method.cs
Outdated
Show resolved
Hide resolved
…tInterfaceService.CodeAction_Method.cs Co-authored-by: CyrusNajmabadi <cyrus.najmabadi@gmail.com>
@CyrusNajmabadi This is ready for another look :) |
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] | ||
public async Task TestStaticAbstractInterfaceOperator_OnlyExplicitlyImplementable() | ||
{ | ||
await TestInRegularAndScriptAsync(@" |
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.
in the future, if your'e interested, it would be good to update these to be sdk style tests. that way we can validate if our fix produces errors :)
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'm working on this change for ImplementInterfaceTests in a separate branch.
|
||
abstract class C : ITest<C> | ||
{ | ||
public abstract static int operator -(C x); |
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'm curious. is this legal?
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.
Abstract statics are allowed only in interfaces
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.
Thanks for noting @CyrusNajmabadi @AlekseyTs
I'm curious whether the "Implement interface abstractly" should do nothing for the operator, or generate it without the "abstract" keyword?
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.
implement abstractly needs to take the code from uncompilable state to compilable, attempting for each member it needs to generate to make that abstract. If the member doesn't need to be generated, we should not generate it.
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.
@CyrusNajmabadi The member needs to be generated to be in a compilable state, but it cannot be generated abstractly.
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 do not believe there is away to implement a static member abstractly. So, if there are static abstract members in the interface, the option probably shouldn't be offered.
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.
The member needs to be generated to be in a compilable state, but it cannot be generated abstractly.
'GEnerate abstractly' means 'generate abstractly if possible'. If not possible, generate legally. This already occurs today where normal instance methods might cause errors if generated abstractly. In that case i believe we normally just generate explicitly.
End goal of this feature is always compilable code. The different user facing choices are about how we should generate when we have such flexibility while still ensuring compilable. If we are constrained, then we generate in whatever manner the constraints force.
src/Workspaces/CSharp/Portable/CodeGeneration/OperatorGenerator.cs
Outdated
Show resolved
Hide resolved
...rkspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/INamedTypeSymbolExtensions.cs
Outdated
Show resolved
Hide resolved
...rkspaces/SharedUtilitiesAndExtensions/Compiler/Core/Extensions/INamedTypeSymbolExtensions.cs
Show resolved
Hide 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.
Overall this looks good. Just some tiny questions/cleanup/requests.
Note that https://github.com/dotnet/roslyn/tree/features/StaticAbstractMembersInInterfaces has been merged to main, all related PRs should target main at this point. |
@@ -309,7 +309,7 @@ private string DetermineMemberName(ISymbol member, ArrayBuilder<ISymbol> impleme | |||
var generateInvisibleMember = GenerateInvisibleMember(member, memberName); | |||
memberName = generateInvisibleMember ? member.Name : memberName; | |||
|
|||
var generateAbstractly = !generateInvisibleMember && Abstractly; | |||
var generateAbstractly = !member.IsStatic && !generateInvisibleMember && Abstractly; |
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.
possibly explicitly comment that the language doesn't allow static abstract impls of interface methods.
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.
Added comment.
return SyntaxFactory.TokenList( | ||
SyntaxFactory.Token(SyntaxKind.PublicKeyword), | ||
SyntaxFactory.Token(SyntaxKind.StaticKeyword)); | ||
var tokens = ArrayBuilder<SyntaxToken>.GetInstance(); |
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 tokens = ArrayBuilder<SyntaxToken>.GetInstance(); | |
using var tokens = TemporaryArray<SyntaxToken>.Empty; |
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.
TemporaryArray is nice when we expect 4 or less items commonly :)
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.
Nice to know about TemporaryArray! Thanks. I applied the change.
CI failure is unrelated and was fixed in |
Thanks! |
Fixes #53927
Fixes #53925
Fixes #54328
Fixes #54327