From 96ef084767b1a19a516d54b50edc8f69b6b6d938 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 23 Jan 2026 11:29:59 -0800 Subject: [PATCH 01/16] Support marking syntax node types and fields as experimental. --- .../Syntax.xml.Internal.Generated.cs | 1 + .../Syntax.xml.Main.Generated.cs | 1 + .../Syntax.xml.Syntax.Generated.cs | 1 + .../CSharp/Portable/Syntax/Syntax.xsd | 10 +++++++ .../Generated/Syntax.Test.xml.Generated.cs | 1 + .../InternalUtilities/RoslynExperiments.cs | 3 ++ .../CSharpSyntaxGenerator/Model/Field.cs | 3 ++ .../CSharpSyntaxGenerator/Model/TreeType.cs | 3 ++ .../CSharpSyntaxGenerator/SourceWriter.cs | 28 +++++++++++++++++++ .../CSharpSyntaxGenerator/TestWriter.cs | 1 + 10 files changed, 52 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 93bbb9d1eb3f1..4573efd993938 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index e8febb0d116fa..4a146fa899473 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index 15426d48b5bd3..34448dbdf06ab 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd b/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd index ef8ce1b6cf169..fb1d962edbba9 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd @@ -8,6 +8,7 @@ + @@ -34,6 +35,7 @@ + @@ -60,6 +62,7 @@ + @@ -83,6 +86,7 @@ + @@ -95,6 +99,7 @@ + @@ -131,6 +136,7 @@ + @@ -170,6 +176,7 @@ + @@ -182,6 +189,7 @@ + @@ -206,6 +214,7 @@ + @@ -220,6 +229,7 @@ + diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 54fecd24c24ff..074948639dcc5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -1,4 +1,5 @@ // +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; diff --git a/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs b/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs index 319732e193bbd..dedfdead59736 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs @@ -15,6 +15,9 @@ internal static class RoslynExperiments internal const string GeneratorHostOutputs = "RSEXPERIMENTAL004"; internal const string GeneratorHostOutputs_Url = "https://github.com/dotnet/roslyn/issues/74753"; + // The URL is customized per-api to point at the test plan for the feature + internal const string PreviewLanguageFeatureApi = "RSEXPERIMENTAL006"; + // Previously taken: RSEXPERIMENTAL003 - https://github.com/dotnet/roslyn/issues/73002 (SyntaxTokenParser) // Previously taken: RSEXPERIMENTAL005 - https://github.com/dotnet/roslyn/issues/77697 } diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs index dcdb02097f0cb..882fc42cdfd13 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs @@ -44,6 +44,9 @@ public class Field : TreeTypeChild [XmlAttribute] public string Type; + [XmlAttribute] + public string Experimental; + [XmlAttribute] public string Optional; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs index fce0006a516cc..7850cc737da3e 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs @@ -17,6 +17,9 @@ public class TreeType [XmlAttribute] public string Base; + [XmlAttribute] + public string Experimental; + [XmlAttribute] public string SkipConvenienceFactories; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs index 495b00d5d6af7..39eb1e503a050 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs @@ -26,11 +26,23 @@ private SourceWriter(TextWriter writer, Tree tree, CancellationToken cancellatio public static void WriteSyntax(TextWriter writer, Tree tree, CancellationToken cancellationToken = default) => new SourceWriter(writer, tree, cancellationToken).WriteSyntax(); + private static string QuoteString(string value) + => "@\"" + value.Replace("\"", "\"\"") + "\""; + + private void WriteExperimentalIfNeeded(string experimental) + { + if (!string.IsNullOrEmpty(experimental)) + { + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(experimental)})]"); + } + } + private void WriteFileHeader() { WriteLine("// "); WriteLine(); WriteLine("#nullable enable"); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using System;"); WriteLine("using System.Collections.Generic;"); @@ -702,6 +714,7 @@ private void WriteRedType(TreeType node) if (node is AbstractNode) { var nd = (AbstractNode)node; + WriteExperimentalIfNeeded(node.Experimental); WriteLine($"public abstract partial class {node.Name} : {node.Base}"); OpenBlock(); WriteLine($"internal {node.Name}(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)"); @@ -720,6 +733,7 @@ private void WriteRedType(TreeType node) var fieldType = GetRedFieldType(field); WriteLine(); WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); WriteLine($"{"public"} abstract {(IsNew(field) ? "new " : "")}{fieldType} {field.Name} {{ get; }}"); WriteLine($"public {node.Name} With{field.Name}({fieldType} {CamelCase(field.Name)}) => With{field.Name}Core({CamelCase(field.Name)});"); WriteLine($"internal abstract {node.Name} With{field.Name}Core({fieldType} {CamelCase(field.Name)});"); @@ -756,6 +770,7 @@ private void WriteRedType(TreeType node) { WriteLine(); WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); WriteLine($"{"public"} abstract {(IsNew(field) ? "new " : "")}{field.Type} {field.Name} {{ get; }}"); } @@ -818,6 +833,7 @@ private void WriteRedType(TreeType node) WriteComment($""); WriteComment($""); + WriteExperimentalIfNeeded(node.Experimental); WriteLine($"public sealed partial class {node.Name} : {node.Base}"); OpenBlock(); @@ -869,6 +885,7 @@ private void WriteRedType(TreeType node) if (field.Type == "SyntaxToken") { WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); Write($"public {OverrideOrNewModifier(field)}{GetRedPropertyType(field)} {field.Name}"); if (IsOptional(field)) { @@ -889,6 +906,7 @@ private void WriteRedType(TreeType node) else if (field.Type == "SyntaxList") { WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); WriteLine($"public {OverrideOrNewModifier(field)}SyntaxTokenList {field.Name}"); OpenBlock(); WriteLine("get"); @@ -901,6 +919,7 @@ private void WriteRedType(TreeType node) else { WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); Write($"public {OverrideOrNewModifier(field)}{GetRedPropertyType(field)} {field.Name}"); if (IsNodeList(field.Type)) @@ -942,6 +961,7 @@ private void WriteRedType(TreeType node) foreach (var field in valueFields) { WriteComment(field.PropertyComment, ""); + WriteExperimentalIfNeeded(field.Experimental); WriteLine($"{"public"} {OverrideOrNewModifier(field)}{field.Type} {field.Name} => ((InternalSyntax.{node.Name})this.Green).{field.Name};"); WriteLine(); } @@ -1088,6 +1108,7 @@ private void WriteRedVisitor(bool genericResult) WriteLine(); nWritten++; WriteComment($"Called when the visitor visits a {node.Name} node."); + WriteExperimentalIfNeeded(node.Experimental); WriteLine($"public virtual {(genericResult ? "TResult?" : "void")} Visit{StripPost(node.Name, "Syntax")}({node.Name} node) => this.DefaultVisit(node);"); } CloseBlock(); @@ -1161,6 +1182,7 @@ private void WriteRedWithMethods(Node node) } } + WriteExperimentalIfNeeded(field.Experimental); Write( $"public{(isNew ? " new " : " ")}{node.Name} With{StripPost(field.Name, "Opt")}({type} {CamelCase(field.Name)})" + " => Update("); @@ -1262,6 +1284,7 @@ private void WriteRedListHelperMethods(Node node, Field field) } } + WriteExperimentalIfNeeded(field.Experimental); WriteLine($"public{(isNew ? " new " : " ")}{node.Name} Add{field.Name}(params {argType}[] items) => With{StripPost(field.Name, "Opt")}(this.{field.Name}.AddRange(items));"); } @@ -1281,6 +1304,7 @@ private void WriteRedNestedListHelperMethods(Node node, Field field, Node refere } // AddBaseListTypes + WriteExperimentalIfNeeded(field.Experimental); Write($"public{(isNew ? " new " : " ")}{node.Name} Add{StripPost(field.Name, "Opt")}{referencedNodeField.Name}(params {argType}[] items)"); if (IsOptional(field)) @@ -1313,6 +1337,7 @@ private void WriteRedRewriter() if (nWritten > 0) WriteLine(); nWritten++; + WriteExperimentalIfNeeded(node.Experimental); WriteLine($"public override SyntaxNode? Visit{StripPost(node.Name, "Syntax")}({node.Name} node)"); if (node.Fields.Count == 0) @@ -1439,6 +1464,7 @@ private void WriteRedFactory(Node nd) WriteComment($"Creates a new {nd.Name} instance."); + WriteExperimentalIfNeeded(nd.Experimental); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); WriteRedFactoryParameters(nd); @@ -1624,6 +1650,7 @@ private void WriteRedFactoryWithNoAutoCreatableTokens(Node nd) this.WriteLine(); WriteComment($"Creates a new {nd.Name} instance."); + WriteExperimentalIfNeeded(nd.Experimental); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); Write(CommaJoin( nd.Kinds.Count > 1 ? "SyntaxKind kind" : "", @@ -1713,6 +1740,7 @@ private void WriteRedMinimalFactory(Node nd, bool withStringNames = false) } WriteComment($"Creates a new {nd.Name} instance."); + WriteExperimentalIfNeeded(nd.Experimental); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); Write(CommaJoin( nd.Kinds.Count > 1 ? "SyntaxKind kind" : "", diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs index 2a8a0f7a471e7..26e9b88ba94d1 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs @@ -24,6 +24,7 @@ public static void Write(TextWriter writer, Tree tree) private void WriteFile() { WriteLine("// "); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using Microsoft.CodeAnalysis.CSharp.Syntax;"); WriteLine("using Roslyn.Utilities;"); From 4250ca17e96f9dcda39e7a771e856cfe52a39d6c Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 23 Jan 2026 11:30:16 -0800 Subject: [PATCH 02/16] Mark collection expression nodes as experimental, suppress where necessary. --- ...CollectionInitializerDiagnosticAnalyzer.cs | 2 ++ .../CSharpCollectionExpressionRewriter.cs | 4 +++ .../Portable/Binder/Binder_Expressions.cs | 4 +++ .../Portable/BoundTree/BoundExpression.cs | 2 ++ .../Compilation/CSharpSemanticModel.cs | 6 ++++ .../Compilation/MemberSemanticModel.cs | 2 ++ .../Syntax.xml.Main.Generated.cs | 5 ++++ .../Syntax.xml.Syntax.Generated.cs | 1 + .../CSharp/Portable/PublicAPI.Unshipped.txt | 28 +++++++++---------- .../CSharp/Portable/Syntax/Syntax.xml | 2 +- ...ressionTests_WithElement_ArraysAndSpans.cs | 2 ++ ...ExpressionTests_WithElement_Constructor.cs | 2 ++ ...ectionExpressionTests_WithElement_Extra.cs | 2 ++ ...ionExpressionTests_WithElement_Nullable.cs | 2 ++ .../NamedParameterCompletionProvider.cs | 4 +++ .../WithElementSignatureHelpProvider.cs | 2 ++ .../Extensions/WithElementSyntaxExtensions.cs | 2 ++ 17 files changed, 57 insertions(+), 15 deletions(-) diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index 9177c39646466..9141a858474f3 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -74,7 +74,9 @@ static IEnumerable GetMatchElements(ImmutableArray match) { if (match.Node is ArgumentListSyntax argumentList) +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 return WithElement(argumentList.WithoutTrivia()); +#pragma warning restore RSEXPERIMENTAL006 var expression = (ExpressionSyntax)(object)match.Node; return match.UseSpread @@ -592,7 +594,9 @@ IEnumerable CreateElements( } else if (node is ArgumentListSyntax argumentList) { +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 yield return WithElement(argumentList.WithoutTrivia()); +#pragma warning restore RSEXPERIMENTAL006 } else { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 4be320e5531a5..33e064d8475ac 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -5346,7 +5346,9 @@ private BoundExpression BindCollectionExpression(CollectionExpressionSyntax synt var builder = ArrayBuilder.GetInstance(syntax.Elements.Count); foreach (var element in syntax.Elements) { +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 if (element is WithElementSyntax withElementSyntax) +#pragma warning restore RSEXPERIMENTAL006 { MessageID.IDS_FeatureCollectionExpressionArguments.CheckFeatureAvailability(diagnostics, syntax, withElementSyntax.WithKeyword.GetLocation()); @@ -5439,7 +5441,9 @@ static BoundNode bindSpreadElement(SpreadElementSyntax syntax, BindingDiagnostic static (BoundUnconvertedWithElement? withElement, BoundBadExpression? badExpression) bindWithElement( Binder @this, CollectionExpressionSyntax syntax, +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElementSyntax, +#pragma warning restore RSEXPERIMENTAL006 BindingDiagnosticBag diagnostics) { // Report a withElement that is not first. Note: for the purposes of error recovery and diagnostics diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs index 3c5ab45d8f194..468d2bc0fb760 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs @@ -23,7 +23,9 @@ public SimpleNameSyntax? InterceptableNameSyntax this.Syntax is InvocationExpressionSyntax or ConstructorInitializerSyntax or PrimaryConstructorBaseTypeSyntax { ArgumentList: { } } +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 or WithElementSyntax +#pragma warning restore RSEXPERIMENTAL006 or CollectionExpressionSyntax, $"Unexpected syntax kind for BoundCall: {this.Syntax.Kind()}"); diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index aec3389cb2741..5a5fa23c4867e 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Collections; @@ -122,7 +123,9 @@ internal static bool CanGetSemanticInfo(CSharpSyntaxNode node, bool allowNamedAr (node is ExpressionSyntax && (isSpeculative || allowNamedArgumentName || !SyntaxFacts.IsNamedArgumentName(node))) || (node is ConstructorInitializerSyntax or PrimaryConstructorBaseTypeSyntax +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 or WithElementSyntax +#pragma warning restore RSEXPERIMENTAL006 or AttributeSyntax or CrefSyntax); } @@ -657,6 +660,7 @@ private static SymbolInfo GetSymbolInfoFromSymbolOrNone(ITypeSymbol type) /// /// Returns what symbol(s), if any, the given 'with(...)' element syntax bound to in the program. /// + [Experimental(RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = "https://github.com/dotnet/roslyn/issues/80613")] internal SymbolInfo GetSymbolInfo(WithElementSyntax withElement, CancellationToken cancellationToken = default(CancellationToken)) { CheckSyntaxNode(withElement); @@ -5021,8 +5025,10 @@ private SymbolInfo GetSymbolInfoFromNode(SyntaxNode node, CancellationToken canc return this.GetSymbolInfo(orderingSyntax, cancellationToken); case PositionalPatternClauseSyntax ppcSyntax: return this.GetSymbolInfo(ppcSyntax, cancellationToken); +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 case WithElementSyntax withElement: return this.GetSymbolInfo(withElement, cancellationToken); +#pragma warning restore RSEXPERIMENTAL006 } return SymbolInfo.None; diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index 017ef8b8991be..e7d3531cc0138 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -2291,7 +2291,9 @@ protected internal virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo !(node is JoinIntoClauseSyntax) && !(node is QueryContinuationSyntax) && !(node is ConstructorInitializerSyntax) && +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 !(node is WithElementSyntax) && +#pragma warning restore RSEXPERIMENTAL006 !(node is PrimaryConstructorBaseTypeSyntax) && !(node is ArrowExpressionClauseSyntax) && !(node is PatternSyntax)) diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 4a146fa899473..048153abab86e 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -230,6 +230,7 @@ public partial class CSharpSyntaxVisitor public virtual TResult? VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a WithElementSyntax node. + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public virtual TResult? VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a QueryExpressionSyntax node. @@ -977,6 +978,7 @@ public partial class CSharpSyntaxVisitor public virtual void VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a WithElementSyntax node. + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public virtual void VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a QueryExpressionSyntax node. @@ -1723,6 +1725,7 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor public override SyntaxNode? VisitSpreadElement(SpreadElementSyntax node) => node.Update(VisitToken(node.OperatorToken), (ExpressionSyntax?)Visit(node.Expression) ?? throw new ArgumentNullException("expression")); + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public override SyntaxNode? VisitWithElement(WithElementSyntax node) => node.Update(VisitToken(node.WithKeyword), (ArgumentListSyntax?)Visit(node.ArgumentList) ?? throw new ArgumentNullException("argumentList")); @@ -3447,6 +3450,7 @@ public static SpreadElementSyntax SpreadElement(ExpressionSyntax expression) => SyntaxFactory.SpreadElement(SyntaxFactory.Token(SyntaxKind.DotDotToken), expression); /// Creates a new WithElementSyntax instance. + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentListSyntax argumentList) { if (withKeyword.Kind() != SyntaxKind.WithKeyword) throw new ArgumentException(nameof(withKeyword)); @@ -3455,6 +3459,7 @@ public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentLis } /// Creates a new WithElementSyntax instance. + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public static WithElementSyntax WithElement(ArgumentListSyntax? argumentList = default) => SyntaxFactory.WithElement(SyntaxFactory.Token(SyntaxKind.WithKeyword), argumentList ?? SyntaxFactory.ArgumentList()); diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index 34448dbdf06ab..4db0b36294471 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -4280,6 +4280,7 @@ public SpreadElementSyntax Update(SyntaxToken operatorToken, ExpressionSyntax ex /// /// /// +[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public sealed partial class WithElementSyntax : CollectionElementSyntax { private ArgumentListSyntax? argumentList; diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 253ca47f335d1..9caa2458488fe 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -3,17 +3,17 @@ Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo.MoveNextAwaitableInfo.get -> 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(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! 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.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> TResult? +[RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax +[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(Microsoft.CodeAnalysis.CSharp.CSharpSyntaxVisitor! 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.VisitWithElement(Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax! node) -> TResult? diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index aada4dc192051..51b2b25bc36a5 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1839,7 +1839,7 @@ - + diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs index 73a69143ddf1c..ffba7a7396c5c 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 + using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs index 9862bb7a04182..708d0afdb34bf 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 + using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs index 3f49ed1e85198..db765dc3311d6 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 + // #DEFINE DICTIONARY_EXPRESSIONS using System.Linq; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs index 66152cd60e935..d867ff1ab9204 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs @@ -2,6 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 + using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs index d4f9713d3e02e..b8b4df193d721 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs @@ -139,7 +139,9 @@ private static ISet GetExistingNamedParameters(BaseArgumentListSyntax ar ElementAccessExpressionSyntax elementAccessExpression => GetElementAccessExpressionParameterLists(semanticModel, position, elementAccessExpression, cancellationToken), BaseObjectCreationExpressionSyntax objectCreationExpression => GetObjectCreationExpressionParameterLists(semanticModel, position, objectCreationExpression, cancellationToken), PrimaryConstructorBaseTypeSyntax baseType => GetPrimaryConstructorParameterLists(semanticModel, baseType, cancellationToken), +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElement => GetWithElementParameterLists(semanticModel, withElement, cancellationToken), +#pragma warning restore RSEXPERIMENTAL006 _ => null, }; @@ -246,7 +248,9 @@ private static ISet GetExistingNamedParameters(BaseArgumentListSyntax ar private static IEnumerable> GetWithElementParameterLists( SemanticModel semanticModel, +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElement, +#pragma warning restore RSEXPERIMENTAL006 CancellationToken cancellationToken) { var creationMethods = withElement.GetCreationMethods(semanticModel, cancellationToken); diff --git a/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs index 557dddc04480f..f1f7126deb1fe 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs @@ -16,6 +16,8 @@ using Microsoft.CodeAnalysis.SignatureHelp; using Microsoft.CodeAnalysis.Text; +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 + namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp; [ExportSignatureHelpProvider("WithElementSignatureHelpProvider", LanguageNames.CSharp), Shared] diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs index 1510033d48582..4e40b97accdfe 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs @@ -15,7 +15,9 @@ internal static class WithElementSyntaxExtensions { #if !ROSLYN_4_12_OR_LOWER public static ImmutableArray GetCreationMethods( +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 this WithElementSyntax? withElement, SemanticModel semanticModel, CancellationToken cancellationToken) +#pragma warning restore RSEXPERIMENTAL006 { if (withElement?.Parent is not CollectionExpressionSyntax collectionExpression) return []; From b3ed9222bc6e205d37623e275055fc745a3579d3 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 23 Jan 2026 12:19:13 -0800 Subject: [PATCH 03/16] Support marking IOperation types as experimental. --- .../Generated/FlowAnalysis.Generated.cs | 2 + .../Generated/OperationKind.Generated.cs | 2 + .../Generated/Operations.Generated.cs | 1 + .../IOperationClassWriter.cs | 40 +++++++++++++++++-- .../Source/IOperationGenerator/Model.cs | 6 +++ 5 files changed, 47 insertions(+), 4 deletions(-) diff --git a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs index 58caf7901843c..92e4b0c3cb7eb 100644 --- a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Immutable; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.PooledObjects; diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index c920786f9d2dd..640845390fcf2 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -3,8 +3,10 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.ComponentModel; +using System.Diagnostics.CodeAnalysis; using Microsoft.CodeAnalysis.FlowAnalysis; using Microsoft.CodeAnalysis.Operations; namespace Microsoft.CodeAnalysis diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index b5cd48551be0e..0497f1941fe04 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Generic; using System.Threading; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index 5f516ad7ed94c..bade5f3a347fa 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -27,6 +27,9 @@ internal sealed partial class IOperationClassWriter private readonly Tree _tree; private readonly Dictionary _typeMap; + private static string QuoteString(string value) + => "@\"" + value.Replace("\"", "\"\"") + "\""; + private IOperationClassWriter(Tree tree, string location) { _tree = tree; @@ -116,6 +119,7 @@ private bool WriteFiles() } WriteUsing("System.Collections.Immutable"); + WriteUsing("System.Diagnostics.CodeAnalysis"); if (@namespace != "Operations") { @@ -123,7 +127,6 @@ private bool WriteFiles() } else { - WriteUsing("System.Diagnostics.CodeAnalysis"); WriteUsing("Microsoft.CodeAnalysis.FlowAnalysis"); } @@ -163,6 +166,7 @@ private bool WriteFiles() writeHeader(); WriteUsing("System"); WriteUsing("System.ComponentModel"); + WriteUsing("System.Diagnostics.CodeAnalysis"); WriteUsing("Microsoft.CodeAnalysis.FlowAnalysis"); WriteUsing("Microsoft.CodeAnalysis.Operations"); @@ -182,6 +186,7 @@ void writeHeader() WriteLine("// See the LICENSE file in the project root for more information."); WriteLine("// < auto-generated />"); WriteLine("#nullable enable"); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed."); } } @@ -205,6 +210,7 @@ private void WriteInterface(AbstractNode node) { WriteComments(node.Comments, getNodeKinds(node), writeReservedRemark: true); + WriteExperimentalAttributeIfNeeded(node); WriteObsoleteIfNecessary(node.Obsolete); WriteLine($"{(node.IsInternal ? "internal" : "public")} interface {node.Name} : {node.Base}"); Brace(); @@ -295,6 +301,7 @@ private void WriteInterfaceProperty(Property prop) if (prop.IsInternal || prop.IsOverride) return; WriteComments(prop.Comments, operationKinds: Enumerable.Empty(), writeReservedRemark: false); + WriteExperimentalAttributeIfNeeded(prop); var modifiers = prop.IsNew ? "new " : ""; WriteLine($"{modifiers}{prop.Type} {prop.Name} {{ get; }}"); } @@ -350,7 +357,8 @@ private void WriteOperationKind() entry.ExtraDescription, entry.EditorBrowsable ?? true, node.Obsolete?.Message, - node.Obsolete?.ErrorText); + node.Obsolete?.ErrorText, + experimentalUrl: node.IsInternal ? null : node.Experimental); } } else @@ -362,14 +370,15 @@ private void WriteOperationKind() currentEntry.OperationKind?.ExtraDescription, editorBrowsable: true, currentEntry.Obsolete?.Message, - currentEntry.Obsolete?.ErrorText); + currentEntry.Obsolete?.ErrorText, + experimentalUrl: currentEntry.IsInternal ? null : currentEntry.Experimental); Debug.Assert(elementsToKindEnumerator.MoveNext() || i == numKinds); } } Unbrace(); - void writeEnumElement(string kind, int value, string operationName, string? extraText, bool editorBrowsable, string? obsoleteMessage, string? obsoleteError) + void writeEnumElement(string kind, int value, string operationName, string? extraText, bool editorBrowsable, string? obsoleteMessage, string? obsoleteError, string? experimentalUrl) { WriteLine($"/// Indicates an .{(extraText is object ? $" {extraText}" : "")}"); @@ -378,6 +387,11 @@ void writeEnumElement(string kind, int value, string operationName, string? extr WriteLine("[EditorBrowsable(EditorBrowsableState.Never)]"); } + if (!string.IsNullOrEmpty(experimentalUrl)) + { + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(experimentalUrl)})]"); + } + if (obsoleteMessage is object) { WriteLine($"[Obsolete({obsoleteMessage}, error: {obsoleteError})]"); @@ -1029,6 +1043,7 @@ public virtual void DefaultVisit(IOperation operation) { /* no-op */ } if (type.SkipInVisitor) continue; + WriteExperimentalAttributeIfNeeded(type); WriteObsoleteIfNecessary(type.Obsolete); var accessibility = type.IsInternal ? "internal" : "public"; var baseName = GetSubName(type.Name); @@ -1049,6 +1064,7 @@ public virtual void DefaultVisit(IOperation operation) { /* no-op */ } if (type.SkipInVisitor) continue; + WriteExperimentalAttributeIfNeeded(type); WriteObsoleteIfNecessary(type.Obsolete); var accessibility = type.IsInternal ? "internal" : "public"; WriteLine($"{accessibility} virtual TResult? {GetVisitorName(type)}({type.Name} operation, TArgument argument) => DefaultVisit(operation, argument);"); @@ -1066,6 +1082,22 @@ private void WriteObsoleteIfNecessary(ObsoleteTag? tag) } } + private void WriteExperimentalAttributeIfNeeded(TreeType node) + { + if (!node.IsInternal && !string.IsNullOrEmpty(node.Experimental)) + { + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(node.Experimental)})]"); + } + } + + private void WriteExperimentalAttributeIfNeeded(Property prop) + { + if (!prop.IsInternal && !prop.IsOverride && !string.IsNullOrEmpty(prop.Experimental)) + { + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(prop.Experimental)})]"); + } + } + private string GetVisitorName(Node type) { return type.VisitorName ?? $"Visit{GetSubName(type.Name)}"; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs index 0ea483c917c89..743b795397fcb 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs @@ -34,6 +34,9 @@ public class TreeType [XmlAttribute] public string Base; + [XmlAttribute] + public string? Experimental; + [XmlAttribute] public string? Namespace; @@ -109,6 +112,9 @@ public class Property [XmlAttribute] public string Type; + [XmlAttribute] + public string? Experimental; + [XmlAttribute(AttributeName = "New")] public string NewText; public bool IsNew => NewText == "true"; From c690aa9b8bd53e3beac52cbe102396c533c56773 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 23 Jan 2026 12:19:39 -0800 Subject: [PATCH 04/16] Mark collection expression arguments IOperation types as experimental --- .../Core/Portable/Generated/OperationKind.Generated.cs | 1 + .../Core/Portable/Generated/Operations.Generated.cs | 4 ++++ .../Core/Portable/Operations/ControlFlowGraphBuilder.cs | 8 ++++++++ .../Core/Portable/Operations/OperationInterfaces.xml | 4 ++-- src/Compilers/Core/Portable/PublicAPI.Unshipped.txt | 8 ++++---- .../Test/Core/Compilation/ControlFlowGraphVerifier.cs | 2 ++ .../Test/Core/Compilation/OperationTreeVerifier.cs | 4 ++++ .../Test/Core/Compilation/TestOperationVisitor.cs | 5 +++++ 8 files changed, 30 insertions(+), 6 deletions(-) diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index 640845390fcf2..5c94ce06815f7 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -288,6 +288,7 @@ public enum OperationKind /// Indicates an . Spread = 0x80, /// Indicates an . + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] CollectionExpressionElementsPlaceholder = 0x81, } } diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index 0497f1941fe04..eeaed2dde86a4 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3969,6 +3969,7 @@ public interface ICollectionExpressionOperation : IOperation /// . The actual elements passed /// to the creation method are contained in . /// + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] ImmutableArray ConstructArguments { get; } /// /// Collection expression elements. @@ -4029,6 +4030,7 @@ public interface ISpreadOperation : IOperation /// This interface is reserved for implementation by its associated APIs. We reserve the right to /// change it in the future. /// + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public interface ICollectionExpressionElementsPlaceholderOperation : IOperation { } @@ -11621,6 +11623,7 @@ internal virtual void VisitNoneOperation(IOperation operation) { /* no-op */ } public virtual void VisitInlineArrayAccess(IInlineArrayAccessOperation operation) => DefaultVisit(operation); public virtual void VisitCollectionExpression(ICollectionExpressionOperation operation) => DefaultVisit(operation); public virtual void VisitSpread(ISpreadOperation operation) => DefaultVisit(operation); + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public virtual void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) => DefaultVisit(operation); } public abstract partial class OperationVisitor @@ -11761,6 +11764,7 @@ public abstract partial class OperationVisitor public virtual TResult? VisitInlineArrayAccess(IInlineArrayAccessOperation operation, TArgument argument) => DefaultVisit(operation, argument); public virtual TResult? VisitCollectionExpression(ICollectionExpressionOperation operation, TArgument argument) => DefaultVisit(operation, argument); public virtual TResult? VisitSpread(ISpreadOperation operation, TArgument argument) => DefaultVisit(operation, argument); + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] public virtual TResult? VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation, TArgument argument) => DefaultVisit(operation, argument); } #endregion diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 9ed8d1815fbc2..1fdc9af9dce1f 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -1275,6 +1275,7 @@ private void AddStatement( ) { #if DEBUG +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 Debug.Assert(spillingTheStack || _evalStack.All( slot => slot.operationOpt == null || slot.operationOpt.Kind == OperationKind.FlowCaptureReference @@ -1282,6 +1283,7 @@ private void AddStatement( || slot.operationOpt.Kind == OperationKind.Discard || slot.operationOpt.Kind == OperationKind.OmittedArgument || slot.operationOpt.Kind == OperationKind.CollectionExpressionElementsPlaceholder)); +#pragma warning restore RSEXPERIMENTAL006 #endif if (statement == null) { @@ -1847,11 +1849,13 @@ private void SpillEvalStack() Debug.Assert(operationOpt != null); // Declarations cannot have control flow, so we don't need to spill them. +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 if (operationOpt.Kind != OperationKind.FlowCaptureReference && operationOpt.Kind != OperationKind.DeclarationExpression && operationOpt.Kind != OperationKind.Discard && operationOpt.Kind != OperationKind.OmittedArgument && operationOpt.Kind != OperationKind.CollectionExpressionElementsPlaceholder) +#pragma warning restore RSEXPERIMENTAL006 { // Here we need to decide what region should own the new capture. Due to the spilling operations occurred before, // we currently might be in a region that is not associated with the stack frame we are in, but it is one of its @@ -6543,6 +6547,7 @@ IArrayInitializerOperation popAndAssembleArrayInitializerValues(IArrayInitialize public override IOperation? VisitCollectionExpression(ICollectionExpressionOperation operation, int? argument) { +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 EvalStackFrame frame = PushStackFrame(); if (operation.ConstructArguments.Any(a => a is IArgumentOperation) && !operation.ConstructArguments.All(a => a is IArgumentOperation)) @@ -6585,6 +6590,7 @@ IArrayInitializerOperation popAndAssembleArrayInitializerValues(IArrayInitialize var creationArguments = arguments.IsDefault ? PopArray(operation.ConstructArguments) : ImmutableArray.CastUp(PopArray(arguments, RewriteArgumentFromArray)); +#pragma warning restore RSEXPERIMENTAL006 return PopStackFrame(frame, new CollectionExpressionOperation( operation.ConstructMethod, @@ -7443,11 +7449,13 @@ internal override IOperation VisitPlaceholder(IPlaceholderOperation operation, i return new PlaceholderOperation(operation.PlaceholderKind, semanticModel: null, operation.Syntax, operation.Type, IsImplicit(operation)); } +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override IOperation? VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation, int? argument) { // Leave collection builder element placeholder alone. It itself doesn't affect flow control. return new CollectionExpressionElementsPlaceholderOperation(semanticModel: null, operation.Syntax, operation.Type, operation.IsImplicit); } +#pragma warning restore RSEXPERIMENTAL006 public override IOperation VisitConversion(IConversionOperation operation, int? captureIdForResult) { diff --git a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml index 325f35130bd45..995cbc208e375 100644 --- a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml +++ b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml @@ -3697,7 +3697,7 @@ - + Arguments passed to to , if present. Arguments are in evaluation order. This can @@ -3761,7 +3761,7 @@ - + Represents the elements of a collection expression as they are passed to some construction method diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 01c5dbd2a5f3f..8fa6e512a7b65 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -2,8 +2,8 @@ Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.MethodImplEntriesSupported.get Microsoft.CodeAnalysis.Emit.EmitDifferenceOptions.MethodImplEntriesSupported.init -> void Microsoft.CodeAnalysis.IMethodSymbol.ReduceExtensionMember(Microsoft.CodeAnalysis.ITypeSymbol! receiverType) -> Microsoft.CodeAnalysis.IMethodSymbol? Microsoft.CodeAnalysis.IPropertySymbol.ReduceExtensionMember(Microsoft.CodeAnalysis.ITypeSymbol! receiverType) -> Microsoft.CodeAnalysis.IPropertySymbol? -Microsoft.CodeAnalysis.OperationKind.CollectionExpressionElementsPlaceholder = 129 -> Microsoft.CodeAnalysis.OperationKind -Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation +[RSEXPERIMENTAL006]Microsoft.CodeAnalysis.OperationKind.CollectionExpressionElementsPlaceholder = 129 -> Microsoft.CodeAnalysis.OperationKind Microsoft.CodeAnalysis.Operations.ICollectionExpressionOperation.ConstructArguments.get -> System.Collections.Immutable.ImmutableArray -virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitCollectionExpressionElementsPlaceholder(Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation! operation) -> void -virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitCollectionExpressionElementsPlaceholder(Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation! operation, TArgument argument) -> TResult? +[RSEXPERIMENTAL006]Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation +[RSEXPERIMENTAL006]virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitCollectionExpressionElementsPlaceholder(Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation! operation) -> void +[RSEXPERIMENTAL006]virtual Microsoft.CodeAnalysis.Operations.OperationVisitor.VisitCollectionExpressionElementsPlaceholder(Microsoft.CodeAnalysis.Operations.ICollectionExpressionElementsPlaceholderOperation! operation, TArgument argument) -> TResult? diff --git a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs index a0f121f55d34a..45fd752a5c569 100644 --- a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs @@ -1979,7 +1979,9 @@ propertyReference.Parent is ISimpleAssignmentOperation simpleAssignment && case OperationKind.InlineArrayAccess: case OperationKind.CollectionExpression: case OperationKind.Spread: +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 case OperationKind.CollectionExpressionElementsPlaceholder: +#pragma warning restore RSEXPERIMENTAL006 return true; } diff --git a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs index 719323071b969..2e68e96901d34 100644 --- a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs @@ -1143,11 +1143,13 @@ internal override void VisitPlaceholder(IPlaceholderOperation operation) Assert.Equal(PlaceholderKind.AggregationGroup, operation.PlaceholderKind); } +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) { LogString(nameof(ICollectionExpressionElementsPlaceholderOperation)); LogCommonPropertiesAndNewLine(operation); } +#pragma warning restore RSEXPERIMENTAL006 public override void VisitUnaryOperator(IUnaryOperation operation) { @@ -1615,6 +1617,7 @@ public override void VisitArrayInitializer(IArrayInitializerOperation operation) public override void VisitCollectionExpression(ICollectionExpressionOperation operation) { +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 LogString(nameof(ICollectionExpressionOperation)); LogString($" ({operation.Elements.Length} elements"); LogSymbol(operation.ConstructMethod, $", {nameof(operation.ConstructMethod)}"); @@ -1625,6 +1628,7 @@ public override void VisitCollectionExpression(ICollectionExpressionOperation op VisitArray(operation.ConstructArguments, nameof(operation.ConstructArguments), logElementCount: true); VisitArray(operation.Elements, nameof(operation.Elements), logElementCount: true); +#pragma warning restore RSEXPERIMENTAL006 } public override void VisitSpread(ISpreadOperation operation) diff --git a/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs b/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs index 798e2fe800512..ebd11f3cec2ac 100644 --- a/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs +++ b/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs @@ -8,6 +8,7 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; +using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.FlowAnalysis; @@ -487,8 +488,10 @@ internal override void VisitFixed(IFixedOperation operation) public override void VisitCollectionExpression(ICollectionExpressionOperation operation) { +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 Assert.Equal(OperationKind.CollectionExpression, operation.Kind); AssertEx.Equal([.. operation.ConstructArguments, .. operation.Elements], operation.ChildOperations); +#pragma warning restore RSEXPERIMENTAL006 } public override void VisitSpread(ISpreadOperation operation) @@ -743,11 +746,13 @@ internal override void VisitPlaceholder(IPlaceholderOperation operation) Assert.Empty(operation.ChildOperations); } +#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) { Assert.Equal(OperationKind.CollectionExpressionElementsPlaceholder, operation.Kind); Assert.Empty(operation.ChildOperations); } +#pragma warning restore RSEXPERIMENTAL006 public override void VisitUnaryOperator(IUnaryOperation operation) { From 175b78d49efb783b7b5f2436b54e7c7c3fb5eb2c Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 23 Jan 2026 12:23:00 -0800 Subject: [PATCH 05/16] Update canary instructions --- src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 02c3491acd282..10bbd094f790a 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -1722,6 +1722,8 @@ public void LanguageVersionAdded_Canary() // - [ ] replace all references to C# "Next" (such as `TestOptions.RegularNext` or `LanguageVersionFacts.CSharpNext`) with the new version and fix failing tests // - [ ] update _MaxAvailableLangVersion cap (a relevant test should break when new version is introduced) // - [ ] update the "UpgradeProject" codefixer + // - [ ] Remove the `Experimental` section from any entries being shipped in Syntax.xml and OperationInterfaces.xml, and rerun the generator + // - [ ] Search the codebase for the URLs that were linked in the Syntax.xml and OperationInterfaces.xml files and remove suppressions or attributes added for those issues. // - [ ] test VS insertion and deal with breaking changes. (note: the runtime repo uses "preview" so breaks are resolved sooner) // // Other repos also need updates: From 21ed3b12dd9514916f6076794ed194afacd30016 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Mon, 26 Jan 2026 09:27:07 -0800 Subject: [PATCH 06/16] Addressing non-suppression comments. --- .../CSharp/Portable/Syntax/Syntax.xml | 2 +- .../CSharp/Portable/Syntax/Syntax.xsd | 20 +++++----- .../Test/CommandLine/CommandLineTests.cs | 2 +- .../InternalUtilities/RoslynExperiments.cs | 2 +- .../Operations/OperationInterfaces.xml | 4 +- .../CSharpSyntaxGenerator/Model/Field.cs | 2 +- .../CSharpSyntaxGenerator/Model/TreeType.cs | 2 +- .../CSharpSyntaxGenerator/SourceWriter.cs | 38 +++++++++---------- .../IOperationClassWriter.Verifier.cs | 12 ++++++ .../IOperationClassWriter.cs | 17 ++++++--- .../Source/IOperationGenerator/Model.cs | 4 +- 11 files changed, 61 insertions(+), 44 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 51b2b25bc36a5..97e8709122f27 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1839,7 +1839,7 @@ - + diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd b/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd index fb1d962edbba9..bbfac4fae23a1 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xsd @@ -8,7 +8,7 @@ - + @@ -35,7 +35,7 @@ - + @@ -62,7 +62,7 @@ - + @@ -86,7 +86,7 @@ - + @@ -99,7 +99,7 @@ - + @@ -136,7 +136,7 @@ - + @@ -176,7 +176,7 @@ - + @@ -189,7 +189,7 @@ - + @@ -214,7 +214,7 @@ - + @@ -229,7 +229,7 @@ - + diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 10bbd094f790a..faa9fd016ed60 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -1722,7 +1722,7 @@ public void LanguageVersionAdded_Canary() // - [ ] replace all references to C# "Next" (such as `TestOptions.RegularNext` or `LanguageVersionFacts.CSharpNext`) with the new version and fix failing tests // - [ ] update _MaxAvailableLangVersion cap (a relevant test should break when new version is introduced) // - [ ] update the "UpgradeProject" codefixer - // - [ ] Remove the `Experimental` section from any entries being shipped in Syntax.xml and OperationInterfaces.xml, and rerun the generator + // - [ ] Remove the `ExperimentalUrl` section from any entries for language features being shipped in Syntax.xml and OperationInterfaces.xml, and rerun the generator // - [ ] Search the codebase for the URLs that were linked in the Syntax.xml and OperationInterfaces.xml files and remove suppressions or attributes added for those issues. // - [ ] test VS insertion and deal with breaking changes. (note: the runtime repo uses "preview" so breaks are resolved sooner) // diff --git a/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs b/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs index dedfdead59736..44db6c6ad693d 100644 --- a/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs +++ b/src/Compilers/Core/Portable/InternalUtilities/RoslynExperiments.cs @@ -15,7 +15,7 @@ internal static class RoslynExperiments internal const string GeneratorHostOutputs = "RSEXPERIMENTAL004"; internal const string GeneratorHostOutputs_Url = "https://github.com/dotnet/roslyn/issues/74753"; - // The URL is customized per-api to point at the test plan for the feature + // The UrlFormat property is customized per-api to point at the test plan for the feature, not a single general issue. internal const string PreviewLanguageFeatureApi = "RSEXPERIMENTAL006"; // Previously taken: RSEXPERIMENTAL003 - https://github.com/dotnet/roslyn/issues/73002 (SyntaxTokenParser) diff --git a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml index 995cbc208e375..bce513d8429e9 100644 --- a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml +++ b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml @@ -3697,7 +3697,7 @@ - + Arguments passed to to , if present. Arguments are in evaluation order. This can @@ -3761,7 +3761,7 @@ - + Represents the elements of a collection expression as they are passed to some construction method diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs index 882fc42cdfd13..4d5ac9e67ee83 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/Field.cs @@ -45,7 +45,7 @@ public class Field : TreeTypeChild public string Type; [XmlAttribute] - public string Experimental; + public string ExperimentalUrl; [XmlAttribute] public string Optional; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs index 7850cc737da3e..a0910b3b0ab62 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/Model/TreeType.cs @@ -18,7 +18,7 @@ public class TreeType public string Base; [XmlAttribute] - public string Experimental; + public string ExperimentalUrl; [XmlAttribute] public string SkipConvenienceFactories; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs index 39eb1e503a050..df877f1cff3d6 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs @@ -29,11 +29,11 @@ private SourceWriter(TextWriter writer, Tree tree, CancellationToken cancellatio private static string QuoteString(string value) => "@\"" + value.Replace("\"", "\"\"") + "\""; - private void WriteExperimentalIfNeeded(string experimental) + private void WriteExperimentalIfNeeded(string experimentalUrl) { - if (!string.IsNullOrEmpty(experimental)) + if (!string.IsNullOrEmpty(experimentalUrl)) { - WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(experimental)})]"); + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(experimentalUrl)})]"); } } @@ -714,7 +714,7 @@ private void WriteRedType(TreeType node) if (node is AbstractNode) { var nd = (AbstractNode)node; - WriteExperimentalIfNeeded(node.Experimental); + WriteExperimentalIfNeeded(node.ExperimentalUrl); WriteLine($"public abstract partial class {node.Name} : {node.Base}"); OpenBlock(); WriteLine($"internal {node.Name}(InternalSyntax.CSharpSyntaxNode green, SyntaxNode? parent, int position)"); @@ -733,7 +733,7 @@ private void WriteRedType(TreeType node) var fieldType = GetRedFieldType(field); WriteLine(); WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); WriteLine($"{"public"} abstract {(IsNew(field) ? "new " : "")}{fieldType} {field.Name} {{ get; }}"); WriteLine($"public {node.Name} With{field.Name}({fieldType} {CamelCase(field.Name)}) => With{field.Name}Core({CamelCase(field.Name)});"); WriteLine($"internal abstract {node.Name} With{field.Name}Core({fieldType} {CamelCase(field.Name)});"); @@ -770,7 +770,7 @@ private void WriteRedType(TreeType node) { WriteLine(); WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); WriteLine($"{"public"} abstract {(IsNew(field) ? "new " : "")}{field.Type} {field.Name} {{ get; }}"); } @@ -833,7 +833,7 @@ private void WriteRedType(TreeType node) WriteComment($""); WriteComment($""); - WriteExperimentalIfNeeded(node.Experimental); + WriteExperimentalIfNeeded(node.ExperimentalUrl); WriteLine($"public sealed partial class {node.Name} : {node.Base}"); OpenBlock(); @@ -885,7 +885,7 @@ private void WriteRedType(TreeType node) if (field.Type == "SyntaxToken") { WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); Write($"public {OverrideOrNewModifier(field)}{GetRedPropertyType(field)} {field.Name}"); if (IsOptional(field)) { @@ -906,7 +906,7 @@ private void WriteRedType(TreeType node) else if (field.Type == "SyntaxList") { WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); WriteLine($"public {OverrideOrNewModifier(field)}SyntaxTokenList {field.Name}"); OpenBlock(); WriteLine("get"); @@ -919,7 +919,7 @@ private void WriteRedType(TreeType node) else { WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); Write($"public {OverrideOrNewModifier(field)}{GetRedPropertyType(field)} {field.Name}"); if (IsNodeList(field.Type)) @@ -961,7 +961,7 @@ private void WriteRedType(TreeType node) foreach (var field in valueFields) { WriteComment(field.PropertyComment, ""); - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); WriteLine($"{"public"} {OverrideOrNewModifier(field)}{field.Type} {field.Name} => ((InternalSyntax.{node.Name})this.Green).{field.Name};"); WriteLine(); } @@ -1108,7 +1108,7 @@ private void WriteRedVisitor(bool genericResult) WriteLine(); nWritten++; WriteComment($"Called when the visitor visits a {node.Name} node."); - WriteExperimentalIfNeeded(node.Experimental); + WriteExperimentalIfNeeded(node.ExperimentalUrl); WriteLine($"public virtual {(genericResult ? "TResult?" : "void")} Visit{StripPost(node.Name, "Syntax")}({node.Name} node) => this.DefaultVisit(node);"); } CloseBlock(); @@ -1182,7 +1182,7 @@ private void WriteRedWithMethods(Node node) } } - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); Write( $"public{(isNew ? " new " : " ")}{node.Name} With{StripPost(field.Name, "Opt")}({type} {CamelCase(field.Name)})" + " => Update("); @@ -1284,7 +1284,7 @@ private void WriteRedListHelperMethods(Node node, Field field) } } - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); WriteLine($"public{(isNew ? " new " : " ")}{node.Name} Add{field.Name}(params {argType}[] items) => With{StripPost(field.Name, "Opt")}(this.{field.Name}.AddRange(items));"); } @@ -1304,7 +1304,7 @@ private void WriteRedNestedListHelperMethods(Node node, Field field, Node refere } // AddBaseListTypes - WriteExperimentalIfNeeded(field.Experimental); + WriteExperimentalIfNeeded(field.ExperimentalUrl); Write($"public{(isNew ? " new " : " ")}{node.Name} Add{StripPost(field.Name, "Opt")}{referencedNodeField.Name}(params {argType}[] items)"); if (IsOptional(field)) @@ -1337,7 +1337,7 @@ private void WriteRedRewriter() if (nWritten > 0) WriteLine(); nWritten++; - WriteExperimentalIfNeeded(node.Experimental); + WriteExperimentalIfNeeded(node.ExperimentalUrl); WriteLine($"public override SyntaxNode? Visit{StripPost(node.Name, "Syntax")}({node.Name} node)"); if (node.Fields.Count == 0) @@ -1464,7 +1464,7 @@ private void WriteRedFactory(Node nd) WriteComment($"Creates a new {nd.Name} instance."); - WriteExperimentalIfNeeded(nd.Experimental); + WriteExperimentalIfNeeded(nd.ExperimentalUrl); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); WriteRedFactoryParameters(nd); @@ -1650,7 +1650,7 @@ private void WriteRedFactoryWithNoAutoCreatableTokens(Node nd) this.WriteLine(); WriteComment($"Creates a new {nd.Name} instance."); - WriteExperimentalIfNeeded(nd.Experimental); + WriteExperimentalIfNeeded(nd.ExperimentalUrl); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); Write(CommaJoin( nd.Kinds.Count > 1 ? "SyntaxKind kind" : "", @@ -1740,7 +1740,7 @@ private void WriteRedMinimalFactory(Node nd, bool withStringNames = false) } WriteComment($"Creates a new {nd.Name} instance."); - WriteExperimentalIfNeeded(nd.Experimental); + WriteExperimentalIfNeeded(nd.ExperimentalUrl); Write($"public static {nd.Name} {StripPost(nd.Name, "Syntax")}("); Write(CommaJoin( nd.Kinds.Count > 1 ? "SyntaxKind kind" : "", diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs index 45c1562960f9d..56d9cf9489b09 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.Verifier.cs @@ -33,6 +33,12 @@ private bool ModelHasErrors(Tree tree) error = true; } + if (abstractNode.IsInternal && !string.IsNullOrEmpty(abstractNode.ExperimentalUrl)) + { + Console.WriteLine($"{abstractNode.Name} is marked as internal and experimental. Internal nodes cannot be experimental."); + error = true; + } + if (!abstractNode.IsInternal && abstractNode.Obsolete is null) { if (abstractNode.Comments?.Elements?[0].Name != "summary") @@ -43,6 +49,12 @@ private bool ModelHasErrors(Tree tree) foreach (var prop in abstractNode.Properties) { + if (prop.IsInternal && !string.IsNullOrEmpty(prop.ExperimentalUrl)) + { + Console.WriteLine($"{abstractNode.Name}.{prop.Name} is marked as internal and experimental. Internal properties cannot be experimental."); + error = true; + } + if (prop.Comments?.Elements?[0].Name != "summary" && !prop.IsInternal && !prop.IsOverride) { Console.WriteLine($"{abstractNode.Name}.{prop.Name} does not have correctly formatted comments, please ensure that there is a block for the property."); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index bade5f3a347fa..c2f73d09e8948 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -358,7 +358,7 @@ private void WriteOperationKind() entry.EditorBrowsable ?? true, node.Obsolete?.Message, node.Obsolete?.ErrorText, - experimentalUrl: node.IsInternal ? null : node.Experimental); + experimentalUrl: node.ExperimentalUrl); } } else @@ -371,7 +371,7 @@ private void WriteOperationKind() editorBrowsable: true, currentEntry.Obsolete?.Message, currentEntry.Obsolete?.ErrorText, - experimentalUrl: currentEntry.IsInternal ? null : currentEntry.Experimental); + experimentalUrl: currentEntry.ExperimentalUrl); Debug.Assert(elementsToKindEnumerator.MoveNext() || i == numKinds); } } @@ -1082,19 +1082,24 @@ private void WriteObsoleteIfNecessary(ObsoleteTag? tag) } } + private void WriteExperimentalAttribute(string experimentalUrl) + { + WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @\"{experimentalUrl.Replace("\"", "\"\"")}\")]"); + } + private void WriteExperimentalAttributeIfNeeded(TreeType node) { - if (!node.IsInternal && !string.IsNullOrEmpty(node.Experimental)) + if (!string.IsNullOrEmpty(node.ExperimentalUrl)) { - WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(node.Experimental)})]"); + WriteExperimentalAttribute(node.ExperimentalUrl); } } private void WriteExperimentalAttributeIfNeeded(Property prop) { - if (!prop.IsInternal && !prop.IsOverride && !string.IsNullOrEmpty(prop.Experimental)) + if (!prop.IsOverride && !string.IsNullOrEmpty(prop.ExperimentalUrl)) { - WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(prop.Experimental)})]"); + WriteExperimentalAttribute(prop.ExperimentalUrl); } } diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs index 743b795397fcb..426f09dafa327 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/Model.cs @@ -35,7 +35,7 @@ public class TreeType public string Base; [XmlAttribute] - public string? Experimental; + public string? ExperimentalUrl; [XmlAttribute] public string? Namespace; @@ -113,7 +113,7 @@ public class Property public string Type; [XmlAttribute] - public string? Experimental; + public string? ExperimentalUrl; [XmlAttribute(AttributeName = "New")] public string NewText; From c74c04dd66b125b9e52b4e8957bbe4f915c071f8 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 11:55:37 -0800 Subject: [PATCH 07/16] Add a global suppression --- .editorconfig | 3 +++ .../CSharpUseCollectionInitializerDiagnosticAnalyzer.cs | 2 -- .../CSharpCollectionExpressionRewriter.cs | 4 ---- .../CSharp/Portable/Binder/Binder_Expressions.cs | 4 ---- .../CSharp/Portable/BoundTree/BoundExpression.cs | 2 -- .../CSharp/Portable/Compilation/CSharpSemanticModel.cs | 6 ------ .../CSharp/Portable/Compilation/MemberSemanticModel.cs | 2 -- ...ollectionExpressionTests_WithElement_ArraysAndSpans.cs | 2 -- .../CollectionExpressionTests_WithElement_Constructor.cs | 2 -- .../CollectionExpressionTests_WithElement_Extra.cs | 2 -- .../CollectionExpressionTests_WithElement_Nullable.cs | 2 -- .../Core/Portable/Operations/ControlFlowGraphBuilder.cs | 8 -------- .../Test/Core/Compilation/ControlFlowGraphVerifier.cs | 2 -- .../Test/Core/Compilation/OperationTreeVerifier.cs | 4 ---- .../Test/Core/Compilation/TestOperationVisitor.cs | 5 ----- .../NamedParameterCompletionProvider.cs | 4 ---- .../SignatureHelp/WithElementSignatureHelpProvider.cs | 2 -- .../CSharp/Extensions/WithElementSyntaxExtensions.cs | 2 -- 18 files changed, 3 insertions(+), 55 deletions(-) diff --git a/.editorconfig b/.editorconfig index e95967a09e126..6c9296ba46ef7 100644 --- a/.editorconfig +++ b/.editorconfig @@ -167,6 +167,9 @@ dotnet_diagnostic.xUnit2020.severity = none dotnet_diagnostic.xUnit2023.severity = none dotnet_diagnostic.xUnit2029.severity = none +# RS0006: Roslyn experimental language API +dotnet_diagnostic.RSEXPERIMENTAL006.severity = none + # CSharp code style settings: [*.cs] # Newline settings diff --git a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs index 9141a858474f3..9177c39646466 100644 --- a/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs +++ b/src/Analyzers/CSharp/Analyzers/UseCollectionInitializer/CSharpUseCollectionInitializerDiagnosticAnalyzer.cs @@ -74,9 +74,7 @@ static IEnumerable GetMatchElements(ImmutableArray match) { if (match.Node is ArgumentListSyntax argumentList) -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 return WithElement(argumentList.WithoutTrivia()); -#pragma warning restore RSEXPERIMENTAL006 var expression = (ExpressionSyntax)(object)match.Node; return match.UseSpread @@ -594,9 +592,7 @@ IEnumerable CreateElements( } else if (node is ArgumentListSyntax argumentList) { -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 yield return WithElement(argumentList.WithoutTrivia()); -#pragma warning restore RSEXPERIMENTAL006 } else { diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 33e064d8475ac..4be320e5531a5 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -5346,9 +5346,7 @@ private BoundExpression BindCollectionExpression(CollectionExpressionSyntax synt var builder = ArrayBuilder.GetInstance(syntax.Elements.Count); foreach (var element in syntax.Elements) { -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 if (element is WithElementSyntax withElementSyntax) -#pragma warning restore RSEXPERIMENTAL006 { MessageID.IDS_FeatureCollectionExpressionArguments.CheckFeatureAvailability(diagnostics, syntax, withElementSyntax.WithKeyword.GetLocation()); @@ -5441,9 +5439,7 @@ static BoundNode bindSpreadElement(SpreadElementSyntax syntax, BindingDiagnostic static (BoundUnconvertedWithElement? withElement, BoundBadExpression? badExpression) bindWithElement( Binder @this, CollectionExpressionSyntax syntax, -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElementSyntax, -#pragma warning restore RSEXPERIMENTAL006 BindingDiagnosticBag diagnostics) { // Report a withElement that is not first. Note: for the purposes of error recovery and diagnostics diff --git a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs index 468d2bc0fb760..3c5ab45d8f194 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/BoundExpression.cs @@ -23,9 +23,7 @@ public SimpleNameSyntax? InterceptableNameSyntax this.Syntax is InvocationExpressionSyntax or ConstructorInitializerSyntax or PrimaryConstructorBaseTypeSyntax { ArgumentList: { } } -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 or WithElementSyntax -#pragma warning restore RSEXPERIMENTAL006 or CollectionExpressionSyntax, $"Unexpected syntax kind for BoundCall: {this.Syntax.Kind()}"); diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs index 5a5fa23c4867e..aec3389cb2741 100644 --- a/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/CSharpSemanticModel.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; using System.Threading; using Microsoft.CodeAnalysis.Collections; @@ -123,9 +122,7 @@ internal static bool CanGetSemanticInfo(CSharpSyntaxNode node, bool allowNamedAr (node is ExpressionSyntax && (isSpeculative || allowNamedArgumentName || !SyntaxFacts.IsNamedArgumentName(node))) || (node is ConstructorInitializerSyntax or PrimaryConstructorBaseTypeSyntax -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 or WithElementSyntax -#pragma warning restore RSEXPERIMENTAL006 or AttributeSyntax or CrefSyntax); } @@ -660,7 +657,6 @@ private static SymbolInfo GetSymbolInfoFromSymbolOrNone(ITypeSymbol type) /// /// Returns what symbol(s), if any, the given 'with(...)' element syntax bound to in the program. /// - [Experimental(RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = "https://github.com/dotnet/roslyn/issues/80613")] internal SymbolInfo GetSymbolInfo(WithElementSyntax withElement, CancellationToken cancellationToken = default(CancellationToken)) { CheckSyntaxNode(withElement); @@ -5025,10 +5021,8 @@ private SymbolInfo GetSymbolInfoFromNode(SyntaxNode node, CancellationToken canc return this.GetSymbolInfo(orderingSyntax, cancellationToken); case PositionalPatternClauseSyntax ppcSyntax: return this.GetSymbolInfo(ppcSyntax, cancellationToken); -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 case WithElementSyntax withElement: return this.GetSymbolInfo(withElement, cancellationToken); -#pragma warning restore RSEXPERIMENTAL006 } return SymbolInfo.None; diff --git a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs index e7d3531cc0138..017ef8b8991be 100644 --- a/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/MemberSemanticModel.cs @@ -2291,9 +2291,7 @@ protected internal virtual CSharpSyntaxNode GetBindableSyntaxNode(CSharpSyntaxNo !(node is JoinIntoClauseSyntax) && !(node is QueryContinuationSyntax) && !(node is ConstructorInitializerSyntax) && -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 !(node is WithElementSyntax) && -#pragma warning restore RSEXPERIMENTAL006 !(node is PrimaryConstructorBaseTypeSyntax) && !(node is ArrowExpressionClauseSyntax) && !(node is PatternSyntax)) diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs index ffba7a7396c5c..73a69143ddf1c 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_ArraysAndSpans.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 - using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs index 708d0afdb34bf..9862bb7a04182 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Constructor.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 - using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs index db765dc3311d6..3f49ed1e85198 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Extra.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 - // #DEFINE DICTIONARY_EXPRESSIONS using System.Linq; diff --git a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs index d867ff1ab9204..66152cd60e935 100644 --- a/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs +++ b/src/Compilers/CSharp/Test/Emit3/Semantics/CollectionExpressionTests_WithElement_Nullable.cs @@ -2,8 +2,6 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 - using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Test.Utilities; diff --git a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs index 1fdc9af9dce1f..9ed8d1815fbc2 100644 --- a/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs +++ b/src/Compilers/Core/Portable/Operations/ControlFlowGraphBuilder.cs @@ -1275,7 +1275,6 @@ private void AddStatement( ) { #if DEBUG -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 Debug.Assert(spillingTheStack || _evalStack.All( slot => slot.operationOpt == null || slot.operationOpt.Kind == OperationKind.FlowCaptureReference @@ -1283,7 +1282,6 @@ private void AddStatement( || slot.operationOpt.Kind == OperationKind.Discard || slot.operationOpt.Kind == OperationKind.OmittedArgument || slot.operationOpt.Kind == OperationKind.CollectionExpressionElementsPlaceholder)); -#pragma warning restore RSEXPERIMENTAL006 #endif if (statement == null) { @@ -1849,13 +1847,11 @@ private void SpillEvalStack() Debug.Assert(operationOpt != null); // Declarations cannot have control flow, so we don't need to spill them. -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 if (operationOpt.Kind != OperationKind.FlowCaptureReference && operationOpt.Kind != OperationKind.DeclarationExpression && operationOpt.Kind != OperationKind.Discard && operationOpt.Kind != OperationKind.OmittedArgument && operationOpt.Kind != OperationKind.CollectionExpressionElementsPlaceholder) -#pragma warning restore RSEXPERIMENTAL006 { // Here we need to decide what region should own the new capture. Due to the spilling operations occurred before, // we currently might be in a region that is not associated with the stack frame we are in, but it is one of its @@ -6547,7 +6543,6 @@ IArrayInitializerOperation popAndAssembleArrayInitializerValues(IArrayInitialize public override IOperation? VisitCollectionExpression(ICollectionExpressionOperation operation, int? argument) { -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 EvalStackFrame frame = PushStackFrame(); if (operation.ConstructArguments.Any(a => a is IArgumentOperation) && !operation.ConstructArguments.All(a => a is IArgumentOperation)) @@ -6590,7 +6585,6 @@ IArrayInitializerOperation popAndAssembleArrayInitializerValues(IArrayInitialize var creationArguments = arguments.IsDefault ? PopArray(operation.ConstructArguments) : ImmutableArray.CastUp(PopArray(arguments, RewriteArgumentFromArray)); -#pragma warning restore RSEXPERIMENTAL006 return PopStackFrame(frame, new CollectionExpressionOperation( operation.ConstructMethod, @@ -7449,13 +7443,11 @@ internal override IOperation VisitPlaceholder(IPlaceholderOperation operation, i return new PlaceholderOperation(operation.PlaceholderKind, semanticModel: null, operation.Syntax, operation.Type, IsImplicit(operation)); } -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override IOperation? VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation, int? argument) { // Leave collection builder element placeholder alone. It itself doesn't affect flow control. return new CollectionExpressionElementsPlaceholderOperation(semanticModel: null, operation.Syntax, operation.Type, operation.IsImplicit); } -#pragma warning restore RSEXPERIMENTAL006 public override IOperation VisitConversion(IConversionOperation operation, int? captureIdForResult) { diff --git a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs index 45fd752a5c569..a0f121f55d34a 100644 --- a/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/ControlFlowGraphVerifier.cs @@ -1979,9 +1979,7 @@ propertyReference.Parent is ISimpleAssignmentOperation simpleAssignment && case OperationKind.InlineArrayAccess: case OperationKind.CollectionExpression: case OperationKind.Spread: -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 case OperationKind.CollectionExpressionElementsPlaceholder: -#pragma warning restore RSEXPERIMENTAL006 return true; } diff --git a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs index 2e68e96901d34..719323071b969 100644 --- a/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs +++ b/src/Compilers/Test/Core/Compilation/OperationTreeVerifier.cs @@ -1143,13 +1143,11 @@ internal override void VisitPlaceholder(IPlaceholderOperation operation) Assert.Equal(PlaceholderKind.AggregationGroup, operation.PlaceholderKind); } -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) { LogString(nameof(ICollectionExpressionElementsPlaceholderOperation)); LogCommonPropertiesAndNewLine(operation); } -#pragma warning restore RSEXPERIMENTAL006 public override void VisitUnaryOperator(IUnaryOperation operation) { @@ -1617,7 +1615,6 @@ public override void VisitArrayInitializer(IArrayInitializerOperation operation) public override void VisitCollectionExpression(ICollectionExpressionOperation operation) { -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 LogString(nameof(ICollectionExpressionOperation)); LogString($" ({operation.Elements.Length} elements"); LogSymbol(operation.ConstructMethod, $", {nameof(operation.ConstructMethod)}"); @@ -1628,7 +1625,6 @@ public override void VisitCollectionExpression(ICollectionExpressionOperation op VisitArray(operation.ConstructArguments, nameof(operation.ConstructArguments), logElementCount: true); VisitArray(operation.Elements, nameof(operation.Elements), logElementCount: true); -#pragma warning restore RSEXPERIMENTAL006 } public override void VisitSpread(ISpreadOperation operation) diff --git a/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs b/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs index ebd11f3cec2ac..798e2fe800512 100644 --- a/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs +++ b/src/Compilers/Test/Core/Compilation/TestOperationVisitor.cs @@ -8,7 +8,6 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; -using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.Collections; using Microsoft.CodeAnalysis.FlowAnalysis; @@ -488,10 +487,8 @@ internal override void VisitFixed(IFixedOperation operation) public override void VisitCollectionExpression(ICollectionExpressionOperation operation) { -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 Assert.Equal(OperationKind.CollectionExpression, operation.Kind); AssertEx.Equal([.. operation.ConstructArguments, .. operation.Elements], operation.ChildOperations); -#pragma warning restore RSEXPERIMENTAL006 } public override void VisitSpread(ISpreadOperation operation) @@ -746,13 +743,11 @@ internal override void VisitPlaceholder(IPlaceholderOperation operation) Assert.Empty(operation.ChildOperations); } -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 public override void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) { Assert.Equal(OperationKind.CollectionExpressionElementsPlaceholder, operation.Kind); Assert.Empty(operation.ChildOperations); } -#pragma warning restore RSEXPERIMENTAL006 public override void VisitUnaryOperator(IUnaryOperation operation) { diff --git a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs index b8b4df193d721..d4f9713d3e02e 100644 --- a/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs +++ b/src/Features/CSharp/Portable/Completion/CompletionProviders/NamedParameterCompletionProvider.cs @@ -139,9 +139,7 @@ private static ISet GetExistingNamedParameters(BaseArgumentListSyntax ar ElementAccessExpressionSyntax elementAccessExpression => GetElementAccessExpressionParameterLists(semanticModel, position, elementAccessExpression, cancellationToken), BaseObjectCreationExpressionSyntax objectCreationExpression => GetObjectCreationExpressionParameterLists(semanticModel, position, objectCreationExpression, cancellationToken), PrimaryConstructorBaseTypeSyntax baseType => GetPrimaryConstructorParameterLists(semanticModel, baseType, cancellationToken), -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElement => GetWithElementParameterLists(semanticModel, withElement, cancellationToken), -#pragma warning restore RSEXPERIMENTAL006 _ => null, }; @@ -248,9 +246,7 @@ private static ISet GetExistingNamedParameters(BaseArgumentListSyntax ar private static IEnumerable> GetWithElementParameterLists( SemanticModel semanticModel, -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 WithElementSyntax withElement, -#pragma warning restore RSEXPERIMENTAL006 CancellationToken cancellationToken) { var creationMethods = withElement.GetCreationMethods(semanticModel, cancellationToken); diff --git a/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs b/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs index f1f7126deb1fe..557dddc04480f 100644 --- a/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs +++ b/src/Features/CSharp/Portable/SignatureHelp/WithElementSignatureHelpProvider.cs @@ -16,8 +16,6 @@ using Microsoft.CodeAnalysis.SignatureHelp; using Microsoft.CodeAnalysis.Text; -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 - namespace Microsoft.CodeAnalysis.CSharp.SignatureHelp; [ExportSignatureHelpProvider("WithElementSignatureHelpProvider", LanguageNames.CSharp), Shared] diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs index 4e40b97accdfe..1510033d48582 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Workspace/CSharp/Extensions/WithElementSyntaxExtensions.cs @@ -15,9 +15,7 @@ internal static class WithElementSyntaxExtensions { #if !ROSLYN_4_12_OR_LOWER public static ImmutableArray GetCreationMethods( -#pragma warning disable RSEXPERIMENTAL006 // With Element: https://github.com/dotnet/roslyn/issues/80613 this WithElementSyntax? withElement, SemanticModel semanticModel, CancellationToken cancellationToken) -#pragma warning restore RSEXPERIMENTAL006 { if (withElement?.Parent is not CollectionExpressionSyntax collectionExpression) return []; From 26a3976334ba0a77ee1c3f486443a3e67d0c1320 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 12:06:45 -0800 Subject: [PATCH 08/16] Update issue link --- .../Syntax.xml.Main.Generated.cs | 10 +++++----- .../Syntax.xml.Syntax.Generated.cs | 2 +- src/Compilers/CSharp/Portable/Syntax/Syntax.xml | 2 +- .../Core/Portable/Generated/OperationKind.Generated.cs | 2 +- .../Core/Portable/Generated/Operations.Generated.cs | 8 ++++---- .../Core/Portable/Operations/OperationInterfaces.xml | 4 ++-- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 048153abab86e..5b3f5c9cfeca2 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -230,7 +230,7 @@ public partial class CSharpSyntaxVisitor public virtual TResult? VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a WithElementSyntax node. - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public virtual TResult? VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a QueryExpressionSyntax node. @@ -978,7 +978,7 @@ public partial class CSharpSyntaxVisitor public virtual void VisitSpreadElement(SpreadElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a WithElementSyntax node. - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public virtual void VisitWithElement(WithElementSyntax node) => this.DefaultVisit(node); /// Called when the visitor visits a QueryExpressionSyntax node. @@ -1725,7 +1725,7 @@ public partial class CSharpSyntaxRewriter : CSharpSyntaxVisitor public override SyntaxNode? VisitSpreadElement(SpreadElementSyntax node) => node.Update(VisitToken(node.OperatorToken), (ExpressionSyntax?)Visit(node.Expression) ?? throw new ArgumentNullException("expression")); - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public override SyntaxNode? VisitWithElement(WithElementSyntax node) => node.Update(VisitToken(node.WithKeyword), (ArgumentListSyntax?)Visit(node.ArgumentList) ?? throw new ArgumentNullException("argumentList")); @@ -3450,7 +3450,7 @@ public static SpreadElementSyntax SpreadElement(ExpressionSyntax expression) => SyntaxFactory.SpreadElement(SyntaxFactory.Token(SyntaxKind.DotDotToken), expression); /// Creates a new WithElementSyntax instance. - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentListSyntax argumentList) { if (withKeyword.Kind() != SyntaxKind.WithKeyword) throw new ArgumentException(nameof(withKeyword)); @@ -3459,7 +3459,7 @@ public static WithElementSyntax WithElement(SyntaxToken withKeyword, ArgumentLis } /// Creates a new WithElementSyntax instance. - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public static WithElementSyntax WithElement(ArgumentListSyntax? argumentList = default) => SyntaxFactory.WithElement(SyntaxFactory.Token(SyntaxKind.WithKeyword), argumentList ?? SyntaxFactory.ArgumentList()); diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index 4db0b36294471..e2f62f11e4d2d 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -4280,7 +4280,7 @@ public SpreadElementSyntax Update(SyntaxToken operatorToken, ExpressionSyntax ex /// /// /// -[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] +[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public sealed partial class WithElementSyntax : CollectionElementSyntax { private ArgumentListSyntax? argumentList; diff --git a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml index 97e8709122f27..1049f058945c1 100644 --- a/src/Compilers/CSharp/Portable/Syntax/Syntax.xml +++ b/src/Compilers/CSharp/Portable/Syntax/Syntax.xml @@ -1839,7 +1839,7 @@ - + diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index 5c94ce06815f7..de106e8bd79dc 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -288,7 +288,7 @@ public enum OperationKind /// Indicates an . Spread = 0x80, /// Indicates an . - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] CollectionExpressionElementsPlaceholder = 0x81, } } diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index eeaed2dde86a4..bb6191306b4d6 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3969,7 +3969,7 @@ public interface ICollectionExpressionOperation : IOperation /// . The actual elements passed /// to the creation method are contained in . /// - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] ImmutableArray ConstructArguments { get; } /// /// Collection expression elements. @@ -4030,7 +4030,7 @@ public interface ISpreadOperation : IOperation /// This interface is reserved for implementation by its associated APIs. We reserve the right to /// change it in the future. /// - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public interface ICollectionExpressionElementsPlaceholderOperation : IOperation { } @@ -11623,7 +11623,7 @@ internal virtual void VisitNoneOperation(IOperation operation) { /* no-op */ } public virtual void VisitInlineArrayAccess(IInlineArrayAccessOperation operation) => DefaultVisit(operation); public virtual void VisitCollectionExpression(ICollectionExpressionOperation operation) => DefaultVisit(operation); public virtual void VisitSpread(ISpreadOperation operation) => DefaultVisit(operation); - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public virtual void VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation) => DefaultVisit(operation); } public abstract partial class OperationVisitor @@ -11764,7 +11764,7 @@ public abstract partial class OperationVisitor public virtual TResult? VisitInlineArrayAccess(IInlineArrayAccessOperation operation, TArgument argument) => DefaultVisit(operation, argument); public virtual TResult? VisitCollectionExpression(ICollectionExpressionOperation operation, TArgument argument) => DefaultVisit(operation, argument); public virtual TResult? VisitSpread(ISpreadOperation operation, TArgument argument) => DefaultVisit(operation, argument); - [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/80613")] + [Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = @"https://github.com/dotnet/roslyn/issues/82210")] public virtual TResult? VisitCollectionExpressionElementsPlaceholder(ICollectionExpressionElementsPlaceholderOperation operation, TArgument argument) => DefaultVisit(operation, argument); } #endregion diff --git a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml index bce513d8429e9..e6439f9758e18 100644 --- a/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml +++ b/src/Compilers/Core/Portable/Operations/OperationInterfaces.xml @@ -3697,7 +3697,7 @@ - + Arguments passed to to , if present. Arguments are in evaluation order. This can @@ -3761,7 +3761,7 @@ - + Represents the elements of a collection expression as they are passed to some construction method From 1bbf7d9181519f42f52890de0aab520a69609216 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 12:10:04 -0800 Subject: [PATCH 09/16] Remove suppression from generated files --- .../Syntax.xml.Internal.Generated.cs | 1 - .../Syntax.xml.Main.Generated.cs | 1 - .../Syntax.xml.Syntax.Generated.cs | 1 - .../CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs | 1 - src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs | 1 - src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs | 1 - src/Compilers/Core/Portable/Generated/Operations.Generated.cs | 1 - .../Source/CSharpSyntaxGenerator/SourceWriter.cs | 1 - .../Source/CSharpSyntaxGenerator/TestWriter.cs | 1 - .../Source/IOperationGenerator/IOperationClassWriter.cs | 1 - 10 files changed, 10 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 4573efd993938..93bbb9d1eb3f1 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 5b3f5c9cfeca2..f14d0e34ce0e0 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index e2f62f11e4d2d..d63f67c258ade 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 074948639dcc5..54fecd24c24ff 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -1,5 +1,4 @@ // -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; diff --git a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs index 92e4b0c3cb7eb..7ec409e282783 100644 --- a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index de106e8bd79dc..08e8f14e0119c 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index bb6191306b4d6..6f8cc2f38ae71 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Generic; using System.Threading; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs index df877f1cff3d6..4555515221a18 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs @@ -42,7 +42,6 @@ private void WriteFileHeader() WriteLine("// "); WriteLine(); WriteLine("#nullable enable"); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using System;"); WriteLine("using System.Collections.Generic;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs index 26e9b88ba94d1..2a8a0f7a471e7 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs @@ -24,7 +24,6 @@ public static void Write(TextWriter writer, Tree tree) private void WriteFile() { WriteLine("// "); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using Microsoft.CodeAnalysis.CSharp.Syntax;"); WriteLine("using Roslyn.Utilities;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index c2f73d09e8948..f87b1ce88bbe4 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -186,7 +186,6 @@ void writeHeader() WriteLine("// See the LICENSE file in the project root for more information."); WriteLine("// < auto-generated />"); WriteLine("#nullable enable"); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed."); } } From bab901b0b039a6fcaf768ee3654988b518eac2c9 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 12:16:56 -0800 Subject: [PATCH 10/16] Break out public APIs into a section in the compiler test plan and add more details. --- docs/contributing/Compiler Test Plan.md | 36 ++++++++++++++----------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/docs/contributing/Compiler Test Plan.md b/docs/contributing/Compiler Test Plan.md index f058d85dbcfde..bc5d9d535755f 100644 --- a/docs/contributing/Compiler Test Plan.md +++ b/docs/contributing/Compiler Test Plan.md @@ -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")]` + - APIs have gone through API review ## Type and members From 7f620b1d09ae54fe2b4a0ba315caadfbafec29e6 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 13:04:20 -0800 Subject: [PATCH 11/16] Revert "Remove suppression from generated files" This reverts commit 1bbf7d9181519f42f52890de0aab520a69609216. --- .../Syntax.xml.Internal.Generated.cs | 1 + .../Syntax.xml.Main.Generated.cs | 1 + .../Syntax.xml.Syntax.Generated.cs | 1 + .../CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs | 1 + src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs | 1 + src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs | 1 + src/Compilers/Core/Portable/Generated/Operations.Generated.cs | 1 + .../Source/CSharpSyntaxGenerator/SourceWriter.cs | 1 + .../Source/CSharpSyntaxGenerator/TestWriter.cs | 1 + .../Source/IOperationGenerator/IOperationClassWriter.cs | 1 + 10 files changed, 10 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 93bbb9d1eb3f1..4573efd993938 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index f14d0e34ce0e0..5b3f5c9cfeca2 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index d63f67c258ade..e2f62f11e4d2d 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -1,6 +1,7 @@ // #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 54fecd24c24ff..074948639dcc5 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -1,4 +1,5 @@ // +#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; diff --git a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs index 7ec409e282783..92e4b0c3cb7eb 100644 --- a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index 08e8f14e0119c..de106e8bd79dc 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index 6f8cc2f38ae71..bb6191306b4d6 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable +#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Generic; using System.Threading; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs index 4555515221a18..df877f1cff3d6 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs @@ -42,6 +42,7 @@ private void WriteFileHeader() WriteLine("// "); WriteLine(); WriteLine("#nullable enable"); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using System;"); WriteLine("using System.Collections.Generic;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs index 2a8a0f7a471e7..26e9b88ba94d1 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs @@ -24,6 +24,7 @@ public static void Write(TextWriter writer, Tree tree) private void WriteFile() { WriteLine("// "); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using Microsoft.CodeAnalysis.CSharp.Syntax;"); WriteLine("using Roslyn.Utilities;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index f87b1ce88bbe4..c2f73d09e8948 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -186,6 +186,7 @@ void writeHeader() WriteLine("// See the LICENSE file in the project root for more information."); WriteLine("// < auto-generated />"); WriteLine("#nullable enable"); + WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed."); } } From da1a98fe26ab1dafd7fb2131e1a34235f65b7979 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 15:08:47 -0800 Subject: [PATCH 12/16] Remove generation from the operation generator. --- src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs | 1 - src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs | 1 - src/Compilers/Core/Portable/Generated/Operations.Generated.cs | 1 - .../Source/IOperationGenerator/IOperationClassWriter.cs | 1 - 4 files changed, 4 deletions(-) diff --git a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs index 92e4b0c3cb7eb..7ec409e282783 100644 --- a/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/FlowAnalysis.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Immutable; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs index de106e8bd79dc..08e8f14e0119c 100644 --- a/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/OperationKind.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.ComponentModel; using System.Diagnostics.CodeAnalysis; diff --git a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs index bb6191306b4d6..6f8cc2f38ae71 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.Generated.cs @@ -3,7 +3,6 @@ // See the LICENSE file in the project root for more information. // < auto-generated /> #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed. using System; using System.Collections.Generic; using System.Threading; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index c2f73d09e8948..f87b1ce88bbe4 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -186,7 +186,6 @@ void writeHeader() WriteLine("// See the LICENSE file in the project root for more information."); WriteLine("// < auto-generated />"); WriteLine("#nullable enable"); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed."); } } From ab2f266b6d54e166c0a1bd2ff3f3daf821822a02 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 15:23:38 -0800 Subject: [PATCH 13/16] Mark SyntaxKind.WithElement as experimental. --- src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs index ebfab2785ee04..191392dc1278e 100644 --- a/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs +++ b/src/Compilers/CSharp/Portable/Syntax/SyntaxKind.cs @@ -2,9 +2,12 @@ // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. +using System.Diagnostics.CodeAnalysis; + namespace Microsoft.CodeAnalysis.CSharp { #pragma warning disable CA1200 // Avoid using cref tags with a prefix - The prefix is required since this file is referenced in projects that can't access syntax nodes + // When adding new experimental kinds, you will need to manually specify RSEXPERIMENTAL006, as not all projects that reference this file have RoslynExperiments available. // DO NOT CHANGE NUMBERS ASSIGNED TO EXISTING KINDS OR YOU WILL BREAK BINARY COMPATIBILITY public enum SyntaxKind : ushort { @@ -933,6 +936,7 @@ public enum SyntaxKind : ushort IgnoredDirectiveTrivia = 9080, + [Experimental("RSEXPERIMENTAL006", UrlFormat = "https://github.com/dotnet/roslyn/issues/82210")] WithElement = 9081, } } From 364ec385da607e695c1fd9903cd4328b8d4df466 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 15:42:05 -0800 Subject: [PATCH 14/16] Fix public api bug that was not looking for experimental on containing properties. --- .../DeclarePublicApiAnalyzer.Impl.cs | 8 +- .../DeclarePublicAPIAnalyzerTestsBase.cs | 106 ++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) diff --git a/src/RoslynAnalyzers/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs b/src/RoslynAnalyzers/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs index a491bae5f2327..8c8619c8ba380 100644 --- a/src/RoslynAnalyzers/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs +++ b/src/RoslynAnalyzers/PublicApiAnalyzers/Core/Analyzers/DeclarePublicApiAnalyzer.Impl.cs @@ -603,6 +603,7 @@ private ApiName GetApiName(ISymbol symbol) { for (var current = symbol; current is not null; current = current.ContainingSymbol) { +start: foreach (var attribute in current.GetAttributes()) { if (attribute.AttributeClass is { Name: "ExperimentalAttribute", ContainingSymbol: INamespaceSymbol { Name: nameof(System.Diagnostics.CodeAnalysis), ContainingNamespace: { Name: nameof(System.Diagnostics), ContainingNamespace: { Name: nameof(System), ContainingNamespace.IsGlobalNamespace: true } } } }) @@ -611,9 +612,14 @@ private ApiName GetApiName(ISymbol symbol) return "???"; return diagnosticId; - } } + + if (current is IMethodSymbol { AssociatedSymbol: { } associatedSymbol }) + { + current = associatedSymbol; + goto start; + } } return null; diff --git a/src/RoslynAnalyzers/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs b/src/RoslynAnalyzers/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs index 3e1174ef8e70c..02833097f4d57 100644 --- a/src/RoslynAnalyzers/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs +++ b/src/RoslynAnalyzers/PublicApiAnalyzers/UnitTests/DeclarePublicAPIAnalyzerTestsBase.cs @@ -2783,6 +2783,112 @@ public Task TestExperimentalApiAsync() [ID1]C.C() -> void """); + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_PropertyAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System.Diagnostics.CodeAnalysis; + + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + [Experimental("ID1")] + {{EnabledModifierCSharp}} int Property { {|{{AddNewApiId}}:get|}; {|{{AddNewApiId}}:set|}; } + } + """, @"", @"", """ + C + C.C() -> void + [ID1]C.Property.get -> int + [ID1]C.Property.set -> void + """); + + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_PropertyGetterOnlyAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System.Diagnostics.CodeAnalysis; + + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + [Experimental("ID1")] + {{EnabledModifierCSharp}} int Property { {|{{AddNewApiId}}:get|}; } + } + """, @"", @"", """ + C + C.C() -> void + [ID1]C.Property.get -> int + """); + + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_PropertySetterOnlyAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System.Diagnostics.CodeAnalysis; + + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + [Experimental("ID1")] + {{EnabledModifierCSharp}} int Property { {|{{AddNewApiId}}:set|} { } } + } + """, @"", @"", """ + C + C.C() -> void + [ID1]C.Property.set -> void + """); + + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_IndexerAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System.Diagnostics.CodeAnalysis; + + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + [Experimental("ID1")] + {{EnabledModifierCSharp}} int this[int index] { {|{{AddNewApiId}}:get|} => 0; {|{{AddNewApiId}}:set|} { } } + } + """, @"", @"", """ + C + C.C() -> void + [ID1]C.this[int index].get -> int + [ID1]C.this[int index].set -> void + """); + + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_EventAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System; + using System.Diagnostics.CodeAnalysis; + + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + [Experimental("ID1")] + {{EnabledModifierCSharp}} event EventHandler {|{{AddNewApiId}}:MyEvent|}; + } + """, @"", @"", """ + C + C.C() -> void + [ID1]C.MyEvent -> System.EventHandler + """); + + [Fact] + [WorkItem(82131, "https://github.com/dotnet/roslyn/pull/82131")] + public Task TestExperimentalApi_PropertyInExperimentalClassAsync() + => VerifyNet80CSharpAdditionalFileFixAsync($$""" + using System.Diagnostics.CodeAnalysis; + + [Experimental("ID1")] + {{EnabledModifierCSharp}} class {|{{AddNewApiId}}:{|{{AddNewApiId}}:C|}|} + { + {{EnabledModifierCSharp}} int Property { {|{{AddNewApiId}}:get|}; {|{{AddNewApiId}}:set|}; } + } + """, @"", @"", """ + [ID1]C + [ID1]C.C() -> void + [ID1]C.Property.get -> int + [ID1]C.Property.set -> void + """); + [Theory] [InlineData("")] [InlineData("null")] From 1e4c68f15d5a4f7e17eb28c6695542cca662f163 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Thu, 29 Jan 2026 16:59:23 -0800 Subject: [PATCH 15/16] Fix api file --- src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 9caa2458488fe..809b435bda6fd 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,6 +1,6 @@ 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 [RSEXPERIMENTAL006]Microsoft.CodeAnalysis.CSharp.Syntax.WithElementSyntax From 5699f278ffb149dc9c0d4c61a63a9122b2ba2d67 Mon Sep 17 00:00:00 2001 From: Fred Silberberg Date: Fri, 13 Feb 2026 16:59:52 -0800 Subject: [PATCH 16/16] PR feedback --- .editorconfig | 3 --- .globalconfig | 2 ++ docs/contributing/Compiler Test Plan.md | 2 +- .../Syntax.xml.Internal.Generated.cs | 1 - .../Syntax.xml.Main.Generated.cs | 1 - .../Syntax.xml.Syntax.Generated.cs | 1 - src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs | 2 +- .../Test/Syntax/Generated/Syntax.Test.xml.Generated.cs | 1 - .../Source/CSharpSyntaxGenerator/SourceWriter.cs | 1 - .../Source/CSharpSyntaxGenerator/TestWriter.cs | 1 - .../Source/IOperationGenerator/IOperationClassWriter.cs | 5 +---- 11 files changed, 5 insertions(+), 15 deletions(-) create mode 100644 .globalconfig diff --git a/.editorconfig b/.editorconfig index 6c9296ba46ef7..e95967a09e126 100644 --- a/.editorconfig +++ b/.editorconfig @@ -167,9 +167,6 @@ dotnet_diagnostic.xUnit2020.severity = none dotnet_diagnostic.xUnit2023.severity = none dotnet_diagnostic.xUnit2029.severity = none -# RS0006: Roslyn experimental language API -dotnet_diagnostic.RSEXPERIMENTAL006.severity = none - # CSharp code style settings: [*.cs] # Newline settings diff --git a/.globalconfig b/.globalconfig new file mode 100644 index 0000000000000..865b6307a9a72 --- /dev/null +++ b/.globalconfig @@ -0,0 +1,2 @@ +# RS0006: Roslyn experimental language API +dotnet_diagnostic.RSEXPERIMENTAL006.severity = none diff --git a/docs/contributing/Compiler Test Plan.md b/docs/contributing/Compiler Test Plan.md index bc5d9d535755f..6cd648a432389 100644 --- a/docs/contributing/Compiler Test Plan.md +++ b/docs/contributing/Compiler Test Plan.md @@ -51,7 +51,7 @@ This document provides guidance for thinking about language interactions and tes - DocumentationCommentId APIs - 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")]` + - APIs are marked with `[Experimental(RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = "link to tracking issue")]` - APIs have gone through API review ## Type and members diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs index 4573efd993938..93bbb9d1eb3f1 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Internal.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs index 5b3f5c9cfeca2..f14d0e34ce0e0 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Main.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs index e2f62f11e4d2d..d63f67c258ade 100644 --- a/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs +++ b/src/Compilers/CSharp/Portable/Generated/CSharpSyntaxGenerator/CSharpSyntaxGenerator.SourceGenerator/Syntax.xml.Syntax.Generated.cs @@ -1,7 +1,6 @@ // #nullable enable -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using System; using System.Collections.Generic; diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index faa9fd016ed60..c9f18f5e87683 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -1723,7 +1723,7 @@ public void LanguageVersionAdded_Canary() // - [ ] update _MaxAvailableLangVersion cap (a relevant test should break when new version is introduced) // - [ ] update the "UpgradeProject" codefixer // - [ ] Remove the `ExperimentalUrl` section from any entries for language features being shipped in Syntax.xml and OperationInterfaces.xml, and rerun the generator - // - [ ] Search the codebase for the URLs that were linked in the Syntax.xml and OperationInterfaces.xml files and remove suppressions or attributes added for those issues. + // - [ ] Search the codebase for references tied to issues linked from Syntax.xml and OperationInterfaces.xml, and remove suppressions or attributes added for those issues. // - [ ] test VS insertion and deal with breaking changes. (note: the runtime repo uses "preview" so breaks are resolved sooner) // // Other repos also need updates: diff --git a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs index 074948639dcc5..54fecd24c24ff 100644 --- a/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs +++ b/src/Compilers/CSharp/Test/Syntax/Generated/Syntax.Test.xml.Generated.cs @@ -1,5 +1,4 @@ // -#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API using Microsoft.CodeAnalysis.CSharp.Syntax; using Roslyn.Utilities; diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs index df877f1cff3d6..4555515221a18 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/SourceWriter.cs @@ -42,7 +42,6 @@ private void WriteFileHeader() WriteLine("// "); WriteLine(); WriteLine("#nullable enable"); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using System;"); WriteLine("using System.Collections.Generic;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs index 26e9b88ba94d1..2a8a0f7a471e7 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/CSharpSyntaxGenerator/TestWriter.cs @@ -24,7 +24,6 @@ public static void Write(TextWriter writer, Tree tree) private void WriteFile() { WriteLine("// "); - WriteLine("#pragma warning disable RSEXPERIMENTAL006 // Preview language feature API"); WriteLine(); WriteLine("using Microsoft.CodeAnalysis.CSharp.Syntax;"); WriteLine("using Roslyn.Utilities;"); diff --git a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs index f87b1ce88bbe4..22bfb75f08b01 100644 --- a/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs +++ b/src/Tools/Source/CompilerGeneratorTools/Source/IOperationGenerator/IOperationClassWriter.cs @@ -27,9 +27,6 @@ internal sealed partial class IOperationClassWriter private readonly Tree _tree; private readonly Dictionary _typeMap; - private static string QuoteString(string value) - => "@\"" + value.Replace("\"", "\"\"") + "\""; - private IOperationClassWriter(Tree tree, string location) { _tree = tree; @@ -388,7 +385,7 @@ void writeEnumElement(string kind, int value, string operationName, string? extr if (!string.IsNullOrEmpty(experimentalUrl)) { - WriteLine($"[Experimental(global::Microsoft.CodeAnalysis.RoslynExperiments.PreviewLanguageFeatureApi, UrlFormat = {QuoteString(experimentalUrl)})]"); + WriteExperimentalAttribute(experimentalUrl); } if (obsoleteMessage is object)