From c830f88e093d8753e92e7f1054393e456e6fac20 Mon Sep 17 00:00:00 2001 From: Neal Gafter Date: Wed, 27 Jul 2016 20:54:45 -0700 Subject: [PATCH] Introduce a "Latest" language version, which maps to the latest supported language version when used in APIs. Also update the C# 7 feature status doc to bring it up-to-date. We also change the default language version for VB from 14 to 15, and put the binary literals and digit separators under language version 15. This PR takes the approach of immediately transforming a "Latest" language version to the actual latest language version. Thus, the extra enum value should never be persisted as part of an options object, but only transiently appear as an argument to an API call setting or resetting the language version. --- docs/Language Feature Status.md | 18 +++++----- .../CSharp/Portable/CSharpParseOptions.cs | 8 +++-- .../CommandLine/CSharpCommandLineParser.cs | 19 ++++++++-- .../CSharp/Portable/LanguageVersion.cs | 11 ++++++ .../CSharp/Portable/PublicAPI.Unshipped.txt | 3 +- .../Test/CommandLine/CommandLineTests.cs | 35 +++++++++++-------- .../VisualBasicCommandLineParser.vb | 4 ++- .../Compilation/VisualBasicCompilation.vb | 2 +- .../VisualBasic/Portable/LanguageVersion.vb | 6 ++++ .../Portable/Parser/ParserFeature.vb | 10 +++--- .../Portable/PublicAPI.Shipped.txt | 1 - .../Portable/PublicAPI.Unshipped.txt | 4 ++- .../VisualBasic/Portable/VBResources.resx | 8 ++--- .../Portable/VisualBasicParseOptions.vb | 9 ++--- .../Test/CommandLine/CommandLineTests.vb | 8 +++++ .../Parser/VisualBasicParseOptionsTests.vb | 11 ++++++ .../Test/Syntax/Scanner/ScannerTests.vb | 9 ++--- 17 files changed, 113 insertions(+), 53 deletions(-) diff --git a/docs/Language Feature Status.md b/docs/Language Feature Status.md index 711dc46708c..e1b70661a2c 100644 --- a/docs/Language Feature Status.md +++ b/docs/Language Feature Status.md @@ -1,28 +1,28 @@ # Language Feature Status -This document reflects the status, and planned work, for the compiler team. It is a live document and will be updated as work progresses, features are added / removed, and as work on feature progresses. +This document reflects the status, and planned work, for the compiler team. It is a live document and will be updated as work progresses, features are added / removed, and as work on feature progresses. ## C# 7.0 and VB 15 | Feature | Branch | State | Owners | LDM Champ | | ------- | ------ | ----- | ------ | --------- | -| [Async Main](https://github.com/dotnet/roslyn/issues/7476) | none | Feature Specification | [tyoverby](https://github.com/tyoverby), [agocke](https://github.com/agocke) | [stephentoub](https://github.com/stephentoub) | | Address of Static | none | Feature Specification | | [jaredpar](https://github.com/jaredpar) | | [Binary Literals](https://github.com/dotnet/roslyn/issues/215) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | | [gafter](https://github.com/gafter) | | [Digit Separators](https://github.com/dotnet/roslyn/issues/216) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | | [gafter](https://github.com/gafter) | | [Local Functions](https://github.com/dotnet/roslyn/blob/master/docs/features/local-functions.md) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [agocke](https://github.com/agocke), [jaredpar](https://github.com/jaredpar), [vsadov](https://github.com/vsadov) | [gafter](https://github.com/gafter) | | [Type switch](https://github.com/dotnet/roslyn/blob/master/docs/features/patterns.md) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [gafter](https://github.com/gafter), [alekseyts](https://github.com/alekseyts), [agocke](https://github.com/agocke) | [gafter](https://github.com/gafter) | | [Ref Returns](https://github.com/dotnet/roslyn/issues/118) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [vsadov](https://github.com/vsadov), [agocke](https://github.com/agocke), [jaredpar](https://github.com/jaredpar) | [vsadov](https://github.com/vsadov) | -| [Source Generation](https://github.com/dotnet/roslyn/blob/master/docs/features/generators.md) | [master](https://github.com/dotnet/roslyn/tree/features/generators) | Prototyping | [cston](https://github.com/cston), [vsadov](https://github.com/vsadov), [agocke](https://github.com/agocke) | [mattwar](https://github.com/mattwar) | -| [Throw Expr](https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md) | [features/patterns](https://github.com/dotnet/roslyn/tree/features/patterns) | Finishing | [agocke](https://github.com/agocke), [tyoverby](https://github.com/tyoverby), [gafter](https://github.com/gafter) | [gafter](https://github.com/gafter) | -| [Tuples](https://github.com/dotnet/roslyn/issues/347) | [features/tuples](https://github.com/dotnet/roslyn/tree/features/tuples) | Finishing | [vsadov](https://github.com/vsadov), [jcouv](https://github.com/jcouv) | [madstorgersen](https://github.com/MadsTorgersen) | -| [Out var](https://github.com/dotnet/roslyn/blob/features/outvar/docs/features/outvar.md) | [features/outvar](https://github.com/dotnet/roslyn/tree/features/outvar) | Prototyping | [alekseyts](https://github.com/alekseyts) | [gafter](https://github.com/gafter) | -| [ValueTask](https://github.com/ljw1004/roslyn/blob/features/async-return/docs/specs/feature%20-%20arbitrary%20async%20returns.md) | None | Prototyping | [alekseyts](https://github.com/alekseyts) | [lucian](https://github.com/ljw1004) | +| [Tuples](https://github.com/dotnet/roslyn/issues/347) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [vsadov](https://github.com/vsadov), [jcouv](https://github.com/jcouv) | [madstorgersen](https://github.com/MadsTorgersen) | +| [Out var](https://github.com/dotnet/roslyn/blob/features/outvar/docs/features/outvar.md) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [alekseyts](https://github.com/alekseyts) | [gafter](https://github.com/gafter) | +| [ValueTask](https://github.com/ljw1004/roslyn/blob/features/async-return/docs/specs/feature%20-%20arbitrary%20async%20returns.md) | [master](https://github.com/dotnet/roslyn/tree/master) | Finishing | [alekseyts](https://github.com/alekseyts) | [lucian](https://github.com/ljw1004) | ## (C# 7.0 and VB 15) + 1 | Feature | Branch | State | Owners | LDM Champ | | ------- | ------ | ----- | ------ | --------- | +| [Async Main](https://github.com/dotnet/roslyn/issues/7476) | none | Feature Specification | [tyoverby](https://github.com/tyoverby), [agocke](https://github.com/agocke) | [stephentoub](https://github.com/stephentoub) | +| [Source Generation](https://github.com/dotnet/roslyn/blob/master/docs/features/generators.md) | [master](https://github.com/dotnet/roslyn/tree/features/generators) | Prototyping | [cston](https://github.com/cston), [vsadov](https://github.com/vsadov), [agocke](https://github.com/agocke) | [mattwar](https://github.com/mattwar) | +| [Throw Expr](https://github.com/dotnet/roslyn/blob/features/patterns/docs/features/patterns.md) | [features/patterns](https://github.com/dotnet/roslyn/tree/features/patterns) | Prototyping | [agocke](https://github.com/agocke), [tyoverby](https://github.com/tyoverby), [gafter](https://github.com/gafter) | [gafter](https://github.com/gafter) | | [private protected](https://github.com/dotnet/roslyn/blob/features/privateProtected/docs/features/private-protected.md) | [features/privateProtected](https://github.com/dotnet/roslyn/tree/features/privateProtected) | Prototyping | | [gafter](https://github.com/gafter) | | [Non-null Ref Types](https://github.com/dotnet/roslyn/blob/features/NullableReferenceTypes/docs/features/NullableReferenceTypes/Nullable%20reference%20types.md) | [features/NullableReferenceTypes](https://github.com/dotnet/roslyn/tree/features/NullableReferenceTypes) | Prototyping | [alekseyts](https://github.com/alekseyts) | [mattwar](https://github.com/mattwar) | | [Better Betterness](https://github.com/dotnet/roslyn/issues/250) | none | Feature Specification | | [gafter](https://github.com/gafter) | @@ -32,5 +32,7 @@ This document reflects the status, and planned work, for the compiler team. It # FAQ -- **Is target version a guarantee?**: No. It's explicitly not a guarantee. This is just the planned and on going work to the best of our knowledge at this time. +- **Is target version a guarantee?**: No. It's explicitly not a guarantee. This is just the planned and ongoing work to the best of our knowledge at this time. - **Where are these State values defined?**: Take a look at the [Developing a Language Feature](contributing/Developing a Language Feature.md) document. + +Updated 2016-07-27 \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs index 06e559c0672..e6058b02584 100644 --- a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs +++ b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs @@ -36,13 +36,13 @@ public override IEnumerable PreprocessorSymbolNames } public CSharpParseOptions( - LanguageVersion languageVersion = LanguageVersion.CSharp7, + LanguageVersion languageVersion = LanguageVersion.Latest, DocumentationMode documentationMode = DocumentationMode.Parse, SourceCodeKind kind = SourceCodeKind.Regular, IEnumerable preprocessorSymbols = null) - : this(languageVersion, documentationMode, kind, preprocessorSymbols.ToImmutableArrayOrEmpty()) + : this(languageVersion.MapLatestToVersion(), documentationMode, kind, preprocessorSymbols.ToImmutableArrayOrEmpty()) { - if (!languageVersion.IsValid()) + if (!LanguageVersion.IsValid()) { throw new ArgumentOutOfRangeException(nameof(languageVersion)); } @@ -120,6 +120,8 @@ public new CSharpParseOptions WithKind(SourceCodeKind kind) public CSharpParseOptions WithLanguageVersion(LanguageVersion version) { + version = version.MapLatestToVersion(); + if (version == this.LanguageVersion) { return this; diff --git a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs index 6cf68676c7c..eccad9c5260 100644 --- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs +++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs @@ -777,7 +777,7 @@ public new CSharpCommandLineArguments Parse(IEnumerable args, string bas { AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "/langversion:"); } - else if (!TryParseLanguageVersion(value, CSharpParseOptions.Default.LanguageVersion, out languageVersion)) + else if (!TryParseLanguageVersion(value, out languageVersion)) { AddDiagnostic(diagnostics, ErrorCode.ERR_BadCompatMode, value); } @@ -1671,8 +1671,10 @@ private static void ValidateWin32Settings(string win32ResourceFile, string win32 return new ResourceDescription(resourceName, fileName, dataProvider, isPublic, embedded, checkArgs: false); } - private static bool TryParseLanguageVersion(string str, LanguageVersion defaultVersion, out LanguageVersion version) + private static bool TryParseLanguageVersion(string str, out LanguageVersion version) { + var defaultVersion = LanguageVersion.Latest.MapLatestToVersion(); + if (str == null) { version = defaultVersion; @@ -1689,13 +1691,24 @@ private static bool TryParseLanguageVersion(string str, LanguageVersion defaultV version = LanguageVersion.CSharp2; return true; + case "7": + version = LanguageVersion.CSharp7; + return true; + case "default": version = defaultVersion; return true; default: + // We are likely to introduce minor version numbers after C# 7, thus breaking the + // one-to-one correspondence between the integers and the corresponding + // LanguageVersion enum values. But for compatibility we continue to accept any + // integral value parsed by int.TryParse for its corresponding LanguageVersion enum + // value for language version C# 6 and earlier (e.g. leading zeros are allowed) int versionNumber; - if (int.TryParse(str, NumberStyles.None, CultureInfo.InvariantCulture, out versionNumber) && ((LanguageVersion)versionNumber).IsValid()) + if (int.TryParse(str, NumberStyles.None, CultureInfo.InvariantCulture, out versionNumber) && + versionNumber <= 6 && + ((LanguageVersion)versionNumber).IsValid()) { version = (LanguageVersion)versionNumber; return true; diff --git a/src/Compilers/CSharp/Portable/LanguageVersion.cs b/src/Compilers/CSharp/Portable/LanguageVersion.cs index 380fd01ece9..22a1e4159c6 100644 --- a/src/Compilers/CSharp/Portable/LanguageVersion.cs +++ b/src/Compilers/CSharp/Portable/LanguageVersion.cs @@ -57,14 +57,25 @@ public enum LanguageVersion /// /// CSharp6 = 6, + /// /// C# language version 7. /// CSharp7 = 7, + + /// + /// The latest version of the language supported. + /// + Latest = int.MaxValue, } internal static partial class LanguageVersionExtensions { + internal static LanguageVersion MapLatestToVersion(this LanguageVersion version) + { + return (version == LanguageVersion.Latest) ? LanguageVersion.CSharp7 : version; + } + internal static bool IsValid(this LanguageVersion value) { return value >= LanguageVersion.CSharp1 && value <= LanguageVersion.CSharp7; diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index c79d05ad099..0f8ef52e2bd 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -1,7 +1,8 @@ -Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion languageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp7, Microsoft.CodeAnalysis.DocumentationMode documentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, Microsoft.CodeAnalysis.SourceCodeKind kind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, System.Collections.Generic.IEnumerable preprocessorSymbols = null) -> void +Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion languageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest, Microsoft.CodeAnalysis.DocumentationMode documentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, Microsoft.CodeAnalysis.SourceCodeKind kind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, System.Collections.Generic.IEnumerable preprocessorSymbols = null) -> void Microsoft.CodeAnalysis.CSharp.Conversion.IsTupleConversion.get -> bool Microsoft.CodeAnalysis.CSharp.Conversion.IsTupleLiteralConversion.get -> bool Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp7 = 7 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion +Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest = 2147483647 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 2467c8e0619..fc0daeaef2b 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -1170,7 +1170,7 @@ public void ArgumentParsing() [Fact] public void LangVersion() { - const LanguageVersion DefaultVersion = LanguageVersion.CSharp7; + LanguageVersion defaultVersion = LanguageVersion.Latest.MapLatestToVersion(); var parsedArgs = DefaultParse(new[] { "/langversion:1", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); @@ -1214,7 +1214,14 @@ public void LangVersion() parsedArgs = DefaultParse(new[] { "/langversion:default", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); + + parsedArgs = DefaultParse(new[] { "/langversion:latest", "a.cs" }, _baseDirectory); + parsedArgs.Errors.Verify( + // error CS1617: Invalid option 'latest' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6. + Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("latest").WithLocation(1, 1) + ); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:iso-1", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); @@ -1226,12 +1233,12 @@ public void LangVersion() parsedArgs = DefaultParse(new[] { "/langversion:default", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); // default value parsedArgs = DefaultParse(new[] { "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); // override value with iso-1 parsedArgs = DefaultParse(new[] { "/langversion:6", "/langversion:iso-1", "a.cs" }, _baseDirectory); @@ -1245,13 +1252,13 @@ public void LangVersion() // override value with default parsedArgs = DefaultParse(new[] { "/langversion:6", "/langversion:default", "a.cs" }, _baseDirectory); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs.Errors.Verify(); // override value with default parsedArgs = DefaultParse(new[] { "/langversion:7", "/langversion:default", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); // override value with numeric parsedArgs = DefaultParse(new[] { "/langversion:iso-2", "/langversion:6", "a.cs" }, _baseDirectory); @@ -1261,40 +1268,40 @@ public void LangVersion() // errors parsedArgs = DefaultParse(new[] { "/langversion:iso-3", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("iso-3")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:iso1", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("iso1")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:7", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify( Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("0")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:8", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify( Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("0"), Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("8")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:1000", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify( Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("0"), Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("1000")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("", "/langversion:")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/LANGversion:", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("", "/langversion:")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion: ", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("", "/langversion:")); - Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); } [Fact] diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb index f59e3d5c200..fdfa90a741a 100644 --- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb +++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb @@ -100,7 +100,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic Dim parseDocumentationComments As Boolean = False ' Don't just null check documentationFileName because we want to do this even if the file name is invalid. Dim outputKind As OutputKind = OutputKind.ConsoleApplication Dim ssVersion As SubsystemVersion = SubsystemVersion.None - Dim languageVersion As LanguageVersion = LanguageVersion.VisualBasic15 + Dim languageVersion As LanguageVersion = LanguageVersion.Latest.MapLatestToVersion() Dim mainTypeName As String = Nothing Dim win32ManifestFile As String = Nothing Dim win32ResourceFile As String = Nothing @@ -793,6 +793,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic languageVersion = LanguageVersion.VisualBasic14 Case "15", "15.0" languageVersion = LanguageVersion.VisualBasic15 + Case "default" + languageVersion = LanguageVersion.Latest.MapLatestToVersion() Case Else AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "langversion", value) End Select diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb index bb9a2351d4a..e5b451fb574 100644 --- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb +++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb @@ -252,7 +252,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ' The My template regularly makes use of more recent language features. Care is ' taken to ensure these are compatible with 2.0 runtimes so there is no danger ' with allowing the newer syntax here. - Dim options = parseOptions.WithLanguageVersion(LanguageVersion.VisualBasic14) + Dim options = parseOptions.WithLanguageVersion(LanguageVersion.Latest) tree = VisualBasicSyntaxTree.ParseText(text, options:=options, isMyTemplate:=True) If tree.GetDiagnostics().Any() Then diff --git a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb index 5372f8531b3..82610d2a3a1 100644 --- a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb +++ b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb @@ -13,6 +13,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic VisualBasic12 = 12 VisualBasic14 = 14 VisualBasic15 = 15 + Latest = Integer.MaxValue End Enum Friend Module LanguageVersionEnumBounds @@ -55,5 +56,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic End Function + + Friend Function MapLatestToVersion(version As LanguageVersion) As LanguageVersion + Return If(version = LanguageVersion.Latest, LanguageVersion.VisualBasic15, version) + End Function + End Module End Namespace diff --git a/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb b/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb index 60081bc9e35..a6b1500aca5 100644 --- a/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb +++ b/src/Compilers/VisualBasic/Portable/Parser/ParserFeature.vb @@ -38,12 +38,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Friend Function GetFeatureFlag(feature As Feature) As String Select Case feature - Case Feature.DigitSeparators - Return "digitSeparators" - - Case Feature.BinaryLiterals - Return "binaryLiterals" - Case Feature.IOperation Return "IOperation" @@ -86,6 +80,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax.InternalSyntax Feature.ImplementingReadonlyOrWriteonlyPropertyWithReadwrite Return LanguageVersion.VisualBasic14 + Case Feature.BinaryLiterals, + Feature.DigitSeparators + Return LanguageVersion.VisualBasic15 + Case Else Throw ExceptionUtilities.UnexpectedValue(feature) End Select diff --git a/src/Compilers/VisualBasic/Portable/PublicAPI.Shipped.txt b/src/Compilers/VisualBasic/Portable/PublicAPI.Shipped.txt index 80c87709cff..eee2092ffcc 100644 --- a/src/Compilers/VisualBasic/Portable/PublicAPI.Shipped.txt +++ b/src/Compilers/VisualBasic/Portable/PublicAPI.Shipped.txt @@ -3240,7 +3240,6 @@ Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.TryGetSpeculativeSemant Microsoft.CodeAnalysis.VisualBasic.VisualBasicExtensions.TryGetSpeculativeSemanticModelForMethodBody(semanticModel As Microsoft.CodeAnalysis.SemanticModel, position As Integer, method As Microsoft.CodeAnalysis.VisualBasic.Syntax.MethodBlockBaseSyntax, ByRef speculativeModel As Microsoft.CodeAnalysis.SemanticModel) -> Boolean Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.LanguageVersion() -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion -Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.New(languageVersion As Microsoft.CodeAnalysis.VisualBasic.LanguageVersion = Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic14, documentationMode As Microsoft.CodeAnalysis.DocumentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, kind As Microsoft.CodeAnalysis.SourceCodeKind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, preprocessorSymbols As System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Object)) = Nothing) -> Void Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.PreprocessorSymbols() -> System.Collections.Immutable.ImmutableArray(Of System.Collections.Generic.KeyValuePair(Of String, Object)) Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.WithFeatures(features As System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, String))) -> Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.WithKind(kind As Microsoft.CodeAnalysis.SourceCodeKind) -> Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions diff --git a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt index de981579636..df62e76f9bc 100644 --- a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt @@ -1 +1,3 @@ -Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic15 = 15 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion \ No newline at end of file +Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.Latest = 2147483647 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion +Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic15 = 15 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion +Microsoft.CodeAnalysis.VisualBasic.VisualBasicParseOptions.New(languageVersion As Microsoft.CodeAnalysis.VisualBasic.LanguageVersion = Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.Latest, documentationMode As Microsoft.CodeAnalysis.DocumentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, kind As Microsoft.CodeAnalysis.SourceCodeKind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, preprocessorSymbols As System.Collections.Generic.IEnumerable(Of System.Collections.Generic.KeyValuePair(Of String, Object)) = Nothing) -> Void diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx index 064faa5202d..15d305a643c 100644 --- a/src/Compilers/VisualBasic/Portable/VBResources.resx +++ b/src/Compilers/VisualBasic/Portable/VBResources.resx @@ -5072,8 +5072,8 @@ diagnostics. /reportanalyzer Report additional analyzer information, such as execution time. - - LANGUAGE - + - LANGUAGE - /define:<symbol_list> Declare global conditional compilation symbol(s). symbol_list:name=value,... (Short form: /d) @@ -5081,15 +5081,15 @@ referenced metadata files. import_list:namespace,... /langversion:<number> Specify language version: - 9|9.0|10|10.0|11|11.0|12|12.0|14|14.0 + 9|9.0|10|10.0|11|11.0|12|12.0|14|14.0|15|15.0|default /optionexplicit[+|-] Require explicit declaration of variables. /optioninfer[+|-] Allow type inference of variables. /rootnamespace:<string> Specifies the root Namespace for all type declarations. /optionstrict[+|-] Enforce strict language semantics. -/optionstrict:custom Warn when strict language semantics are not +/optionstrict:custom Warn when strict language semantics are not respected. -/optioncompare:binary Specifies binary-style string comparisons. +/optioncompare:binary Specifies binary-style string comparisons. This is the default. /optioncompare:text Specifies text-style string comparisons. diff --git a/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb b/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb index 089efb178ce..f28079d005f 100644 --- a/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb +++ b/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb @@ -29,19 +29,19 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' The kind of source code. ''' An enumerable sequence of KeyValuePair representing preprocessor symbols. Public Sub New( - Optional languageVersion As LanguageVersion = LanguageVersion.VisualBasic14, + Optional languageVersion As LanguageVersion = LanguageVersion.Latest, Optional documentationMode As DocumentationMode = DocumentationMode.Parse, Optional kind As SourceCodeKind = SourceCodeKind.Regular, Optional preprocessorSymbols As IEnumerable(Of KeyValuePair(Of String, Object)) = Nothing) - MyClass.New(languageVersion, + MyClass.New(languageVersion.MapLatestToVersion(), documentationMode, kind, If(preprocessorSymbols Is Nothing, DefaultPreprocessorSymbols, ImmutableArray.CreateRange(preprocessorSymbols)), ImmutableDictionary(Of String, String).Empty) - If Not languageVersion.IsValid Then - Throw New ArgumentOutOfRangeException(NameOf(languageVersion)) + If Not _languageVersion.IsValid Then + Throw New ArgumentOutOfRangeException(NameOf(_languageVersion)) End If If Not kind.IsValid Then @@ -172,6 +172,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic ''' The parser language version. ''' A new instance of VisualBasicParseOptions if different language version is different; otherwise current instance. Public Shadows Function WithLanguageVersion(version As LanguageVersion) As VisualBasicParseOptions + version = version.MapLatestToVersion() If version = _languageVersion Then Return Me End If diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb index 713307b4479..8403159e9f4 100644 --- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb +++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb @@ -1005,6 +1005,14 @@ a.vb parsedArgs.Errors.Verify() Assert.Equal(LanguageVersion.VisualBasic15, parsedArgs.ParseOptions.LanguageVersion) + parsedArgs = DefaultParse({"/langVERSION:default", "a.vb"}, _baseDirectory) + parsedArgs.Errors.Verify() + Assert.Equal(LanguageVersion.VisualBasic15, parsedArgs.ParseOptions.LanguageVersion) + + parsedArgs = DefaultParse({"/langVERSION:latest", "a.vb"}, _baseDirectory) + parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("langversion", "latest").WithLocation(1, 1)) + Assert.Equal(LanguageVersion.VisualBasic15, parsedArgs.ParseOptions.LanguageVersion) + ' default: "current version" parsedArgs = DefaultParse({"a.vb"}, _baseDirectory) parsedArgs.Errors.Verify() diff --git a/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb b/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb index 1f8b8c6b38e..0d52bdafd5c 100644 --- a/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb +++ b/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb @@ -25,6 +25,16 @@ Public Class VisualBasicParseOptionsTests Assert.Throws(Of ArgumentOutOfRangeException)(Function() VisualBasicParseOptions.Default.WithLanguageVersion(DirectCast(1000, LanguageVersion))) End Sub + + Public Sub WithLatestLanguageVersion() + Dim oldOpt1 = VisualBasicParseOptions.Default + Dim newOpt1 = oldOpt1.WithLanguageVersion(LanguageVersion.Latest) + Dim newOpt2 = newOpt1.WithLanguageVersion(LanguageVersion.Latest) + Assert.Equal(LanguageVersion.Latest.MapLatestToVersion, oldOpt1.LanguageVersion) + Assert.Equal(LanguageVersion.Latest.MapLatestToVersion, newOpt1.LanguageVersion) + Assert.Equal(LanguageVersion.Latest.MapLatestToVersion, newOpt2.LanguageVersion) + End Sub + Public Sub WithPreprocessorSymbols() Dim syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)("A", 1), @@ -109,6 +119,7 @@ Public Class VisualBasicParseOptionsTests GetValues(GetType(LanguageVersion)). Cast(Of LanguageVersion). Select(Function(x) CInt(x)). + Where(Function(x) x <> LanguageVersion.Latest). Max() Assert.Equal(highest, CInt(PredefinedPreprocessorSymbols.CurrentVersionNumber)) diff --git a/src/Compilers/VisualBasic/Test/Syntax/Scanner/ScannerTests.vb b/src/Compilers/VisualBasic/Test/Syntax/Scanner/ScannerTests.vb index af977df0225..134add5c4dd 100644 --- a/src/Compilers/VisualBasic/Test/Syntax/Scanner/ScannerTests.vb +++ b/src/Compilers/VisualBasic/Test/Syntax/Scanner/ScannerTests.vb @@ -700,7 +700,7 @@ End If]]>.Value, Assert.Equal(LiteralBase.Decimal, tk.GetBase()) Assert.Equal(42, tk.Value) Assert.Equal(" 4_2 ", tk.ToFullString()) - Assert.Equal("error BC36716: Visual Basic 14.0 does not support digit separators.", tk.Errors().Single().ToString()) + Assert.Equal(0, tk.Errors().Count) Str = " &H42L " tk = ScanOnce(Str) @@ -729,17 +729,14 @@ End If]]>.Value, Assert.Equal(LiteralBase.Binary, tk.GetBase()) Assert.Equal(&HAL, tk.Value) Assert.Equal(" &B1010L ", tk.ToFullString()) - Assert.Equal("error BC36716: Visual Basic 14.0 does not support binary literals.", tk.Errors().Single().ToString()) - + Assert.Equal(0, tk.Errors().Count) Str = " &B1_0_1_0L " tk = ScanOnce(Str) Assert.Equal(SyntaxKind.IntegerLiteralToken, tk.Kind) Assert.Equal(LiteralBase.Binary, tk.GetBase()) Assert.Equal(&HAL, tk.Value) Assert.Equal(" &B1_0_1_0L ", tk.ToFullString()) - Assert.Equal(2, tk.Errors().Count) - Assert.Equal("error BC36716: Visual Basic 14.0 does not support digit separators.", tk.Errors()(0).ToString()) - Assert.Equal("error BC36716: Visual Basic 14.0 does not support binary literals.", tk.Errors()(1).ToString()) + Assert.Equal(0, tk.Errors().Count) End Sub -- GitLab