-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Support marking generated public APIs as experimental #82131
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
base: main
Are you sure you want to change the base?
Changes from all commits
96ef084
4250ca1
b3ed922
c690aa9
175b78d
21ed3b1
c74c04d
26a3976
1bbf7d9
bab901b
7f620b1
da1a98f
ab2f266
364ec38
1e4c68f
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 | ||||
|---|---|---|---|---|---|---|
|
|
@@ -11,6 +11,23 @@ This document provides guidance for thinking about language interactions and tes | |||||
| - BCL (including mono) and other customer impact | ||||||
| - Determinism | ||||||
| - Loading from metadata (source vs. loaded from metadata) | ||||||
| - VB/F# interop | ||||||
| - C++/CLI interop (particularly for metadata format changes, e.g. DIMs, static abstracts in interfaces, or generic attributes) | ||||||
| - Performance and stress testing | ||||||
| - Can build VS | ||||||
| - Check that `Obsolete` is honored for members used in binding/lowering | ||||||
| - LangVersion | ||||||
| - IL verification (file issue on `runtime` repo as needed and track [here](https://github.com/dotnet/roslyn/issues/22872)) | ||||||
| - Does the feature use cryptographic hashes in any way? (examples: metadata names of file-local types, extension types, assembly strong naming, PDB document table, etc.) | ||||||
| - Consider using non-cryptographic hash such as `XxHash128` instead. | ||||||
| - If you must use a cryptographic hash in the feature implementation, then use `SourceHashAlgorithms.Default`, and not any specific hash. | ||||||
| - A cryptographic hash must never be included in a public API name. Taking a change to the default crypto algorithm would then change public API surface, which would be enormously breaking. | ||||||
| - **DO NOT** allow using the value of a crypto hash in a field, method or type name | ||||||
| - **DO** allow using the value of a crypto hash in attribute or field values | ||||||
| - Any time the compiler reads in metadata containing crypto hashes, even if it's an attribute value, ensure the crypto hash algorithm name is included in the metadata (e.g. prefixing it to the hash value), so that it can be changed over time and the compiler can continue to read both metadata using both the old and new algorithms. | ||||||
|
|
||||||
| ## Public APIs | ||||||
|
|
||||||
| - Public compiler APIs (including semantic model and other APIs listed below): | ||||||
| - GetDeclaredSymbol | ||||||
| - GetEnclosingSymbol | ||||||
|
|
@@ -32,21 +49,10 @@ This document provides guidance for thinking about language interactions and tes | |||||
| - GetOperation (`IOperation`) | ||||||
| - GetCFG (`ControlFlowGraph`), including a scenario with some nested conditional | ||||||
| - DocumentationCommentId APIs | ||||||
| - VB/F# interop | ||||||
| - C++/CLI interop (particularly for metadata format changes, e.g. DIMs, static abstracts in interfaces, or generic attributes) | ||||||
| - Performance and stress testing | ||||||
| - Can build VS | ||||||
| - Check that `Obsolete` is honored for members used in binding/lowering | ||||||
| - LangVersion | ||||||
| - IL verification (file issue on `runtime` repo as needed and track [here](https://github.com/dotnet/roslyn/issues/22872)) | ||||||
|
|
||||||
| - Does the feature use cryptographic hashes in any way? (examples: metadata names of file-local types, extension types, assembly strong naming, PDB document table, etc.) | ||||||
| - Consider using non-cryptographic hash such as `XxHash128` instead. | ||||||
| - If you must use a cryptographic hash in the feature implementation, then use `SourceHashAlgorithms.Default`, and not any specific hash. | ||||||
| - A cryptographic hash must never be included in a public API name. Taking a change to the default crypto algorithm would then change public API surface, which would be enormously breaking. | ||||||
| - **DO NOT** allow using the value of a crypto hash in a field, method or type name | ||||||
| - **DO** allow using the value of a crypto hash in attribute or field values | ||||||
| - Any time the compiler reads in metadata containing crypto hashes, even if it's an attribute value, ensure the crypto hash algorithm name is included in the metadata (e.g. prefixing it to the hash value), so that it can be changed over time and the compiler can continue to read both metadata using both the old and new algorithms. | ||||||
| - All newly added APIs are experimental | ||||||
| - Tracking issue for marking APIs as non-experimental | ||||||
| - APIs are marked with `[Experimental(RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"link to tracking issue")]` | ||||||
|
Member
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 wouldn't expect backslashes in the URL
Suggested change
|
||||||
| - APIs have gone through API review | ||||||
|
|
||||||
| ## Type and members | ||||||
|
|
||||||
|
|
||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,19 +1,19 @@ | ||
| Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo.DisposeAwaitableInfo.get -> Microsoft.CodeAnalysis.CSharp.AwaitExpressionInfo | ||
| Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo.MoveNextAwaitableInfo.get -> Microsoft.CodeAnalysis.CSharp.AwaitExpressionInfo | ||
| Microsoft.CodeAnalysis.CSharp.SyntaxKind.WithElement = 9081 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.SyntaxKind.WithElement = 9081 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind | ||
| static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetAwaitExpressionInfo(this Microsoft.CodeAnalysis.SemanticModel? semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.LocalDeclarationStatementSyntax! awaitUsingDeclaration) -> Microsoft.CodeAnalysis.CSharp.AwaitExpressionInfo | ||
| static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetAwaitExpressionInfo(this Microsoft.CodeAnalysis.SemanticModel? semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.UsingStatementSyntax! awaitUsingStatement) -> Microsoft.CodeAnalysis.CSharp.AwaitExpressionInfo | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax![]! items) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken withKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken | ||
| Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithWithKeyword(Microsoft.CodeAnalysis.SyntaxToken withKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> Microsoft.CodeAnalysis.SyntaxNode? | ||
| override Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> void | ||
| override Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>! visitor) -> TResult? | ||
| static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax? argumentList = null) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.SyntaxToken withKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> void | ||
| virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> TResult? | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax | ||
|
Member
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. Should the SyntaxKind above bet considered experimental too? |
||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.AddArgumentListArguments(params Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentSyntax![]! items) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.ArgumentList.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken withKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithArgumentList(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken | ||
| [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.WithWithKeyword(Microsoft.CodeAnalysis.SyntaxToken withKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]override Microsoft.CodeAnalysis.CSharp.CSharpSyntaxRewriter.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> Microsoft.CodeAnalysis.SyntaxNode? | ||
| [RSEXPERIMENTAL006]override Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Accept(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! visitor) -> void | ||
| [RSEXPERIMENTAL006]override Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax.Accept<TResult>(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>! visitor) -> TResult? | ||
| [RSEXPERIMENTAL006]static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax? argumentList = null) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.WithElement(Microsoft.CodeAnalysis.SyntaxToken withKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ArgumentListSyntax! argumentList) -> Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! | ||
| [RSEXPERIMENTAL006]virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> void | ||
| [RSEXPERIMENTAL006]virtual Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor<TResult>.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> TResult? | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,6 +8,7 @@ | |
| <xs:complexType> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Base" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
|
Contributor
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.
Member
Author
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 is maintained manually. It predates my time here, and presumably provides completion for the XML structure in Syntax.xml. If we decide we don't want it, that's ok with me, but I think that should be a separate PR. For now, I'm going to keep this as is and update appropriately.
Member
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, it's used for that. I think the checker also uses this to validate the structure of the XML too? |
||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element maxOccurs="unbounded" name="AbstractNode"> | ||
|
|
@@ -34,6 +35,7 @@ | |
| </xs:sequence> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| <xs:attribute name="Optional" type="xs:boolean" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
|
|
@@ -60,6 +62,7 @@ | |
| </xs:sequence> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element minOccurs="0" name="Sequence"> | ||
|
|
@@ -83,6 +86,7 @@ | |
| </xs:sequence> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
|
|
@@ -95,6 +99,7 @@ | |
| </xs:sequence> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Base" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element maxOccurs="unbounded" name="Node"> | ||
|
|
@@ -131,6 +136,7 @@ | |
| <xs:attribute name="MinCount" type="xs:unsignedByte" use="optional" /> | ||
| <xs:attribute name="Optional" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="AllowTrailingSeparator" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element name="TypeComment"> | ||
|
|
@@ -170,6 +176,7 @@ | |
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="Override" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="Optional" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| <xs:element minOccurs="0" name="Sequence"> | ||
|
|
@@ -182,6 +189,7 @@ | |
| <xs:complexType> | ||
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
|
|
@@ -206,6 +214,7 @@ | |
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Type" type="xs:string" use="required" /> | ||
| <xs:attribute name="Override" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:sequence> | ||
|
|
@@ -220,6 +229,7 @@ | |
| <xs:attribute name="Name" type="xs:string" use="required" /> | ||
| <xs:attribute name="Base" type="xs:string" use="required" /> | ||
| <xs:attribute name="SkipConvenienceFactories" type="xs:boolean" use="optional" /> | ||
| <xs:attribute name="ExperimentalUrl" type="xs:string" use="optional" /> | ||
| </xs:complexType> | ||
| </xs:element> | ||
| </xs:choice> | ||
|
|
||
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.
Did you consider putting this into a
.globalconfigfile instead? Then we wouldn't need separate suppressions in source-generated files.