-
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
Changes from all commits
63455b8
d3de713
4ac5573
565f0c8
d0a4148
cdb15f3
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -149,6 +149,53 @@ public void Method1() | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
}"); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[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 commentThe 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
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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
namespace System.Runtime.CompilerServices | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[System.AttributeUsage(AttributeTargets.All)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public sealed class NativeIntegerAttribute : System.Attribute | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public NativeIntegerAttribute() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public NativeIntegerAttribute(bool[] flags) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Note: we're putting the attribute by hand to simulate metadata | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await TestWithAllCodeStyleOptionsOffAsync( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@"interface IInterface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[return: System.Runtime.CompilerServices.NativeInteger(new[] { true, true })] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(nint, nuint) Method(nint x, nuint x2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class Class : [|IInterface|] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}" + nativeIntegerAttributeDefinition, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@"using System; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
interface IInterface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[return: System.Runtime.CompilerServices.NativeInteger(new[] { true, true })] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
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 commentThe reason will be displayed to describe this comment to others. Learn more. Discussed and resolved offline. See comment above and in existing test ( |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
(nint, nuint) Method(nint x, nuint x2); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
class Class : IInterface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public (nint, nuint) Method(nint x, nuint x2) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
throw new NotImplementedException(); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
}" + nativeIntegerAttributeDefinition); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task TestMethodWithTuple() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
@@ -235,9 +282,10 @@ public sealed class TupleElementNamesAttribute : Attribute { } | |||||||||||||||||||||||||||||||||||||||||||||||||||||||
} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
"; | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), Test.Utilities.CompilerTrait(Test.Utilities.CompilerFeature.Tuples)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
[Fact, Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface), CompilerTrait(CompilerFeature.Tuples)] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
public async Task TupleWithNamesInMethod() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
// Note: we're putting the attribute by hand to simulate metadata | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
await TestWithAllCodeStyleOptionsOffAsync( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
@"interface IInterface | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -31,6 +31,54 @@ I am the very model of a modern major general. | |
Assert.Equal(expectedXMLFragment, extractedXMLFragment); | ||
} | ||
|
||
[Fact, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] | ||
[WorkItem(42986, "https://github.com/dotnet/roslyn/issues/42986")] | ||
public async Task TestNativeInteger() | ||
{ | ||
var metadataSource = "public class C { public nint i; public nuint i2; }"; | ||
var symbolName = "C"; | ||
|
||
await GenerateAndVerifySourceAsync(metadataSource, symbolName, LanguageNames.CSharp, languageVersion: "Preview", metadataLanguageVersion: "Preview", | ||
expected: $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null | ||
// {CodeAnalysisResources.InMemoryAssembly} | ||
#endregion | ||
|
||
using System; | ||
using System.Runtime.CompilerServices; | ||
|
||
public class [|C|] | ||
{{ | ||
[NativeIntegerAttribute] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more. @jcouv That's another bug. 😄 |
||
public nint i; | ||
[NativeIntegerAttribute] | ||
public nuint i2; | ||
|
||
public C(); | ||
}}"); | ||
} | ||
|
||
[Fact, Trait(Traits.Feature, Traits.Features.MetadataAsSource)] | ||
public async Task TestTupleWithNames() | ||
{ | ||
var metadataSource = "public class C { public (int a, int b) t; }"; | ||
var symbolName = "C"; | ||
|
||
await GenerateAndVerifySourceAsync(metadataSource, symbolName, LanguageNames.CSharp, | ||
expected: $@"#region {FeaturesResources.Assembly} ReferencedAssembly, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null | ||
// {CodeAnalysisResources.InMemoryAssembly} | ||
#endregion | ||
|
||
using System.Runtime.CompilerServices; | ||
|
||
public class [|C|] | ||
{{ | ||
[TupleElementNames(new[] {{ ""a"", ""b"" }})] | ||
public (int a, int b) t; | ||
|
||
public C(); | ||
}}"); | ||
} | ||
|
||
[Fact, WorkItem(26605, "https://github.com/dotnet/roslyn/issues/26605")] | ||
public async Task TestValueTuple() | ||
{ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -291,6 +291,11 @@ public static bool IsNumericType([NotNullWhen(returnValue: true)] this ITypeSymb | |
case SpecialType.System_Single: | ||
case SpecialType.System_Double: | ||
case SpecialType.System_Decimal: | ||
#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 commentThe 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 commentThe 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 commentThe 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 commentThe reason will be displayed to describe this comment to others. Learn more.
In reply to: 401951786 [](ancestors = 401951786) There was a problem hiding this comment. Choose a reason for hiding this commentThe 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? |
||
#endif | ||
return true; | ||
} | ||
} | ||
|
@@ -393,6 +398,11 @@ public static bool IsSpecialType([NotNullWhen(returnValue: true)] this ITypeSymb | |
case SpecialType.System_UInt16: | ||
case SpecialType.System_UInt32: | ||
case SpecialType.System_UInt64: | ||
#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 symbol.IsNativeIntegerType: | ||
case SpecialType.System_UIntPtr when symbol.IsNativeIntegerType: | ||
#endif | ||
return true; | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,10 +4,10 @@ | |
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Diagnostics; | ||
using System.Linq; | ||
using System.Threading; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
using Microsoft.CodeAnalysis.FindSymbols.Finders; | ||
using Microsoft.CodeAnalysis.Options; | ||
using Microsoft.CodeAnalysis.Shared.Extensions; | ||
using Microsoft.CodeAnalysis.Simplification; | ||
|
@@ -71,6 +71,7 @@ public override TypeSyntax VisitArrayType(IArrayTypeSymbol symbol) | |
underlyingType = innerArray.ElementType; | ||
|
||
#if !CODE_STYLE // TODO: Remove the #if once NullableAnnotation is available. | ||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
if (underlyingType.NullableAnnotation == NullableAnnotation.Annotated) | ||
{ | ||
// If the inner array we just moved to is also nullable, then | ||
|
@@ -107,6 +108,7 @@ public override TypeSyntax VisitArrayType(IArrayTypeSymbol symbol) | |
TypeSyntax arrayTypeSyntax = SyntaxFactory.ArrayType(elementTypeSyntax, ranks.ToSyntaxList()); | ||
|
||
#if !CODE_STYLE // TODO: Remove the #if once NullableAnnotation is available. | ||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
if (symbol.NullableAnnotation == NullableAnnotation.Annotated) | ||
{ | ||
arrayTypeSyntax = SyntaxFactory.NullableType(arrayTypeSyntax); | ||
|
@@ -188,6 +190,14 @@ 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 commentThe 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 commentThe 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 :) |
||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
if (symbol.IsNativeIntegerType) | ||
{ | ||
return SyntaxFactory.IdentifierName(symbol.SpecialType == SpecialType.System_IntPtr ? "nint" : "nuint"); | ||
} | ||
#endif | ||
|
||
if (symbol.IsNullable()) | ||
{ | ||
// Can't have a nullable of a pointer type. i.e. "int*?" is illegal. | ||
|
@@ -260,6 +270,7 @@ public override TypeSyntax VisitNamedType(INamedTypeSymbol symbol) | |
} | ||
|
||
#if !CODE_STYLE // TODO: Remove the #if once NullableAnnotation is available. | ||
// https://github.com/dotnet/roslyn/issues/41462 tracks adding this support | ||
if (symbol.NullableAnnotation == NullableAnnotation.Annotated) | ||
{ | ||
typeSyntax = AddInformationTo(SyntaxFactory.NullableType(typeSyntax), 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.
📝 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