From 5572d51ccb84e37faf54d1f64390d1559852ff69 Mon Sep 17 00:00:00 2001 From: VSadov Date: Fri, 6 May 2016 17:38:05 -0700 Subject: [PATCH] Hide replace/original functionality behind feature flag. Since "original" is by itself contextual on the presence of "replace", only "replace" actually needs to be keyed off a flag. --- .../CSharp/Portable/CSharpParseOptions.cs | 1 + .../Portable/CSharpResources.Designer.cs | 9 ++++++++ .../CSharp/Portable/CSharpResources.resx | 3 +++ .../CSharp/Portable/Errors/MessageID.cs | 3 +++ .../CSharp/Portable/Parser/LanguageParser.cs | 1 + .../Symbol/Symbols/ReplaceOriginalTests.cs | 10 +++++++++ .../Syntax/Parsing/ReplaceParsingTests.cs | 21 +++++++++++++++---- .../Utilities/CSharp.Desktop/TestOptions.cs | 5 +++++ .../Test/Utilities/CSharp/TestOptions.cs | 5 +++++ 9 files changed, 54 insertions(+), 4 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs index f43c0414f027d..5e882e7850167 100644 --- a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs +++ b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs @@ -219,6 +219,7 @@ internal bool IsFeatureEnabled(MessageID feature) case MessageID.IDS_FeatureRefLocalsReturns: case MessageID.IDS_FeaturePatternMatching: case MessageID.IDS_FeatureTuples: + case MessageID.IDS_FeatureReplace: // in "demo" mode enable proposed new C# 7 language features. if (PreprocessorSymbols.Contains("__DEMO__")) { diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 92a3b4d441126..6b1ff3ab33a94 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -9773,6 +9773,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to replaced members. + /// + internal static string IDS_FeatureReplace { + get { + return ResourceManager.GetString("IDS_FeatureReplace", resourceCulture); + } + } + /// /// Looks up a localized string similar to static classes. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index f4cc3f0d769ef..f6cfb070583d7 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -240,6 +240,9 @@ partial method + + replaced members + method diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index d72c42534c81b..3ce1c3fabbfe9 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -119,6 +119,7 @@ internal enum MessageID IDS_FeatureRefLocalsReturns = MessageBase + 12710, IDS_FeatureTuples = MessageBase + 12711, + IDS_FeatureReplace = MessageBase + 12712, } // Message IDs may refer to strings that need to be localized. @@ -174,6 +175,8 @@ internal static string RequiredFeature(this MessageID feature) return "patterns"; case MessageID.IDS_FeatureTuples: return "tuples"; + case MessageID.IDS_FeatureReplace: + return "replace"; default: return null; } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 3e08abd0212f5..6caf84698b231 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -1400,6 +1400,7 @@ private void ParseModifiers(SyntaxListBuilder tokens) if (ShouldCurrentContextualKeywordBeTreatedAsModifier()) { modTok = ConvertToKeyword(this.EatToken()); + modTok = CheckFeatureAvailability(modTok, MessageID.IDS_FeatureReplace); break; } return; diff --git a/src/Compilers/CSharp/Test/Symbol/Symbols/ReplaceOriginalTests.cs b/src/Compilers/CSharp/Test/Symbol/Symbols/ReplaceOriginalTests.cs index cc8df7d475045..b9b04faac55cd 100644 --- a/src/Compilers/CSharp/Test/Symbol/Symbols/ReplaceOriginalTests.cs +++ b/src/Compilers/CSharp/Test/Symbol/Symbols/ReplaceOriginalTests.cs @@ -14,6 +14,16 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests.Symbols { public class ReplaceOriginalTests : CSharpTestBase { + private static CSharpCompilation CreateCompilationWithMscorlib(string text) + { + return CreateCompilationWithMscorlib(text, parseOptions: TestOptions.Regular.WithReplaceFeature()); + } + + private static CSharpCompilation CreateCompilationWithMscorlib(string text, CSharpCompilationOptions options) + { + return CreateCompilationWithMscorlib(text, options: options, parseOptions: TestOptions.Regular.WithReplaceFeature()); + } + [WorkItem(11123, "https://github.com/dotnet/roslyn/issues/11123")] [Fact] public void Members() diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ReplaceParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ReplaceParsingTests.cs index ee42fcbb147a5..753aa14b3af07 100644 --- a/src/Compilers/CSharp/Test/Syntax/Parsing/ReplaceParsingTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ReplaceParsingTests.cs @@ -4,15 +4,17 @@ using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.CSharp.Symbols; using Xunit; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; +using System; namespace Microsoft.CodeAnalysis.CSharp.UnitTests { - public class ReplaceParsingTests + public class ReplaceParsingTests: CSharpTestBase { [Fact] public void ReplaceClass() { - var root = SyntaxFactory.ParseCompilationUnit("abstract replace override class C { }"); + var root = SyntaxFactory.ParseCompilationUnit("abstract replace override class C { }", options: TestOptions.Regular.WithReplaceFeature()); root.Errors().Verify(); var type = (TypeDeclarationSyntax)root.Members[0]; Assert.Equal( @@ -23,7 +25,7 @@ public void ReplaceClass() [Fact] public void ReplaceMethod() { - var root = SyntaxFactory.ParseCompilationUnit("class C { virtual replace protected void M() { } }"); + var root = SyntaxFactory.ParseCompilationUnit("class C { virtual replace protected void M() { } }", options: TestOptions.Regular.WithReplaceFeature()); root.Errors().Verify(); var type = (TypeDeclarationSyntax)root.Members[0]; Assert.Equal( @@ -35,6 +37,17 @@ public void ReplaceMethod() DeclarationModifiers.Virtual | DeclarationModifiers.Protected | DeclarationModifiers.Replace); } + [Fact] + public void ReplaceMethodNoFeature() + { + var source = "class C { virtual replace protected void M() { } }"; + CreateCompilationWithMscorlib(source, options: TestOptions.DebugDll).VerifyDiagnostics( + // (1,19): error CS8058: Feature 'replaced members' is experimental and unsupported; use '/features:replace' to enable. + // class C { virtual replace protected void M() { } } + Diagnostic(ErrorCode.ERR_FeatureIsExperimental, "replace").WithArguments("replaced members", "replace").WithLocation(1, 19) + ); + } + [Fact] public void OriginalExpression() { @@ -72,7 +85,7 @@ public void OriginalInReplace() private void OriginalInMember(string text, bool inReplace) { - var tree = SyntaxFactory.ParseSyntaxTree(text); + var tree = SyntaxFactory.ParseSyntaxTree(text, options: TestOptions.Regular.WithReplaceFeature()); var root = tree.GetCompilationUnitRoot(); root.Errors().Verify(); var token = root.DescendantTokens().Where(t => t.Text == "original").Single(); diff --git a/src/Compilers/Test/Utilities/CSharp.Desktop/TestOptions.cs b/src/Compilers/Test/Utilities/CSharp.Desktop/TestOptions.cs index 77dbfbf09eb6e..45b01b53eda23 100644 --- a/src/Compilers/Test/Utilities/CSharp.Desktop/TestOptions.cs +++ b/src/Compilers/Test/Utilities/CSharp.Desktop/TestOptions.cs @@ -68,5 +68,10 @@ public static CSharpParseOptions WithPatternsFeature(this CSharpParseOptions opt { return options.WithFeature("patterns", "true"); } + + public static CSharpParseOptions WithReplaceFeature(this CSharpParseOptions options) + { + return options.WithFeature("replace", "true"); + } } } diff --git a/src/Compilers/Test/Utilities/CSharp/TestOptions.cs b/src/Compilers/Test/Utilities/CSharp/TestOptions.cs index dc9ea7dd114a2..4d7ff8eca641a 100644 --- a/src/Compilers/Test/Utilities/CSharp/TestOptions.cs +++ b/src/Compilers/Test/Utilities/CSharp/TestOptions.cs @@ -69,5 +69,10 @@ public static CSharpParseOptions WithTuplesFeature(this CSharpParseOptions optio { return options.WithFeature("tuples", "true"); } + + public static CSharpParseOptions WithReplaceFeature(this CSharpParseOptions options) + { + return options.WithFeature("replace", "true"); + } } }