From 1d8c2c8fbdadb303604e22887172658b6212768d Mon Sep 17 00:00:00 2001 From: Evan Hauck Date: Thu, 4 Jun 2015 10:16:33 -0700 Subject: [PATCH] Enable feature flag for local functions --- .../Portable/CSharpResources.Designer.cs | 9 +++ .../CSharp/Portable/CSharpResources.resx | 3 + .../CSharp/Portable/Errors/MessageID.cs | 4 ++ .../CSharp/Portable/Parser/LanguageParser.cs | 3 +- .../DiagnosticAnalyzerTests.AllInOne.cs | 6 +- .../Semantic/Semantics/LocalFunctionTests.cs | 57 ++++++++++++------- .../Syntax/Syntax/SyntaxAnnotationTests.cs | 16 +++--- .../Test/Utilities/CSharp/TestOptions.cs | 2 +- src/Test/Utilities/TestResource.Designer.cs | 2 +- src/Test/Utilities/TestResource.resx | 4 ++ 10 files changed, 73 insertions(+), 33 deletions(-) diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 216abf14dd7..2d2e1e5c0ae 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -8999,6 +8999,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to local functions. + /// + internal static string IDS_FeatureLocalFunctions { + get { + return ResourceManager.GetString("IDS_FeatureLocalFunctions", resourceCulture); + } + } + /// /// Looks up a localized string similar to module as an attribute target specifier. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index aeabf8e8fc0..f7f82362911 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -4599,6 +4599,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ await in catch blocks and finally blocks + + local functions + A '{0}' character must be escaped (by doubling) in an interpolated string. diff --git a/src/Compilers/CSharp/Portable/Errors/MessageID.cs b/src/Compilers/CSharp/Portable/Errors/MessageID.cs index 04a7f1774a0..b78459d9b60 100644 --- a/src/Compilers/CSharp/Portable/Errors/MessageID.cs +++ b/src/Compilers/CSharp/Portable/Errors/MessageID.cs @@ -112,6 +112,7 @@ internal enum MessageID IDS_OperationCausedStackOverflow = MessageBase + 12703, IDS_AwaitInCatchAndFinally = MessageBase + 12704, + IDS_FeatureLocalFunctions = MessageBase + 12705, } // Message IDs may refer to strings that need to be localized. @@ -149,6 +150,9 @@ internal static string RequiredFeature(this MessageID feature) { switch (feature) { + case MessageID.IDS_FeatureLocalFunctions: + return "localFunctions"; + default: return null; } diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs index 35857bea46a..1a43ac4ca8e 100644 --- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs +++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs @@ -7938,8 +7938,9 @@ private StatementSyntax ParseLocalDeclarationStatement() try { this.ParseDeclarationModifiers(mods); + var allowLocalFunctions = IsFeatureEnabled(MessageID.IDS_FeatureLocalFunctions); LocalFunctionStatementSyntax localFunction; - this.ParseDeclaration(out type, variables, true, mods.ToTokenList(), out localFunction); + this.ParseDeclaration(out type, variables, allowLocalFunctions, mods.ToTokenList(), out localFunction); if (localFunction != null) { Debug.Assert(variables.Count == 0); diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs index fe8bc0056ae..e8cc8c259e3 100644 --- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs +++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/DiagnosticAnalyzerTests.AllInOne.cs @@ -26,7 +26,7 @@ public void DiagnosticAnalyzerAllInOne() symbolKindsWithNoCodeBlocks.Add(SymbolKind.NamedType); var analyzer = new CSharpTrackingDiagnosticAnalyzer(); - CreateCompilationWithMscorlib45(source, parseOptions: TestOptions.Regular).VerifyAnalyzerDiagnostics(new[] { analyzer }); + CreateExperimentalCompilationWithMscorlib45(source).VerifyAnalyzerDiagnostics(new[] { analyzer }); analyzer.VerifyAllAnalyzerMembersWereCalled(); analyzer.VerifyAnalyzeSymbolCalledForAllSymbolKinds(); analyzer.VerifyAnalyzeNodeCalledForAllSyntaxKinds(); @@ -85,7 +85,7 @@ public class C [WorkItem(759)] public void AnalyzerDriverIsSafeAgainstAnalyzerExceptions() { - var compilation = CreateCompilationWithMscorlib45(TestResource.AllInOneCSharpCode, parseOptions: TestOptions.Regular); + var compilation = CreateExperimentalCompilationWithMscorlib45(TestResource.AllInOneCSharpCode); ThrowingDiagnosticAnalyzer.VerifyAnalyzerEngineIsSafeAgainstExceptions(analyzer => compilation.GetAnalyzerDiagnostics(new[] { analyzer }, null, logAnalyzerExceptionAsDiagnostics: true)); } @@ -99,7 +99,7 @@ public void AnalyzerOptionsArePassedToAllAnalyzers() new[] { new TestAdditionalText("myfilepath", text) }.ToImmutableArray() ); - var compilation = CreateCompilationWithMscorlib45(TestResource.AllInOneCSharpCode, parseOptions: TestOptions.Regular); + var compilation = CreateExperimentalCompilationWithMscorlib45(TestResource.AllInOneCSharpCode); var analyzer = new OptionsDiagnosticAnalyzer(options); compilation.GetAnalyzerDiagnostics(new[] { analyzer }, options); analyzer.VerifyAnalyzerOptions(); diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs index 516a761dc01..757317e7868 100644 --- a/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/Semantics/LocalFunctionTests.cs @@ -7,6 +7,8 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests { public class LocalFunctionTests : CSharpTestBase { + private readonly CSharpParseOptions _parseOptions = TestOptions.Regular.WithFeatures(new SmallDictionary { { "localFunctions", "true" } }); + [Fact] public void EndToEnd() { @@ -25,7 +27,8 @@ void Local() } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" Hello, world! "); } @@ -45,7 +48,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -83,7 +87,8 @@ void NamedOptional(int x = 2) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 2 2 @@ -137,7 +142,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 2 "); @@ -165,7 +171,8 @@ void Local2() } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 2 "); @@ -196,7 +203,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 1 2 "); @@ -234,7 +242,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 6 "); } @@ -267,7 +276,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -296,7 +306,8 @@ void Foo(int depth) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -328,7 +339,8 @@ void Bar(int depth2) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -368,7 +380,8 @@ IEnumerator LocalEnumerator() } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 2 2 @@ -395,7 +408,9 @@ async Task Local() } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: new CSharpCompilationOptions(OutputKind.ConsoleApplication)); + var compilation = CreateCompilationWithMscorlib45(source, + options: new CSharpCompilationOptions(OutputKind.ConsoleApplication), + parseOptions: _parseOptions); var comp = CompileAndVerify(compilation, expectedOutput: @" 2 "); @@ -421,7 +436,9 @@ async Task Local(int x) } } "; - var compilation = CreateCompilationWithMscorlib45(source, options: new CSharpCompilationOptions(OutputKind.ConsoleApplication)); + var compilation = CreateCompilationWithMscorlib45(source, + options: new CSharpCompilationOptions(OutputKind.ConsoleApplication), + parseOptions: _parseOptions); var comp = CompileAndVerify(compilation, expectedOutput: @" 2 "); @@ -480,7 +497,8 @@ static void Main(string[] args) } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -509,7 +527,8 @@ void Local() } } "; - var comp = CompileAndVerify(source, expectedOutput: @" + var comp = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe, parseOptions: _parseOptions); + var verify = CompileAndVerify(comp, expectedOutput: @" 2 "); } @@ -531,7 +550,7 @@ void Local1() } "; var option = TestOptions.ReleaseExe.WithWarningLevel(0); - CreateCompilationWithMscorlibAndSystemCore(source, options: option).VerifyDiagnostics( + CreateCompilationWithMscorlibAndSystemCore(source, options: option, parseOptions: _parseOptions).VerifyDiagnostics( // (9,22): error CS1002: ; expected // void Local1() Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(9, 22), @@ -565,7 +584,7 @@ IEnumerable Local(ref int x) } "; var option = TestOptions.ReleaseExe.WithWarningLevel(0); - CreateCompilationWithMscorlibAndSystemCore(source, options: option).VerifyDiagnostics( + CreateCompilationWithMscorlibAndSystemCore(source, options: option, parseOptions: _parseOptions).VerifyDiagnostics( // (9,40): error CS1623: Iterators cannot have ref or out parameters // IEnumerable Local(ref int x) Diagnostic(ErrorCode.ERR_BadIteratorArgType, "x").WithLocation(9, 40) @@ -592,7 +611,7 @@ IEnumerable Local(__arglist) } "; var option = TestOptions.ReleaseExe.WithWarningLevel(0); - CreateCompilationWithMscorlibAndSystemCore(source, options: option).VerifyDiagnostics( + CreateCompilationWithMscorlibAndSystemCore(source, options: option, parseOptions: _parseOptions).VerifyDiagnostics( // (9,26): error CS1636: __arglist is not allowed in the parameter list of iterators // IEnumerable Local(__arglist) Diagnostic(ErrorCode.ERR_VarargsIterator, "Local").WithLocation(9, 26) @@ -616,7 +635,7 @@ static void Main(string[] args) } "; var option = TestOptions.ReleaseExe.WithWarningLevel(0); - CreateCompilationWithMscorlibAndSystemCore(source, options: option).VerifyDiagnostics( + CreateCompilationWithMscorlibAndSystemCore(source, options: option, parseOptions: _parseOptions).VerifyDiagnostics( // (9,27): error CS0841: Cannot use local variable 'Local' before it is declared // Console.WriteLine(Local()); Diagnostic(ErrorCode.ERR_VariableUsedBeforeDeclaration, "Local").WithArguments("Local").WithLocation(9, 27) diff --git a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxAnnotationTests.cs b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxAnnotationTests.cs index 4e07d6fb4b6..342a3de8918 100644 --- a/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxAnnotationTests.cs +++ b/src/Compilers/CSharp/Test/Syntax/Syntax/SyntaxAnnotationTests.cs @@ -125,7 +125,7 @@ public void TestCopyAnnotationOfZeroLengthToSyntaxTrivia() public void TestMissingAnnotationsOnNodesOrTokens() { SyntaxAnnotation annotation = new SyntaxAnnotation(); - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); var matchingNodesOrTokens = tree.GetCompilationUnitRoot().GetAnnotatedNodesAndTokens(annotation); Assert.Empty(matchingNodesOrTokens); @@ -135,7 +135,7 @@ public void TestMissingAnnotationsOnNodesOrTokens() public void TestMissingAnnotationsOnTrivia() { SyntaxAnnotation annotation = new SyntaxAnnotation(); - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); var matchingTrivia = tree.GetCompilationUnitRoot().GetAnnotatedTrivia(annotation); Assert.Empty(matchingTrivia); @@ -298,7 +298,7 @@ public void TestIfNodeHasAnnotations() [Fact] public void TestCSharpAllInOne() { - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); TestAnnotation(tree); } @@ -306,7 +306,7 @@ public void TestCSharpAllInOne() [Fact] public void TestCSharpAllInOneRandom() { - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); TestRandomAnnotations(tree); } @@ -314,7 +314,7 @@ public void TestCSharpAllInOneRandom() [Fact] public void TestCSharpAllInOneManyRandom() { - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); TestManyRandomAnnotations(tree); } @@ -322,7 +322,7 @@ public void TestCSharpAllInOneManyRandom() [Fact] public void TestCSharpAllInOneTrivia() { - var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); TestTriviaAnnotation(tree); } @@ -330,8 +330,8 @@ public void TestCSharpAllInOneTrivia() [Fact] public void TestCopyAnnotations1() { - var tree1 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); - var tree2 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.Regular); + var tree1 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); + var tree2 = SyntaxFactory.ParseSyntaxTree(_allInOneCSharpCode, options: Test.Utilities.TestOptions.ExperimentalParseOptions); TestCopyAnnotations(tree1, tree2); } diff --git a/src/Compilers/Test/Utilities/CSharp/TestOptions.cs b/src/Compilers/Test/Utilities/CSharp/TestOptions.cs index c5e5ddefdbc..e80722fef6f 100644 --- a/src/Compilers/Test/Utilities/CSharp/TestOptions.cs +++ b/src/Compilers/Test/Utilities/CSharp/TestOptions.cs @@ -15,7 +15,7 @@ public static class TestOptions public static readonly CSharpParseOptions Regular = new CSharpParseOptions(kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.None); public static readonly CSharpParseOptions RegularWithDocumentationComments = new CSharpParseOptions(kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.Diagnose); - private static readonly SmallDictionary s_experimentalFeatures = new SmallDictionary(); // no experimental features to enable + private static readonly SmallDictionary s_experimentalFeatures = new SmallDictionary { { "localFunctions", "true" } }; public static readonly CSharpParseOptions ExperimentalParseOptions = new CSharpParseOptions(kind: SourceCodeKind.Regular, documentationMode: DocumentationMode.None, languageVersion: LanguageVersion.CSharp6).WithFeatures(s_experimentalFeatures); diff --git a/src/Test/Utilities/TestResource.Designer.cs b/src/Test/Utilities/TestResource.Designer.cs index 821bf5815bc..4fa573a8b42 100644 --- a/src/Test/Utilities/TestResource.Designer.cs +++ b/src/Test/Utilities/TestResource.Designer.cs @@ -1,7 +1,7 @@ //------------------------------------------------------------------------------ // // This code was generated by a tool. -// Runtime Version:4.0.30319.0 +// Runtime Version:4.0.30319.42000 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. diff --git a/src/Test/Utilities/TestResource.resx b/src/Test/Utilities/TestResource.resx index 92b03dc3041..2f9550e2e8f 100644 --- a/src/Test/Utilities/TestResource.resx +++ b/src/Test/Utilities/TestResource.resx @@ -196,6 +196,10 @@ namespace My var s2 = $@"x {1 , -2 :d}"; } + int LocalFunction() + { + } + #if DEBUG Console.WriteLine(export.iefSupplied.command); #endif -- GitLab