diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs index 7dff2879d0469..335f581c6d10f 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs +++ b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs @@ -1232,7 +1232,7 @@ internal static string ERR_BadCoClassSig { } /// - /// Looks up a localized string similar to Invalid option '{0}' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 7.. + /// Looks up a localized string similar to Invalid option '{0}' for /langversion; must be ISO-1, ISO-2, Default, Latest or a valid version in range 1 to 7.1.. /// internal static string ERR_BadCompatMode { get { @@ -4453,6 +4453,15 @@ internal static string ERR_FeatureNotAvailableInVersion7 { } } + /// + /// Looks up a localized string similar to Feature '{0}' is not available in C# 7.1. Please use language version {1} or greater.. + /// + internal static string ERR_FeatureNotAvailableInVersion7_1 { + get { + return ResourceManager.GetString("ERR_FeatureNotAvailableInVersion7_1", resourceCulture); + } + } + /// /// Looks up a localized string similar to An expression tree may not contain '{0}'. /// diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx index 0290d2430281c..280e2b2cc9155 100644 --- a/src/Compilers/CSharp/Portable/CSharpResources.resx +++ b/src/Compilers/CSharp/Portable/CSharpResources.resx @@ -2690,7 +2690,7 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep This warning occurs if the assembly attributes AssemblyKeyFileAttribute or AssemblyKeyNameAttribute found in source conflict with the /keyfile or /keycontainer command line option or key file name or key container specified in the Project Properties. - Invalid option '{0}' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 7. + Invalid option '{0}' for /langversion; must be ISO-1, ISO-2, Default, Latest or a valid version in range 1 to 7.1. Cannot create delegate with '{0}' because it or a method it overrides has a Conditional attribute @@ -5032,4 +5032,7 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ Invalid name for a preprocessing symbol; '{0}' is not a valid identifier + + Feature '{0}' is not available in C# 7.1. Please use language version {1} or greater. + \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs index f7ce50eaad930..29a51eff04724 100644 --- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs +++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs @@ -1468,5 +1468,6 @@ internal enum ErrorCode ERR_Merge_conflict_marker_encountered = 8300, ERR_InvalidPreprocessingSymbol = 8301, + ERR_FeatureNotAvailableInVersion7_1 = 8302, } } \ No newline at end of file diff --git a/src/Compilers/CSharp/Portable/LanguageVersion.cs b/src/Compilers/CSharp/Portable/LanguageVersion.cs index 6060b10241058..ee433a587f845 100644 --- a/src/Compilers/CSharp/Portable/LanguageVersion.cs +++ b/src/Compilers/CSharp/Portable/LanguageVersion.cs @@ -69,6 +69,11 @@ public enum LanguageVersion /// CSharp7 = 7, + /// + /// C# language version 7.1 + /// + CSharp7_1 = 701, + /// /// The latest version of the language supported. /// @@ -79,7 +84,20 @@ internal static class LanguageVersionExtensionsInternal { internal static bool IsValid(this LanguageVersion value) { - return value >= LanguageVersion.CSharp1 && value <= LanguageVersion.CSharp7; + switch (value) + { + case LanguageVersion.CSharp1: + case LanguageVersion.CSharp2: + case LanguageVersion.CSharp3: + case LanguageVersion.CSharp4: + case LanguageVersion.CSharp5: + case LanguageVersion.CSharp6: + case LanguageVersion.CSharp7: + case LanguageVersion.CSharp7_1: + return true; + } + + return false; } internal static ErrorCode GetErrorCode(this LanguageVersion version) @@ -100,6 +118,8 @@ internal static ErrorCode GetErrorCode(this LanguageVersion version) return ErrorCode.ERR_FeatureNotAvailableInVersion6; case LanguageVersion.CSharp7: return ErrorCode.ERR_FeatureNotAvailableInVersion7; + case LanguageVersion.CSharp7_1: + return ErrorCode.ERR_FeatureNotAvailableInVersion7_1; default: throw ExceptionUtilities.UnexpectedValue(version); } @@ -142,6 +162,8 @@ public static string ToDisplayString(this LanguageVersion version) return "6"; case LanguageVersion.CSharp7: return "7"; + case LanguageVersion.CSharp7_1: + return "7.1"; case LanguageVersion.Default: return "default"; case LanguageVersion.Latest: @@ -172,10 +194,6 @@ public static bool TryParse(this string version, out LanguageVersion result) result = LanguageVersion.CSharp2; return true; - case "7": - result = LanguageVersion.CSharp7; - return true; - case "default": result = LanguageVersion.Default; return true; @@ -184,19 +202,18 @@ public static bool TryParse(this string version, out LanguageVersion result) result = LanguageVersion.Latest; return true; + case "7.1": + result = LanguageVersion.CSharp7_1; + 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(version, NumberStyles.None, CultureInfo.InvariantCulture, out versionNumber) && - versionNumber <= 6 && - ((LanguageVersion)versionNumber).IsValid()) + if (int.TryParse(version, NumberStyles.None, CultureInfo.InvariantCulture, out int versionNumber) && versionNumber <= 7) { result = (LanguageVersion)versionNumber; - return true; + if (result.IsValid()) + { + return true; + } } result = LanguageVersion.Default; @@ -212,6 +229,7 @@ public static LanguageVersion MapSpecifiedToEffectiveVersion(this LanguageVersio switch (version) { case LanguageVersion.Latest: + return LanguageVersion.CSharp7_1; case LanguageVersion.Default: return LanguageVersion.CSharp7; default: diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt index 42e6ee0886678..05206cd42bdcd 100644 --- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt @@ -13,6 +13,7 @@ Microsoft.CodeAnalysis.CSharp.Conversion.IsThrow.get -> bool 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.CSharp7_1 = 701 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion Microsoft.CodeAnalysis.CSharp.LanguageVersion.Default = 0 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion Microsoft.CodeAnalysis.CSharp.LanguageVersion.Latest = 2147483647 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs index 7b064856c0a19..6775f3a8d74fa 100644 --- a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs +++ b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs @@ -1191,7 +1191,8 @@ public void ArgumentParsing() [Fact] public void LangVersion() { - LanguageVersion defaultVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion(); + LanguageVersion defaultEffectiveVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion(); + LanguageVersion latestEffectiveVersion = LanguageVersion.Latest.MapSpecifiedToEffectiveVersion(); var parsedArgs = DefaultParse(new[] { "/langversion:1", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); @@ -1233,15 +1234,19 @@ public void LangVersion() parsedArgs.Errors.Verify(); Assert.Equal(LanguageVersion.CSharp7, parsedArgs.ParseOptions.LanguageVersion); + parsedArgs = DefaultParse(new[] { "/langversion:7.1", "a.cs" }, _baseDirectory); + parsedArgs.Errors.Verify(); + Assert.Equal(LanguageVersion.CSharp7_1, parsedArgs.ParseOptions.LanguageVersion); + parsedArgs = DefaultParse(new[] { "/langversion:default", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); Assert.Equal(LanguageVersion.Default, parsedArgs.ParseOptions.SpecifiedLanguageVersion); - Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(defaultEffectiveVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:latest", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); Assert.Equal(LanguageVersion.Latest, parsedArgs.ParseOptions.SpecifiedLanguageVersion); - Assert.Equal(defaultVersion, parsedArgs.ParseOptions.LanguageVersion); + Assert.Equal(latestEffectiveVersion, parsedArgs.ParseOptions.LanguageVersion); parsedArgs = DefaultParse(new[] { "/langversion:iso-1", "a.cs" }, _baseDirectory); parsedArgs.Errors.Verify(); @@ -1251,14 +1256,11 @@ public void LangVersion() parsedArgs.Errors.Verify(); Assert.Equal(LanguageVersion.CSharp2, parsedArgs.ParseOptions.LanguageVersion); - parsedArgs = DefaultParse(new[] { "/langversion:default", "a.cs" }, _baseDirectory); - parsedArgs.Errors.Verify(); - 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(LanguageVersion.Default, parsedArgs.ParseOptions.SpecifiedLanguageVersion); + Assert.Equal(defaultEffectiveVersion, parsedArgs.ParseOptions.LanguageVersion); // override value with iso-1 parsedArgs = DefaultParse(new[] { "/langversion:6", "/langversion:iso-1", "a.cs" }, _baseDirectory); @@ -1272,13 +1274,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(defaultEffectiveVersion, 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(defaultEffectiveVersion, parsedArgs.ParseOptions.LanguageVersion); // override value with numeric parsedArgs = DefaultParse(new[] { "/langversion:iso-2", "/langversion:6", "a.cs" }, _baseDirectory); @@ -1288,40 +1290,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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, 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(defaultEffectiveVersion, parsedArgs.ParseOptions.LanguageVersion); } [Fact] @@ -1332,14 +1334,14 @@ public void LanguageVersionAdded_Canary() // - update the "UpgradeProject" codefixer // - update the IDE drop-down for selecting Language Version // - don't fix the canary test until you update all the tests that include it - Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion()); + Assert.Equal(LanguageVersion.CSharp7_1, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion()); Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.Default.MapSpecifiedToEffectiveVersion()); } [Fact] public void LanguageVersion_DisplayString() { - AssertEx.SetEqual(new[] { "default", "1", "2", "3", "4", "5", "6", "7", "latest" }, + AssertEx.SetEqual(new[] { "default", "1", "2", "3", "4", "5", "6", "7", "7.1", "latest" }, Enum.GetValues(typeof(LanguageVersion)).Cast().Select(v => v.ToDisplayString())); // For minor versions, the format should be "x.y", such as "7.1" } @@ -1355,7 +1357,7 @@ public void LanguageVersion_MapSpecifiedToEffectiveVersion() Assert.Equal(LanguageVersion.CSharp6, LanguageVersion.CSharp6.MapSpecifiedToEffectiveVersion()); Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.CSharp7.MapSpecifiedToEffectiveVersion()); Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.Default.MapSpecifiedToEffectiveVersion()); - Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion()); + Assert.Equal(LanguageVersion.CSharp7_1, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion()); // The canary check is a reminder that this test needs to be updated when a language version is added LanguageVersionAdded_Canary(); @@ -1373,7 +1375,8 @@ public void LanguageVersion_MapSpecifiedToEffectiveVersion() InlineData("05", true, LanguageVersion.CSharp5), InlineData("6", true, LanguageVersion.CSharp6), InlineData("7", true, LanguageVersion.CSharp7), - InlineData("07", false, LanguageVersion.Default), + InlineData("07", true, LanguageVersion.CSharp7), + InlineData("7.1", true, LanguageVersion.CSharp7_1), InlineData("default", true, LanguageVersion.Default), InlineData("latest", true, LanguageVersion.Latest), InlineData(null, true, LanguageVersion.Default),