-
Notifications
You must be signed in to change notification settings - Fork 4.1k
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
Generate friendly syntax for nint/nuint #42999
Conversation
@@ -362,6 +362,62 @@ void Method(int? x) | |||
await TestInRegularAndScriptAsync(before, after, options: ExplicitTypeExceptWhereApparent()); | |||
} | |||
|
|||
#if !CODE_STYLE // TODO: Skipped tests in CodeStyle layer depend on new compiler API (IsNativeIntegerType) that is not available in CodeStyle layer. |
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 is a similar region below for tests involving new nullability APIs
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, yes this is a know drawback of shared code between CodeStyle package based on earlier CodeAnalysis version and Features layer based on latest Roslyn. I plan to bring this up for discussion at next IDE design meeting on how to handle these changes in future.
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.
can we explicitly update #41462 to mention nint/nuint?
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.
it can link to this pr btw.
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 a note in #41462 with link to this PR
#if !CODE_STYLE // TODO: Remove the #if once IsNativeIntegerType is available. | ||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
case SpecialType.System_IntPtr when type.IsNativeIntegerType: | ||
case SpecialType.System_UIntPtr when type.IsNativeIntegerType: |
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 not sure how to cover those cases, but made the change opportunistically anyway
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.
interesting that it's not a special SpecialType. i.e. why not SpecialType.Nint?
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'll let @cston answer for design of nint type symbol.
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.
SpecialType
has a very specific definition, and it did not seem appropriate to change that. See SpecialType.cs.
In reply to: 401951786 [](ancestors = 401951786)
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.
@cston As a consumer of the API, how does that specific definition make sense? This feels like an implementation detail leaking in some way?
@@ -188,6 +188,24 @@ private TypeSyntax TryCreateSpecializedNamedTypeSyntax(INamedTypeSymbol symbol) | |||
return CreateTupleTypeSyntax(symbol); | |||
} | |||
|
|||
#if !CODE_STYLE // TODO: Remove the #if once IsNativeIntegerType is available. |
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 is a similar region below for tests involving new nullability APIs
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.
note: given the redundancy in checks in these places, IDE will likely just have an extension of IsNint and IsNuint since really, that's what we want to ask :)
|
||
class Class : IInterface | ||
{ | ||
public (nint, nuint) Method(nint x, nuint x2) |
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 expected we would produce attribute here (I saw logic to remove attribute in implemented interfaces, see AttributesToRemove
) and I would have to filter the NativeIntegerAttribute
. But it seems to be working okay as-is.
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.
@jcouv Are the attributes only included if we're reading from metadata? I believe we have tests that test that case too. We get bitten by this.
Debug.Assert(symbol.SpecialType == SpecialType.System_UIntPtr); | ||
name = "nuint"; | ||
} | ||
return SyntaxFactory.IdentifierName(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.
honestly, i'm ok with return SyntaxFactory.IdentifierName(symbol.SpecialType == SpecialType.System_IntPtr ? "nint" : "nuint");
:)
So overall feedback is that i'm fine with this for now. one issue is that this will generate nint/nuint in projects that don't support that. i'm not a fan of that, but i recognize it would be a bunch of work to theread through the options from all the callers to here to support doing the right thing. GIven that this is a niche feature and will likel be used primarily in projects all targetting new C#, i think this is an acceptable place to merge. |
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.
Approving now. LMK if you make any major changes that i should rereview.
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.
Looks like this isn't doing dropping of the attributes when it should. I suspect the "implement interface" case does work which was surprising because the attributes are only appearing in PE-imported symbols, not ones from source.
|
||
class Class : IInterface | ||
{ | ||
public (nint, nuint) Method(nint x, nuint x2) |
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.
@jcouv Are the attributes only included if we're reading from metadata? I believe we have tests that test that case too. We get bitten by this.
|
||
public class [|C|] | ||
{{ | ||
[NativeIntegerAttribute] |
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.
We should be dropping these, right?
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 don't think so. Notice the test below for tuples which I included for reference.
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.
@jcouv That's another bug. 😄
#if !CODE_STYLE // TODO: Remove the #if once IsNativeIntegerType is available. | ||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
case SpecialType.System_IntPtr when type.IsNativeIntegerType: | ||
case SpecialType.System_UIntPtr when type.IsNativeIntegerType: |
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.
@cston As a consumer of the API, how does that specific definition make sense? This feels like an implementation detail leaking in some way?
I couldn't find a test that actually uses metadata, but we have a test that simulates it (the only test I could find that breaks when removing the filtering logic). I did the same here and added the filtering logic for NativeIntegerAttribute as well. |
Added tests for classification as keywords (conditionally on semantic model) and corresponding fix. Thanks @jasonmalinowski, I had not noticed the colorization difference with |
@CyrusNajmabadi @mavasani @jasonmalinowski I added filtering for the attribute and fixed classification. |
|
||
interface IInterface | ||
{ | ||
[return: System.Runtime.CompilerServices.NativeInteger(new[] { true, true })] |
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.
[return: System.Runtime.CompilerServices.NativeInteger(new[] { true, true })] [](start = 4, length = 77)
Does this test involve metadata? If not, the attribute definition and explicit attributes are not needed.
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.
Discussed and resolved offline. See comment above and in existing test (// Note: we're putting the attribute by hand to simulate metadata
)
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.
Looks better but as called out the attributes appearing in Metadata as Source is a bug, and the tuple name situation is also a bug. 😄
|
||
public class [|C|] | ||
{{ | ||
[NativeIntegerAttribute] |
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.
@jcouv That's another bug. 😄
[WorkItem(42986, "https://github.com/dotnet/roslyn/issues/42986")] | ||
public async Task TestMethodWithNativeIntegers() | ||
{ | ||
var nativeIntegerAttributeDefinition = @" |
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's a way to have this generate a proper metadata reference:
roslyn/src/EditorFeatures/CSharpTest/ImplementInterface/ImplementInterfaceTests.cs
Lines 436 to 462 in cdb15f3
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] | |
public async Task NoNullableAttributesInMethodFromMetadata() | |
{ | |
var initial = @" | |
<Workspace> | |
<Project Language=""C#"" AssemblyName=""Assembly1"" CommonReferences=""true""> | |
<MetadataReferenceFromSource Language=""C#"" CommonReferences=""true""> | |
<Document> | |
#nullable enable | |
public interface IInterface | |
{ | |
void M(string? s1, string s2); | |
string this[string? s1, string s2] { get; set; } | |
} | |
</Document> | |
</MetadataReferenceFromSource> | |
<Document> | |
#nullable enable | |
using System; | |
class C : [|IInterface|] | |
{ | |
}</Document> | |
</Project> | |
</Workspace>"; |
That way you can just use the actual feature syntax in the reference, which also means you won't have any issues if this isn't quite expressing reality.
Filed #43028 for MetadataAsSource issue.
Thanks. I missed that trick. I'll stick with current approach for now because trying to get this in so we can merge the feature branch in. Test tweak doesn't seem blocker. |
Fixes #42986
Also fixes classification for
nint/nuint
(should be a keyword when bound as native integers)Taggging @jasonmalinowski @CyrusNajmabadi @mavasani for review.
Tagging @cston FYI
Relates to #38821