-
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
Bind native integers in cref #61431
Bind native integers in cref #61431
Changes from 3 commits
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 |
---|---|---|
|
@@ -145,11 +145,13 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N | |
|
||
int arity; | ||
string memberName; | ||
string memberNameText; | ||
|
||
if (nameSyntax != null) | ||
{ | ||
arity = nameSyntax.Arity; | ||
memberName = nameSyntax.Identifier.ValueText; | ||
memberNameText = nameSyntax.Identifier.Text; | ||
} | ||
else | ||
{ | ||
|
@@ -161,7 +163,7 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N | |
containerOpt = BindNamespaceOrTypeSymbolInCref(syntax.Name); | ||
|
||
arity = 0; | ||
memberName = WellKnownMemberNames.InstanceConstructorName; | ||
memberName = memberNameText = WellKnownMemberNames.InstanceConstructorName; | ||
} | ||
|
||
if (string.IsNullOrEmpty(memberName)) | ||
|
@@ -170,7 +172,7 @@ private ImmutableArray<Symbol> BindNameMemberCref(NameMemberCrefSyntax syntax, N | |
return ImmutableArray<Symbol>.Empty; | ||
} | ||
|
||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); | ||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText, arity, syntax.Parameters != null, diagnostics); | ||
|
||
if (sortedSymbols.IsEmpty) | ||
{ | ||
|
@@ -192,7 +194,7 @@ private ImmutableArray<Symbol> BindIndexerMemberCref(IndexerMemberCrefSyntax syn | |
{ | ||
const int arity = 0; | ||
|
||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, WellKnownMemberNames.Indexer, arity, syntax.Parameters != null, diagnostics); | ||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, WellKnownMemberNames.Indexer, memberNameText: WellKnownMemberNames.Indexer, arity, syntax.Parameters != null, diagnostics); | ||
|
||
if (sortedSymbols.IsEmpty) | ||
{ | ||
|
@@ -240,7 +242,7 @@ private ImmutableArray<Symbol> BindOperatorMemberCref(OperatorMemberCrefSyntax s | |
return ImmutableArray<Symbol>.Empty; | ||
} | ||
|
||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); | ||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText: memberName, arity, syntax.Parameters != null, diagnostics); | ||
|
||
if (sortedSymbols.IsEmpty) | ||
{ | ||
|
@@ -286,7 +288,7 @@ private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperat | |
memberName = WellKnownMemberNames.ExplicitConversionName; | ||
} | ||
|
||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, arity, syntax.Parameters != null, diagnostics); | ||
ImmutableArray<Symbol> sortedSymbols = ComputeSortedCrefMembers(syntax, containerOpt, memberName, memberNameText: memberName, arity, syntax.Parameters != null, diagnostics); | ||
|
||
if (sortedSymbols.IsEmpty) | ||
{ | ||
|
@@ -324,17 +326,18 @@ private ImmutableArray<Symbol> BindConversionOperatorMemberCref(ConversionOperat | |
/// <remarks> | ||
/// Never returns null. | ||
/// </remarks> | ||
private ImmutableArray<Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol? containerOpt, string memberName, int arity, bool hasParameterList, BindingDiagnosticBag diagnostics) | ||
private ImmutableArray<Symbol> ComputeSortedCrefMembers(CSharpSyntaxNode syntax, NamespaceOrTypeSymbol? containerOpt, string memberName, string memberNameText, int arity, bool hasParameterList, BindingDiagnosticBag diagnostics) | ||
{ | ||
CompoundUseSiteInfo<AssemblySymbol> useSiteInfo = GetNewCompoundUseSiteInfo(diagnostics); | ||
var result = ComputeSortedCrefMembers(containerOpt, memberName, arity, hasParameterList, ref useSiteInfo); | ||
var result = ComputeSortedCrefMembers(containerOpt, memberName, memberNameText, arity, hasParameterList, syntax, diagnostics, ref useSiteInfo); | ||
diagnostics.Add(syntax, useSiteInfo); | ||
return result; | ||
} | ||
|
||
private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol? containerOpt, string memberName, int arity, bool hasParameterList, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) | ||
private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol? containerOpt, string memberName, string memberNameText, int arity, bool hasParameterList, | ||
CSharpSyntaxNode syntax, BindingDiagnosticBag diagnostics, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) | ||
{ | ||
// Since we may find symbols without going through the lookup API, | ||
// Since we may find symbols without going through the lookup API, | ||
// expose the symbols via an ArrayBuilder. | ||
ArrayBuilder<Symbol> builder; | ||
{ | ||
|
@@ -349,8 +352,19 @@ private ImmutableArray<Symbol> ComputeSortedCrefMembers(NamespaceOrTypeSymbol? c | |
diagnose: false, | ||
useSiteInfo: ref useSiteInfo); | ||
|
||
if (memberNameText is "nint" or "nuint" | ||
&& containerOpt is null | ||
&& arity == 0 | ||
&& !hasParameterList | ||
&& !IsViableType(result)) | ||
{ | ||
result.Free(); // Won't be using this. | ||
CheckFeatureAvailability(syntax, MessageID.IDS_FeatureNativeInt, diagnostics); | ||
builder = ArrayBuilder<Symbol>.GetInstance(); | ||
builder.Add(this.GetSpecialType(memberName == "nint" ? SpecialType.System_IntPtr : SpecialType.System_UIntPtr, diagnostics, syntax).AsNativeInteger()); | ||
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. This should also likely be |
||
} | ||
// CONSIDER: Dev11 also checks for a constructor in the event of an ambiguous result. | ||
if (result.IsMultiViable) | ||
else if (result.IsMultiViable) | ||
{ | ||
// Dev11 doesn't consider members from System.Object when the container is an interface. | ||
// Lookup should already have dropped such members. | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10305,6 +10305,105 @@ public class C | |
comp.VerifyDiagnostics(); | ||
} | ||
|
||
[Theory] | ||
[InlineData("nint")] | ||
[InlineData("nuint")] | ||
[InlineData("System.IntPtr")] | ||
[InlineData("System.UIntPtr")] | ||
public void XmlDoc_Cref(string type) | ||
{ | ||
var src = $$""" | ||
/// <summary>Summary <see cref="{{type}}"/>.</summary> | ||
class C { } | ||
"""; | ||
var comp = CreateNumericIntPtrCompilation(src, references: new[] { MscorlibRefWithoutSharingCachedSymbols }, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal(type, cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var nintSymbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.True(nintSymbol.IsNativeIntegerType); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_Alias() | ||
{ | ||
var src = """ | ||
using @nint = System.String; | ||
|
||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
class C { } | ||
"""; | ||
|
||
var comp = CreateNumericIntPtrCompilation(src, references: new[] { MscorlibRefWithoutSharingCachedSymbols }, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.False(symbol.IsNativeIntegerType); | ||
Assert.Equal("System.String", symbol.ToTestDisplayString()); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_Member() | ||
{ | ||
var src = """ | ||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
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 think a test should be added where this is 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. That was a good scenario. Fixed a bug. Thanks! |
||
public class C | ||
{ | ||
/// <summary></summary> | ||
public int nint; | ||
} | ||
"""; | ||
|
||
var comp = CreateNumericIntPtrCompilation(src, references: new[] { MscorlibRefWithoutSharingCachedSymbols }, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.True(symbol.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. This appears to be a breaking change, as this code will currently reference the 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. Yes, that's an expected change. 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. My 2 cents: I find it understandable and reasonable to make a breaking change like this, especially since it only relates to xmldoc. But I find it odd that this will still work for types named 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. Also, with this break, I would expect to be able to add |
||
Assert.Equal("nint", symbol.ToTestDisplayString()); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_Member_Escaped() | ||
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. It would be a good idea to make this a |
||
{ | ||
var src = """ | ||
/// <summary>Summary <see cref="@nint"/>.</summary> | ||
public class C | ||
{ | ||
/// <summary></summary> | ||
public int nint; | ||
} | ||
"""; | ||
|
||
var comp = CreateNumericIntPtrCompilation(src, references: new[] { MscorlibRefWithoutSharingCachedSymbols }, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("@nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (IFieldSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.Equal("System.Int32 C.nint", symbol.ToTestDisplayString()); | ||
} | ||
|
||
private void VerifyNoNativeIntegerAttributeEmitted(CSharpCompilation comp) | ||
{ | ||
// PEVerify is skipped because it reports "Type load failed" because of the above corlib, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14813,5 +14813,154 @@ public static void M10(IntPtr{{s1Nullable}} x) { } | |
|
||
CompileAndVerify(comp, expectedOutput: "M1 M2 M3 M4 M5 M6 M7 M8 M9 M10"); | ||
} | ||
|
||
[Theory] | ||
[InlineData("nint")] | ||
[InlineData("nuint")] | ||
public void XmlDoc_Cref(string type) | ||
{ | ||
var src = $$""" | ||
/// <summary>Summary <see cref="{{type}}"/>.</summary> | ||
class C { } | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal(type, cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var nintSymbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.True(nintSymbol.IsNativeIntegerType); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_IntPtr() | ||
{ | ||
var src = """ | ||
/// <summary>Summary <see cref="System.IntPtr"/>.</summary> | ||
class C { } | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("System.IntPtr", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var nintSymbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.False(nintSymbol.IsNativeIntegerType); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_Alias() | ||
{ | ||
var src = """ | ||
using @nint = System.String; | ||
|
||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
class C { } | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.False(symbol.IsNativeIntegerType); | ||
Assert.Equal("System.String", symbol.ToTestDisplayString()); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_Member() | ||
{ | ||
var src = """ | ||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
public class C | ||
{ | ||
/// <summary></summary> | ||
public int nint; | ||
} | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.True(symbol.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. 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 short, what cases does the 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. See The 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. Thanks. Given that |
||
Assert.Equal("nint", symbol.ToTestDisplayString()); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_NamedType() | ||
{ | ||
var src = """ | ||
interface @nint { } | ||
|
||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
class C { } | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics(); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (INamedTypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.False(symbol.IsNativeIntegerType); | ||
Assert.Equal("nint", symbol.ToTestDisplayString()); | ||
Assert.Equal(TypeKind.Interface, symbol.TypeKind); | ||
} | ||
|
||
[Fact] | ||
public void XmlDoc_Cref_TypeParameter() | ||
{ | ||
var src = """ | ||
struct Outer<@nint> | ||
{ | ||
/// <summary>Summary <see cref="nint"/>.</summary> | ||
class C { } | ||
} | ||
"""; | ||
|
||
var comp = CreateCompilation(src, parseOptions: TestOptions.RegularWithDocumentationComments); | ||
comp.VerifyDiagnostics( | ||
// (3,37): warning CS1723: XML comment has cref attribute 'nint' that refers to a type parameter | ||
// /// <summary>Summary <see cref="nint"/>.</summary> | ||
Diagnostic(ErrorCode.WRN_BadXMLRefTypeVar, "nint").WithArguments("nint").WithLocation(3, 37) | ||
); | ||
|
||
var tree = comp.SyntaxTrees.Single(); | ||
var docComments = tree.GetCompilationUnitRoot().DescendantTrivia().Select(trivia => trivia.GetStructure()).OfType<DocumentationCommentTriviaSyntax>(); | ||
var cref = docComments.First().DescendantNodes().OfType<XmlCrefAttributeSyntax>().First().Cref; | ||
Assert.Equal("nint", cref.ToString()); | ||
|
||
var model = comp.GetSemanticModel(tree, ignoreAccessibility: false); | ||
var symbol = (ITypeSymbol)model.GetSymbolInfo(cref).Symbol; | ||
Assert.False(symbol.IsNativeIntegerType); | ||
Assert.Equal("nint", symbol.ToTestDisplayString()); | ||
Assert.Equal(TypeKind.TypeParameter, symbol.TypeKind); | ||
} | ||
} | ||
} |
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.
Are we testing members other than types? For instance: