Skip to content
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

Merged
merged 6 commits into from
Apr 2, 2020

Conversation

jcouv
Copy link
Member

@jcouv jcouv commented Apr 1, 2020

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

@jcouv jcouv requested a review from a team as a code owner April 1, 2020 22:33
@jcouv jcouv self-assigned this Apr 1, 2020
@jcouv jcouv added the Area-IDE label Apr 1, 2020
@@ -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.
Copy link
Member Author

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

Copy link
Contributor

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.

Copy link
Member

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?

Copy link
Member

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.

Copy link
Member Author

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:
Copy link
Member Author

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

Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

@cston cston Apr 1, 2020

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)

Copy link
Member

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.
Copy link
Member Author

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

Copy link
Member

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)
Copy link
Member Author

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.

Copy link
Member

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);
Copy link
Member

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"); :)

@CyrusNajmabadi
Copy link
Member

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.

Copy link
Member

@CyrusNajmabadi CyrusNajmabadi left a 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.

Copy link
Member

@jasonmalinowski jasonmalinowski left a 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)
Copy link
Member

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]
Copy link
Member

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?

Copy link
Member Author

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.

Copy link
Member

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:
Copy link
Member

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?

@jcouv
Copy link
Member Author

jcouv commented Apr 2, 2020

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.

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.
Thanks

@jcouv jcouv requested a review from a team as a code owner April 2, 2020 05:34
@jcouv
Copy link
Member Author

jcouv commented Apr 2, 2020

Added tests for classification as keywords (conditionally on semantic model) and corresponding fix. Thanks @jasonmalinowski, I had not noticed the colorization difference with int in IDE.

image

@jcouv
Copy link
Member Author

jcouv commented Apr 2, 2020

@CyrusNajmabadi @mavasani @jasonmalinowski I added filtering for the attribute and fixed classification.


interface IInterface
{
[return: System.Runtime.CompilerServices.NativeInteger(new[] { true, true })]
Copy link
Member

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.

Copy link
Member Author

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)

Copy link
Member

@jasonmalinowski jasonmalinowski left a 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]
Copy link
Member

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 = @"
Copy link
Member

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:

[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.

@jcouv
Copy link
Member Author

jcouv commented Apr 2, 2020

Filed #43028 for MetadataAsSource issue.

There's a way to have this generate a proper metadata reference

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.

@jcouv jcouv merged commit cdafef6 into dotnet:features/NativeInt Apr 2, 2020
@jcouv jcouv deleted the nint-syntax branch April 2, 2020 18:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants