提交 5243bd67 编写于 作者: J Julien Couvreur 提交者: GitHub

List supported language versions (#20153)

上级 493d300a
......@@ -50,7 +50,8 @@
| `/checked`{`+`|`-`} | Generate overflow checks
| `/unsafe`{`+`|`-`} | Allow 'unsafe' code
| `/define:`*symbol list* | Define conditional compilation symbol(s) (Short form: `/d`)
| `/langversion`:*string* | Specify language version mode: `ISO-1`, `ISO-2`, `3`, `4`, `5`, `6`, `7`, `7.1`, `7.2`, `Default` (latest major version), or `Latest` (latest version, including minor versions)
| `/langversion:?` | Display the allowed values for language version
| `/langversion`:*string* | Specify language version such as `default` (latest major version), or `latest` (latest version, including minor versions)
| **SECURITY**
| `/delaysign`{`+`|`-`} | Delay-sign the assembly using only the public portion of the strong name key
| `/keyfile:`*file* | Specify a strong name key file
......
......@@ -52,7 +52,8 @@
| **LANGUAGE**
| `/define:`*symbol_list* | Declare global conditional compilation symbol(s). *symbol_list* is *name*`=`*value*`,`... (Short form: `/d`)
| `/imports:`*import_list* | Declare global Imports for namespaces in referenced metadata files. *import_list* is *namespace*`,`...
| `/langversion:`*number* | Specify language version: `9`|`9.0`|`10`|`10.0`|`11`|`11.0`|`12`|`12.0`|`13`|`13.0`|`14`|`14.0`|`15`|`15.0`|`15.3`|`15.6`. The default is `15` and the latest is `15.6`.
| `/langversion:?` | Display the allowed values for language version
| `/langversion`:*string* | Specify language version such as `default` (latest major version), or `latest` (latest version, including minor versions)
| `/optionexplicit`{`+`|`-`} | Require explicit declaration of variables.
| `/optioninfer`{`+`|`-`} | Allow type inference of variables.
| `/rootnamespace`:*string* | Specifies the root Namespace for all top-level type declarations.
......
......@@ -1241,7 +1241,7 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Invalid option &apos;{0}&apos; for /langversion; must be ISO-1, ISO-2, Default, Latest or a valid version in range 1 to 7.2..
/// Looks up a localized string similar to Invalid option &apos;{0}&apos; for /langversion. Use &apos;/langversion:?&apos; to list supported values..
/// </summary>
internal static string ERR_BadCompatMode {
get {
......@@ -10457,6 +10457,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Supported language versions:.
/// </summary>
internal static string IDS_LangVersions {
get {
return ResourceManager.GetString("IDS_LangVersions", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to LIB environment variable.
/// </summary>
......
......@@ -2711,7 +2711,7 @@ A catch() block after a catch (System.Exception e) block can catch non-CLS excep
<value>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.</value>
</data>
<data name="ERR_BadCompatMode" xml:space="preserve">
<value>Invalid option '{0}' for /langversion; must be ISO-1, ISO-2, Default, Latest or a valid version in range 1 to 7.2.</value>
<value>Invalid option '{0}' for /langversion. Use '/langversion:?' to list supported values.</value>
</data>
<data name="ERR_DelegateOnConditional" xml:space="preserve">
<value>Cannot create delegate with '{0}' because it or a method it overrides has a Conditional attribute</value>
......@@ -4392,6 +4392,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="IDS_LogoLine2" xml:space="preserve">
<value>Copyright (C) Microsoft Corporation. All rights reserved.</value>
</data>
<data name="IDS_LangVersions" xml:space="preserve">
<value>Supported language versions:</value>
</data>
<data name="IDS_CSCHelp" xml:space="preserve">
<value>
Visual C# Compiler Options
......@@ -4477,8 +4480,11 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
/unsafe[+|-] Allow 'unsafe' code
/define:&lt;symbol list&gt; Define conditional compilation symbol(s) (Short
form: /d)
/langversion:&lt;string&gt; Specify language version mode: ISO-1, ISO-2, 3,
4, 5, 6, 7.0, 7.1, 7.2, Default, or Latest
/langversion:? Display the allowed values for language version
/langversion:&lt;string&gt; Specify language version such as
`default` (latest major version), or
`latest` (latest version, including minor versions),
or specific versions like `6` or `7.1`
- SECURITY -
/delaysign[+|-] Delay-sign the assembly using only the public
......
......@@ -55,6 +55,7 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
bool displayLogo = true;
bool displayHelp = false;
bool displayVersion = false;
bool displayLangVersions = false;
bool optimize = false;
bool checkOverflow = false;
bool allowUnsafe = false;
......@@ -837,6 +838,10 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
// treat them as identifiers (behaviour in native compiler). This error helps users identify that breaking change.
AddDiagnostic(diagnostics, ErrorCode.ERR_LanguageVersionCannotHaveLeadingZeroes, value);
}
else if (value == "?")
{
displayLangVersions = true;
}
else if (!value.TryParse(out languageVersion))
{
AddDiagnostic(diagnostics, ErrorCode.ERR_BadCompatMode, value);
......@@ -1347,6 +1352,7 @@ public new CSharpCommandLineArguments Parse(IEnumerable<string> args, string bas
DisplayLogo = displayLogo,
DisplayHelp = displayHelp,
DisplayVersion = displayVersion,
DisplayLangVersions = displayLangVersions,
ManifestResources = managedResources.AsImmutable(),
CompilationOptions = options,
ParseOptions = parseOptions,
......
......@@ -267,6 +267,28 @@ public override void PrintLogo(TextWriter consoleOutput)
consoleOutput.WriteLine();
}
public override void PrintLangVersions(TextWriter consoleOutput)
{
consoleOutput.WriteLine(ErrorFacts.GetMessage(MessageID.IDS_LangVersions, Culture));
var defaultVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion();
var latestVersion = LanguageVersion.Latest.MapSpecifiedToEffectiveVersion();
foreach (LanguageVersion v in Enum.GetValues(typeof(LanguageVersion)))
{
if (v == defaultVersion)
{
consoleOutput.WriteLine($"{v.ToDisplayString()} (default)");
}
else if (v == latestVersion)
{
consoleOutput.WriteLine($"{v.ToDisplayString()} (latest)");
}
else
{
consoleOutput.WriteLine(v.ToDisplayString());
}
}
consoleOutput.WriteLine();
}
internal override Type Type
{
......
......@@ -131,6 +131,7 @@ internal enum MessageID
IDS_FeatureInferredTupleNames = MessageBase + 12719,
IDS_FeatureGenericPatternMatching = MessageBase + 12720,
IDS_FeatureAsyncMain = MessageBase + 12721,
IDS_LangVersions = MessageBase + 12722,
}
// Message IDs may refer to strings that need to be localized.
......
......@@ -1110,6 +1110,12 @@ public void ArgumentParsing()
Assert.True(parsedArgs.DisplayVersion);
Assert.False(parsedArgs.SourceFiles.Any());
parsedArgs = CSharpCommandLineParser.ScriptRunner.Parse(new[] { "/langversion:?" }, _baseDirectory, s_defaultSdkDirectory);
parsedArgs.Errors.Verify(
// error CS2007: Unrecognized option: '/langversion:?'
Diagnostic(ErrorCode.ERR_BadSwitch).WithArguments("/langversion:?").WithLocation(1, 1)
);
parsedArgs = CSharpCommandLineParser.ScriptRunner.Parse(new[] { "/version", "c.csx" }, _baseDirectory, s_defaultSdkDirectory);
parsedArgs.Errors.Verify();
Assert.True(parsedArgs.DisplayVersion);
......@@ -1268,8 +1274,9 @@ public void LangVersion_NoValueSpecified()
public void LangVersion_BadVersion(string value)
{
DefaultParse(new[] { $"/langversion:{value}", "a.cs" }, _baseDirectory).Errors.Verify(
// error CS1617: Invalid option 'XXX' for /langversion; must be ISO-1, ISO-2, Default, Latest or a valid version in range 1 to 7.1.
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments(value).WithLocation(1, 1));
// error CS1617: Invalid option 'XXX' for /langversion. Use '/langversion:?' to list supported values.
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments(value).WithLocation(1, 1)
);
}
[Theory]
......@@ -1295,6 +1302,19 @@ public void LangVersion_NoVersion(string option)
Diagnostic(ErrorCode.ERR_SwitchNeedsString).WithArguments("<text>", "/langversion:").WithLocation(1, 1));
}
[Fact]
public void LangVersion_LangVersions()
{
var args = DefaultParse(new[] { "/langversion:?" }, _baseDirectory);
args.Errors.Verify(
// warning CS2008: No source files specified.
Diagnostic(ErrorCode.WRN_NoSources).WithLocation(1, 1),
// error CS1562: Outputs without source must have the /out option specified
Diagnostic(ErrorCode.ERR_OutputNeedsName).WithLocation(1, 1)
);
Assert.True(args.DisplayLangVersions);
}
[Fact]
public void LanguageVersionAdded_Canary()
{
......@@ -1392,29 +1412,26 @@ public void LanguageVersion_TryParseDisplayString(string input, bool success, La
}
[Fact]
public void LanguageVersion_CommandLineUsage()
public void LangVersion_ListLangVersions()
{
var dir = Temp.CreateDirectory();
var outWriter = new StringWriter(CultureInfo.InvariantCulture);
var csc = new MockCSharpCompiler(null, dir.Path, new[] { "/langversion:?" });
int exitCode = csc.Run(outWriter);
Assert.Equal(0, exitCode);
var expected = Enum.GetValues(typeof(LanguageVersion)).Cast<LanguageVersion>()
.Where(v => v != LanguageVersion.CSharp1 && v != LanguageVersion.CSharp2)
.Select(v => v.ToDisplayString());
string help = CSharpResources.IDS_CSCHelp;
var rangeStart = help.IndexOf("/langversion");
var rangeEnd = help.IndexOf("/delaysign");
Assert.True(rangeEnd > rangeStart);
string helpRange = help.Substring(rangeStart, rangeEnd - rangeStart).ToLowerInvariant();
var acceptableSurroundingChar = new[] { '\r', '\n', ',' , ' '};
var actual = outWriter.ToString();
var acceptableSurroundingChar = new[] { '\r', '\n', '(' , ')', ' '};
foreach (var version in expected)
{
var foundIndex = helpRange.IndexOf(version);
var foundIndex = actual.IndexOf(version);
Assert.True(foundIndex > 0, $"Missing version '{version}'");
Assert.True(Array.IndexOf(acceptableSurroundingChar, helpRange[foundIndex - 1]) >= 0);
Assert.True(Array.IndexOf(acceptableSurroundingChar, helpRange[foundIndex + version.Length]) >= 0);
Assert.True(Array.IndexOf(acceptableSurroundingChar, actual[foundIndex - 1]) >= 0);
Assert.True(Array.IndexOf(acceptableSurroundingChar, actual[foundIndex + version.Length]) >= 0);
}
// The canary check is a reminder that this test needs to be updated when a language version is added
LanguageVersionAdded_Canary();
}
[Fact]
......@@ -9369,7 +9386,7 @@ public void CompilingCodeWithInvalidLanguageVersionShouldProvideDiagnostics()
{
var parsedArgs = DefaultParse(new[] { "/langversion:1000", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify(
// error CS1617: Invalid option '1000' for /langversion; must be ISO-1, ISO-2, Default or an integer in range 1 to 6.
// error CS1617: Invalid option '1000' for /langversion. Use '/langversion:?' to list supported values.
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("1000").WithLocation(1, 1));
}
......
......@@ -183,6 +183,12 @@ public abstract class CommandLineArguments
/// </summary>
public bool DisplayVersion { get; internal set; }
/// <summary>
/// If true, prepend the compiler-supported language versions during
/// <see cref="CommonCompiler.Run"/>
/// </summary>
public bool DisplayLangVersions { get; internal set; }
/// <summary>
/// The path to a Win32 resource.
/// </summary>
......
......@@ -78,6 +78,7 @@ internal abstract partial class CommonCompiler
public abstract Compilation CreateCompilation(TextWriter consoleOutput, TouchedFileLogger touchedFilesLogger, ErrorLogger errorLoggerOpt);
public abstract void PrintLogo(TextWriter consoleOutput);
public abstract void PrintHelp(TextWriter consoleOutput);
public abstract void PrintLangVersions(TextWriter consoleOutput);
/// <summary>
/// Print compiler version
......@@ -520,6 +521,12 @@ private int RunCore(TextWriter consoleOutput, ErrorLogger errorLogger, Cancellat
return Succeeded;
}
if (Arguments.DisplayLangVersions)
{
PrintLangVersions(consoleOutput);
return Succeeded;
}
if (Arguments.DisplayLogo)
{
PrintLogo(consoleOutput);
......
......@@ -913,3 +913,4 @@ virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.Vi
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWhileUntilLoopStatement(Microsoft.CodeAnalysis.Semantics.IWhileUntilLoopStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitWithStatement(Microsoft.CodeAnalysis.Semantics.IWithStatement operation, TArgument argument) -> TResult
virtual Microsoft.CodeAnalysis.Semantics.OperationVisitor<TArgument, TResult>.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation, TArgument argument) -> TResult
Microsoft.CodeAnalysis.CommandLineArguments.DisplayLangVersions.get -> bool
......@@ -87,6 +87,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim displayLogo As Boolean = True
Dim displayHelp As Boolean = False
Dim displayVersion As Boolean = False
Dim displayLangVersions As Boolean = False
Dim outputLevel As OutputLevel = OutputLevel.Normal
Dim optimize As Boolean = False
Dim checkOverflow As Boolean = True
......@@ -822,13 +823,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Case "langversion"
value = RemoveQuotesAndSlashes(value)
If value Is Nothing Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "langversion", ":<number>")
Continue For
End If
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "langversion", ":<number>")
ElseIf value = "?" Then
displayLangVersions = True
Else
If Not value.TryParse(languageVersion) Then
AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "langversion", value)
......@@ -1408,6 +1406,7 @@ lVbRuntimePlus:
.DisplayLogo = displayLogo,
.DisplayHelp = displayHelp,
.DisplayVersion = displayVersion,
.DisplayLangVersions = displayLangVersions,
.ManifestResources = managedResources.AsImmutable(),
.CompilationOptions = options,
.ParseOptions = parseOptions,
......
......@@ -203,6 +203,22 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_VBCHelp, Culture))
End Sub
Public Overrides Sub PrintLangVersions(consoleOutput As TextWriter)
consoleOutput.WriteLine(ErrorFactory.IdToString(ERRID.IDS_LangVersions, Culture))
Dim defaultVersion = LanguageVersion.Default.MapSpecifiedToEffectiveVersion()
Dim latestVersion = LanguageVersion.Latest.MapSpecifiedToEffectiveVersion()
For Each v As LanguageVersion In System.Enum.GetValues(GetType(LanguageVersion))
If v = defaultVersion Then
consoleOutput.WriteLine($"{v.ToDisplayString()} (default)")
ElseIf v = latestVersion Then
consoleOutput.WriteLine($"{v.ToDisplayString()} (latest)")
Else
consoleOutput.WriteLine(v.ToDisplayString())
End If
Next
consoleOutput.WriteLine()
End Sub
Protected Overrides Function TryGetCompilerDiagnosticCode(diagnosticId As String, ByRef code As UInteger) As Boolean
Return CommonCompiler.TryGetCompilerDiagnosticCode(diagnosticId, "BC", code)
End Function
......
......@@ -1977,7 +1977,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
IDS_LogoLine1 = 56007
IDS_LogoLine2 = 56008
IDS_VBCHelp = 56009
' available: 56010
IDS_LangVersions = 56010
IDS_ToolName = 56011
' Feature codes
......
......@@ -23,7 +23,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
'''<summary>
''' A strongly-typed resource class, for looking up localized strings, etc.
'''</summary>
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0"), _
<Global.System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0"), _
Global.System.Diagnostics.DebuggerNonUserCodeAttribute(), _
Global.System.Runtime.CompilerServices.CompilerGeneratedAttribute(), _
Global.Microsoft.VisualBasic.HideModuleNameAttribute()> _
......@@ -12243,6 +12243,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
'''<summary>
''' Looks up a localized string similar to Supported language versions:.
'''</summary>
Friend ReadOnly Property IDS_LangVersions() As String
Get
Return ResourceManager.GetString("IDS_LangVersions", resourceCulture)
End Get
End Property
'''<summary>
''' Looks up a localized string similar to {0} version {1}.
'''</summary>
......
......@@ -5045,6 +5045,9 @@
<data name="IDS_LogoLine2" xml:space="preserve">
<value>Copyright (C) Microsoft Corporation. All rights reserved.</value>
</data>
<data name="IDS_LangVersions" xml:space="preserve">
<value>Supported language versions:</value>
</data>
<data name="IDS_VBCHelp" xml:space="preserve">
<value> Visual Basic Compiler Options
......@@ -5130,9 +5133,11 @@
/imports:&lt;import_list&gt; Declare global Imports for namespaces in
referenced metadata files.
import_list:namespace,...
/langversion:&lt;number&gt; Specify language version:
9|9.0|10|10.0|11|11.0|12|12.0|14|14.0|15|
15.0|15.3|15.6|default|latest
/langversion:? Display the allowed values for language version
/langversion:&lt;string&gt; Specify language version such as
`default` (latest major version), or
`latest` (latest version, including minor versions),
or specific versions like `14` or `15.3`
/optionexplicit[+|-] Require explicit declaration of variables.
/optioninfer[+|-] Allow type inference of variables.
/rootnamespace:&lt;string&gt; Specifies the root Namespace for all type
......
......@@ -1703,26 +1703,22 @@ End Module").Path
End Sub
<Fact>
Public Sub LanguageVersion_CommandLineUsage()
Dim expected = [Enum].GetValues(GetType(LanguageVersion)).Cast(Of LanguageVersion)().Select(Function(v) v.ToDisplayString())
Dim help = VBResources.IDS_VBCHelp
Dim rangeStart = help.IndexOf("/langversion")
Dim rangeEnd = help.IndexOf("/optionexplicit")
Assert.True(rangeEnd > rangeStart)
Public Sub LanguageVersion_ListLangVersions()
Dim dir = Temp.CreateDirectory()
Dim outWriter As New StringWriter()
Dim exitCode As Integer = New MockVisualBasicCompiler(Nothing, dir.ToString(), {"/langversion:?"}).Run(outWriter, Nothing)
Assert.Equal(0, exitCode)
Dim helpRange = help.Substring(rangeStart, rangeEnd - rangeStart).ToLowerInvariant()
Dim acceptableSurroundingChar = {CChar(vbCr), CChar(vbLf), "|"c, " "c}
Dim actual = outWriter.ToString()
Dim expected = [Enum].GetValues(GetType(LanguageVersion)).Cast(Of LanguageVersion)().Select(Function(v) v.ToDisplayString())
Dim acceptableSurroundingChar = {CChar(vbCr), CChar(vbLf), "("c, ")"c, " "c}
For Each v In expected
Dim foundIndex = helpRange.IndexOf(v)
Dim foundIndex = actual.IndexOf(v)
Assert.True(foundIndex > 0, $"Missing version '{v}'")
Assert.True(Array.IndexOf(acceptableSurroundingChar, helpRange(foundIndex - 1)) >= 0)
Assert.True(Array.IndexOf(acceptableSurroundingChar, helpRange(foundIndex + v.Length)) >= 0)
Assert.True(Array.IndexOf(acceptableSurroundingChar, actual(foundIndex - 1)) >= 0)
Assert.True(Array.IndexOf(acceptableSurroundingChar, actual(foundIndex + v.Length)) >= 0)
Next
' The canary check is a reminder that this test needs to be updated when a language version is added
LanguageVersionAdded_Canary()
End Sub
<Fact>
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册