diff --git a/NuGet.Config b/NuGet.Config
index 7ad028f274052..f3a854ff13377 100644
--- a/NuGet.Config
+++ b/NuGet.Config
@@ -18,6 +18,7 @@
+
diff --git a/Roslyn.sln b/Roslyn.sln
index c93853a9295be..57c8d98637fbb 100644
--- a/Roslyn.sln
+++ b/Roslyn.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
-VisualStudioVersion = 15.0.25920.0
+VisualStudioVersion = 15.0.26228.4
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeAnalysisTest", "src\Compilers\Core\CodeAnalysisTest\CodeAnalysisTest.csproj", "{A4C99B85-765C-4C65-9C2A-BB609AAB09E6}"
EndProject
@@ -235,8 +235,6 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ResultProvider.Portable", "
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "vbc", "src\Compilers\VisualBasic\vbc\vbc.csproj", "{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Pdb2Xml", "src\Tools\Source\Pdb2Xml\Pdb2Xml.csproj", "{CF450DCE-D12B-4A11-8D2D-A7A125372C48}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Setup", "Setup", "{19148439-436F-4CDA-B493-70AF4FFC13E9}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Features", "Features", "{2491A9B9-C0A8-49EE-9077-A32DE76E1E94}"
@@ -792,10 +790,6 @@ Global
{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1}.Release|Any CPU.Build.0 = Release|Any CPU
- {CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {CF450DCE-D12B-4A11-8D2D-A7A125372C48}.Release|Any CPU.Build.0 = Release|Any CPU
{E3CD2895-76A8-4D11-A316-EA67CB5EA42C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E3CD2895-76A8-4D11-A316-EA67CB5EA42C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E3CD2895-76A8-4D11-A316-EA67CB5EA42C}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -1096,7 +1090,6 @@ Global
{BEDC5A4A-809E-4017-9CFD-6C8D4E1847F0} = {998CAFE8-06E4-4683-A151-0F6AA4BFF6C6}
{FA0E905D-EC46-466D-B7B2-3B5557F9428C} = {998CAFE8-06E4-4683-A151-0F6AA4BFF6C6}
{E58EE9D7-1239-4961-A0C1-F9EC3952C4C1} = {C65C6143-BED3-46E6-869E-9F0BE6E84C37}
- {CF450DCE-D12B-4A11-8D2D-A7A125372C48} = {64BDF58B-41BA-A19E-0D34-B5FA598403B6}
{19148439-436F-4CDA-B493-70AF4FFC13E9} = {999FBDA2-33DA-4F74-B957-03AC72CCE5EC}
{2491A9B9-C0A8-49EE-9077-A32DE76E1E94} = {999FBDA2-33DA-4F74-B957-03AC72CCE5EC}
{5CA5F70E-0FDB-467B-B22C-3CD5994F0087} = {999FBDA2-33DA-4F74-B957-03AC72CCE5EC}
diff --git a/build/Targets/Dependencies.props b/build/Targets/Dependencies.props
index 279cf4abe3ccb..1957b6c346794 100644
--- a/build/Targets/Dependencies.props
+++ b/build/Targets/Dependencies.props
@@ -21,6 +21,7 @@
0.8.31-beta
1.0.35
1.1.0
+ 1.0.0-beta1-61515-01
1.5.0
1.2.0
1.1.0
diff --git a/build/config/SignToolData.json b/build/config/SignToolData.json
index 7f9c78ee5048b..3b03bfcfc19b8 100644
--- a/build/config/SignToolData.json
+++ b/build/config/SignToolData.json
@@ -55,7 +55,6 @@
"Exes\\vbccore\\vbc.exe",
"Exes\\vbi\\vbi.exe",
"Exes\\vbicore\\vbi.exe",
- "Exes\\Pdb2Xml\\Pdb2Xml.exe",
"Vsix\\CompilerExtension\\Roslyn.Compilers.Extension.dll",
"Vsix\\Templates\\Roslyn.Templates.dll",
"Vsix\\VisualStudioDiagnosticsWindow\\Roslyn.VisualStudio.DiagnosticsWindow.dll",
diff --git a/build/scripts/cibuild.ps1 b/build/scripts/cibuild.ps1
index c5991a7823ebd..eaf0af76bdf0c 100644
--- a/build/scripts/cibuild.ps1
+++ b/build/scripts/cibuild.ps1
@@ -104,15 +104,16 @@ try {
Run-MSBuild Roslyn.sln /p:Configuration=$buildConfiguration /p:DeployExtension=false
# Check if we have credentials to upload to benchview
- if ((Test-Path env:\GIT_BRANCH) -and (Test-Path BV_UPLOAD_SAS_TOKEN)) {
- $extraArgs="--report-benchview --branch $(env:GIT_BRANCH)"
+ $extraArgs = ""
+ if ((Test-Path env:\GIT_BRANCH) -and (Test-Path env:\BV_UPLOAD_SAS_TOKEN)) {
+ $extraArgs = "--report-benchview --branch $($env:GIT_BRANCH)"
# Check if we are in a PR or this is a rolling submission
if (Test-Path env:\ghprbPullTitle) {
- $extraArgs='$($extraArgs) --benchview-submission-name "[$($env:ghprbPullAuthorLogin)] PR $($env:ghprbPullId): $($env:ghprbPullTitle)" --benchview-submission-type private'
+ $extraArgs = '$($extraArgs) --benchview-submission-name "[$($env:ghprbPullAuthorLogin)] PR $($env:ghprbPullId): $($env:ghprbPullTitle)" --benchview-submission-type private'
}
else {
- $extraArgs='$(4extraArgs) --benchview-submission-type rolling'
+ $extraArgs = '$(4extraArgs) --benchview-submission-type rolling'
}
Create-Directory ".\Binaries\$buildConfiguration\tools\"
@@ -121,7 +122,10 @@ try {
}
Terminate-BuildProcesses
- Exec { & ".\Binaries\$buildConfiguration\Exes\Perf.Runner\Roslyn.Test.Performance.Runner.exe" --search-directory=".\\Binaries\\$buildConfiguration\\Dlls\\" --no-trace-upload $extraArgs }
+ & ".\Binaries\$buildConfiguration\Exes\Perf.Runner\Roslyn.Test.Performance.Runner.exe" --search-directory=".\\Binaries\\$buildConfiguration\\Dlls\\" --no-trace-upload $extraArgs
+ if (-not $?) {
+ throw "Perf run failed"
+ }
exit 0
}
diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
index b8de77a07ac40..15bd156c13e0f 100644
--- a/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
+++ b/src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
@@ -2079,7 +2079,7 @@ internal static void CheckFeatureAvailability(SyntaxNode syntax, MessageID featu
LanguageVersion requiredVersion = feature.RequiredVersion();
if (requiredVersion > availableVersion)
{
- diagnostics.Add(availableVersion.GetErrorCode(), location, feature.Localize(), requiredVersion.Localize());
+ diagnostics.Add(availableVersion.GetErrorCode(), location, feature.Localize(), new CSharpRequiredLanguageVersion(requiredVersion));
}
}
}
diff --git a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs
index 39d6699788197..f27c57ed273a5 100644
--- a/src/Compilers/CSharp/Portable/CSharpParseOptions.cs
+++ b/src/Compilers/CSharp/Portable/CSharpParseOptions.cs
@@ -50,32 +50,10 @@ public CSharpParseOptions(
IEnumerable preprocessorSymbols = null)
: this(languageVersion,
documentationMode,
- kind,
- preprocessorSymbols.ToImmutableArrayOrEmpty(),
+ kind,
+ preprocessorSymbols.ToImmutableArrayOrEmpty(),
ImmutableDictionary.Empty)
{
- // We test the mapped value, LanguageVersion, rather than the parameter, languageVersion,
- // which has not had "Latest" mapped to the latest version yet.
- if (!LanguageVersion.IsValid())
- {
- throw new ArgumentOutOfRangeException(nameof(languageVersion));
- }
-
- if (!kind.IsValid())
- {
- throw new ArgumentOutOfRangeException(nameof(kind));
- }
-
- if (preprocessorSymbols != null)
- {
- foreach (var preprocessorSymbol in preprocessorSymbols)
- {
- if (!SyntaxFacts.IsValidIdentifier(preprocessorSymbol))
- {
- throw new ArgumentException($"{nameof(preprocessorSymbols)} contains a symbol that is not a valid identifier", nameof(preprocessorSymbols));
- }
- }
- }
}
internal CSharpParseOptions(
@@ -83,15 +61,13 @@ internal CSharpParseOptions(
DocumentationMode documentationMode,
SourceCodeKind kind,
IEnumerable preprocessorSymbols,
- ImmutableDictionary features)
- : this(languageVersion, documentationMode, kind, preprocessorSymbols)
+ IReadOnlyDictionary features)
+ : base(kind, documentationMode)
{
- if (features == null)
- {
- throw new ArgumentNullException(nameof(features));
- }
-
- _features = features;
+ this.SpecifiedLanguageVersion = languageVersion;
+ this.LanguageVersion = languageVersion.MapSpecifiedToEffectiveVersion();
+ this.PreprocessorSymbols = preprocessorSymbols.ToImmutableArrayOrEmpty();
+ _features = features?.ToImmutableDictionary() ?? ImmutableDictionary.Empty;
}
private CSharpParseOptions(CSharpParseOptions other) : this(
@@ -99,41 +75,21 @@ private CSharpParseOptions(CSharpParseOptions other) : this(
documentationMode: other.DocumentationMode,
kind: other.Kind,
preprocessorSymbols: other.PreprocessorSymbols,
- features: other.Features.ToImmutableDictionary())
- {
- }
-
- // No validation
- private CSharpParseOptions(
- LanguageVersion languageVersion,
- DocumentationMode documentationMode,
- SourceCodeKind kind,
- ImmutableArray preprocessorSymbols,
- ImmutableDictionary features)
- : base(kind, documentationMode)
+ features: other.Features)
{
- Debug.Assert(!preprocessorSymbols.IsDefault);
- this.SpecifiedLanguageVersion = languageVersion;
- this.LanguageVersion = languageVersion.MapSpecifiedToEffectiveVersion();
- this.PreprocessorSymbols = preprocessorSymbols;
- _features = features;
}
-
+
public override string Language => LanguageNames.CSharp;
public new CSharpParseOptions WithKind(SourceCodeKind kind)
{
- if (kind == this.Kind)
+ if (kind == this.SpecifiedKind)
{
return this;
}
- if (!kind.IsValid())
- {
- throw new ArgumentOutOfRangeException(nameof(kind));
- }
-
- return new CSharpParseOptions(this) { Kind = kind };
+ var effectiveKind = kind.MapSpecifiedToEffectiveKind();
+ return new CSharpParseOptions(this) { SpecifiedKind = kind, Kind = effectiveKind };
}
public CSharpParseOptions WithLanguageVersion(LanguageVersion version)
@@ -144,11 +100,6 @@ public CSharpParseOptions WithLanguageVersion(LanguageVersion version)
}
var effectiveLanguageVersion = version.MapSpecifiedToEffectiveVersion();
- if (!effectiveLanguageVersion.IsValid())
- {
- throw new ArgumentOutOfRangeException(nameof(version));
- }
-
return new CSharpParseOptions(this) { SpecifiedLanguageVersion = version, LanguageVersion = effectiveLanguageVersion };
}
@@ -184,11 +135,6 @@ public CSharpParseOptions WithPreprocessorSymbols(ImmutableArray symbols
return this;
}
- if (!documentationMode.IsValid())
- {
- throw new ArgumentOutOfRangeException(nameof(documentationMode));
- }
-
return new CSharpParseOptions(this) { DocumentationMode = documentationMode };
}
@@ -212,12 +158,11 @@ protected override ParseOptions CommonWithFeatures(IEnumerable
public new CSharpParseOptions WithFeatures(IEnumerable> features)
{
- if (features == null)
- {
- throw new ArgumentNullException(nameof(features));
- }
+ ImmutableDictionary dictionary =
+ features?.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase)
+ ?? ImmutableDictionary.Empty;
- return new CSharpParseOptions(this) { _features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase) };
+ return new CSharpParseOptions(this) { _features = dictionary };
}
public override IReadOnlyDictionary Features
@@ -228,6 +173,32 @@ public override IReadOnlyDictionary Features
}
}
+ internal override void ValidateOptions(ArrayBuilder builder)
+ {
+ ValidateOptions(builder, MessageProvider.Instance);
+
+ // Validate LanguageVersion not SpecifiedLanguageVersion, after Latest/Default has been converted:
+ if (!LanguageVersion.IsValid())
+ {
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, (int)ErrorCode.ERR_BadLanguageVersion, LanguageVersion.ToString()));
+ }
+
+ if (!PreprocessorSymbols.IsDefaultOrEmpty)
+ {
+ foreach (var symbol in PreprocessorSymbols)
+ {
+ if (symbol == null)
+ {
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, (int)ErrorCode.ERR_InvalidPreprocessingSymbol, "null"));
+ }
+ else if (!SyntaxFacts.IsValidIdentifier(symbol))
+ {
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, (int)ErrorCode.ERR_InvalidPreprocessingSymbol, symbol));
+ }
+ }
+ }
+ }
+
internal bool IsFeatureEnabled(MessageID feature)
{
string featureFlag = feature.RequiredFeature();
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs b/src/Compilers/CSharp/Portable/CSharpResources.Designer.cs
index 05f0ae7abe233..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 {
@@ -1330,6 +1330,15 @@ internal static string ERR_BadDirectivePlacement {
}
}
+ ///
+ /// Looks up a localized string similar to Provided documentation mode is unsupported or invalid: '{0}'..
+ ///
+ internal static string ERR_BadDocumentationMode {
+ get {
+ return ResourceManager.GetString("ERR_BadDocumentationMode", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to '{0}': user-defined conversions to or from the dynamic type are not allowed.
///
@@ -1618,6 +1627,15 @@ internal static string ERR_BadIteratorReturnRef {
}
}
+ ///
+ /// Looks up a localized string similar to Provided language version is unsupported or invalid: '{0}'..
+ ///
+ internal static string ERR_BadLanguageVersion {
+ get {
+ return ResourceManager.GetString("ERR_BadLanguageVersion", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to The modifier '{0}' is not valid for this item.
///
@@ -1861,6 +1879,15 @@ internal static string ERR_BadSKunknown {
}
}
+ ///
+ /// Looks up a localized string similar to Provided source code kind is unsupported or invalid: '{0}'.
+ ///
+ internal static string ERR_BadSourceCodeKind {
+ get {
+ return ResourceManager.GetString("ERR_BadSourceCodeKind", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Parameters or locals of type '{0}' cannot be declared in async methods or lambda expressions..
///
@@ -4426,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}'.
///
@@ -5641,6 +5677,15 @@ internal static string ERR_InvalidPathMap {
}
}
+ ///
+ /// Looks up a localized string similar to Invalid name for a preprocessing symbol; '{0}' is not a valid identifier.
+ ///
+ internal static string ERR_InvalidPreprocessingSymbol {
+ get {
+ return ResourceManager.GetString("ERR_InvalidPreprocessingSymbol", resourceCulture);
+ }
+ }
+
///
/// Looks up a localized string similar to Invalid preprocessor expression.
///
@@ -12105,7 +12150,7 @@ internal static string WRN_DefaultValueForUnconsumedLocation_Title {
}
///
- /// Looks up a localized string similar to Invalid value for '/define'; '{0}' is not a valid identifier.
+ /// Looks up a localized string similar to Invalid name for a preprocessing symbol; '{0}' is not a valid identifier.
///
internal static string WRN_DefineIdentifierRequired {
get {
@@ -12114,7 +12159,7 @@ internal static string WRN_DefineIdentifierRequired {
}
///
- /// Looks up a localized string similar to Invalid value for '/define'; not a valid identifier.
+ /// Looks up a localized string similar to Invalid name for a preprocessing symbol; not a valid identifier.
///
internal static string WRN_DefineIdentifierRequired_Title {
get {
diff --git a/src/Compilers/CSharp/Portable/CSharpResources.resx b/src/Compilers/CSharp/Portable/CSharpResources.resx
index f5ced08a92dff..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
@@ -3321,10 +3321,10 @@ Give the compiler some way to differentiate the methods. For example, you can gi
'id#' syntax is no longer supported. Use '$id' instead.
- Invalid value for '/define'; '{0}' is not a valid identifier
+ Invalid name for a preprocessing symbol; '{0}' is not a valid identifier
- Invalid value for '/define'; not a valid identifier
+ Invalid name for a preprocessing symbol; not a valid identifier
Cannot create short filename '{0}' when a long filename with the same short filename already exists
@@ -5020,4 +5020,19 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
It is not legal to use the type 'dynamic' in a pattern.
+
+ Provided documentation mode is unsupported or invalid: '{0}'.
+
+
+ Provided source code kind is unsupported or invalid: '{0}'
+
+
+ Provided language version is unsupported or invalid: '{0}'.
+
+
+ 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/CommandLine/CSharpCommandLineParser.cs b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
index f83230991b3f1..89926ce2c350d 100644
--- a/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
+++ b/src/Compilers/CSharp/Portable/CommandLine/CSharpCommandLineParser.cs
@@ -805,7 +805,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
{
AddDiagnostic(diagnostics, ErrorCode.ERR_SwitchNeedsString, MessageID.IDS_Text.Localize(), "/langversion:");
}
- else if (!TryParseLanguageVersion(value, out languageVersion))
+ else if (!value.TryParse(out languageVersion))
{
AddDiagnostic(diagnostics, ErrorCode.ERR_BadCompatMode, value);
}
@@ -1217,12 +1217,10 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
languageVersion: languageVersion,
preprocessorSymbols: defines.ToImmutableAndFree(),
documentationMode: parseDocumentationComments ? DocumentationMode.Diagnose : DocumentationMode.None,
- kind: SourceCodeKind.Regular,
+ kind: IsScriptRunner ? SourceCodeKind.Script : SourceCodeKind.Regular,
features: parsedFeatures
);
- var scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script);
-
// We want to report diagnostics with source suppression in the error log file.
// However, these diagnostics won't be reported on the command line.
var reportSuppressedDiagnostics = errorLogPath != null;
@@ -1271,6 +1269,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
// add option incompatibility errors if any
diagnostics.AddRange(options.Errors);
+ diagnostics.AddRange(parseOptions.Errors);
return new CSharpCommandLineArguments
{
@@ -1307,7 +1306,7 @@ internal sealed override CommandLineArguments CommonParse(IEnumerable ar
DisplayVersion = displayVersion,
ManifestResources = managedResources.AsImmutable(),
CompilationOptions = options,
- ParseOptions = IsScriptRunner ? scriptParseOptions : parseOptions,
+ ParseOptions = parseOptions,
EmitOptions = emitOptions,
ScriptArguments = scriptArgs.AsImmutableOrEmpty(),
TouchedFilesPath = touchedFilesPath,
@@ -1470,7 +1469,7 @@ private ImmutableArray BuildSearchPaths(string sdkDirectoryOpt, List ParseConditionalCompilationSymbols(string value, out IEnumerable diagnostics)
{
- Diagnostic myDiagnostic = null;
+ DiagnosticBag outputDiagnostics = DiagnosticBag.GetInstance();
value = value.TrimEnd(null);
// Allow a trailing semicolon or comma in the options
@@ -1490,15 +1489,13 @@ public static IEnumerable ParseConditionalCompilationSymbols(string valu
{
defines.Add(trimmedId);
}
- else if (myDiagnostic == null)
+ else
{
- myDiagnostic = Diagnostic.Create(CSharp.MessageProvider.Instance, (int)ErrorCode.WRN_DefineIdentifierRequired, trimmedId);
+ outputDiagnostics.Add(Diagnostic.Create(CSharp.MessageProvider.Instance, (int)ErrorCode.WRN_DefineIdentifierRequired, trimmedId));
}
}
- diagnostics = myDiagnostic == null ? SpecializedCollections.EmptyEnumerable()
- : SpecializedCollections.SingletonEnumerable(myDiagnostic);
-
+ diagnostics = outputDiagnostics.ToReadOnlyAndFree();
return defines.AsEnumerable();
}
@@ -1761,56 +1758,6 @@ internal static ResourceDescription ParseResourceDescription(
return new ResourceDescription(resourceName, fileName, dataProvider, isPublic, embedded, checkArgs: false);
}
- private static bool TryParseLanguageVersion(string str, out LanguageVersion version)
- {
- if (str == null)
- {
- version = LanguageVersion.Default;
- return true;
- }
-
- switch (str.ToLowerInvariant())
- {
- case "iso-1":
- version = LanguageVersion.CSharp1;
- return true;
-
- case "iso-2":
- version = LanguageVersion.CSharp2;
- return true;
-
- case "7":
- version = LanguageVersion.CSharp7;
- return true;
-
- case "default":
- version = LanguageVersion.Default;
- return true;
-
- case "latest":
- version = LanguageVersion.Latest;
- 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) &&
- versionNumber <= 6 &&
- ((LanguageVersion)versionNumber).IsValid())
- {
- version = (LanguageVersion)versionNumber;
- return true;
- }
-
- version = LanguageVersion.Default;
- return false;
- }
- }
-
private static IEnumerable ParseWarnings(string value)
{
value = value.Unquote();
diff --git a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
index f1c43315e2751..a163e9ecc6b49 100644
--- a/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
+++ b/src/Compilers/CSharp/Portable/Compilation/CSharpCompilation.cs
@@ -1940,6 +1940,20 @@ internal ImmutableArray GetDiagnostics(CompilationStage stage, bool
builder.AddRange(syntaxTree.GetDiagnostics(cancellationToken));
}
}
+
+ var parseOptionsReported = new HashSet();
+ foreach (var syntaxTree in syntaxTrees)
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+ if (!syntaxTree.Options.Errors.IsDefaultOrEmpty && parseOptionsReported.Add(syntaxTree.Options))
+ {
+ var location = syntaxTree.GetLocation(TextSpan.FromBounds(0, 0));
+ foreach (var error in syntaxTree.Options.Errors)
+ {
+ builder.Add(error.WithLocation(location));
+ }
+ }
+ }
}
if (stage == CompilationStage.Declare || stage > CompilationStage.Declare && includeEarlierStages)
diff --git a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
index 3036a614c69cd..29a51eff04724 100644
--- a/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
+++ b/src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
@@ -1439,7 +1439,13 @@ internal enum ErrorCode
ERR_DelegateRefMismatch = 8189,
#endregion stragglers for C# 7
- // Available = 8190-8195
+ #region diagnostics for parse options
+ ERR_BadSourceCodeKind = 8190,
+ ERR_BadDocumentationMode = 8191,
+ ERR_BadLanguageVersion = 8192,
+ #endregion
+
+ // Available = 8193-8195
#region diagnostics for out var
ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList = 8196,
@@ -1461,5 +1467,7 @@ internal enum ErrorCode
#endregion more stragglers for C# 7
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/Errors/MessageProvider.cs b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
index b7dc830404811..88f4689b56e38 100644
--- a/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
+++ b/src/Compilers/CSharp/Portable/Errors/MessageProvider.cs
@@ -146,6 +146,10 @@ public override ReportDiagnostic GetDiagnosticReport(DiagnosticInfo diagnosticIn
public override int ERR_CantReadRulesetFile => (int)ErrorCode.ERR_CantReadRulesetFile;
public override int ERR_CompileCancelled => (int)ErrorCode.ERR_CompileCancelled;
+ // parse options:
+ public override int ERR_BadSourceCodeKind => (int)ErrorCode.ERR_BadSourceCodeKind;
+ public override int ERR_BadDocumentationMode => (int)ErrorCode.ERR_BadDocumentationMode;
+
// compilation options:
public override int ERR_BadCompilationOptionValue => (int)ErrorCode.ERR_BadCompilationOptionValue;
public override int ERR_MutuallyExclusiveOptions => (int)ErrorCode.ERR_MutuallyExclusiveOptions;
diff --git a/src/Compilers/CSharp/Portable/LanguageVersion.cs b/src/Compilers/CSharp/Portable/LanguageVersion.cs
index fa89df7158d9f..ee433a587f845 100644
--- a/src/Compilers/CSharp/Portable/LanguageVersion.cs
+++ b/src/Compilers/CSharp/Portable/LanguageVersion.cs
@@ -1,5 +1,6 @@
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+using System.Globalization;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp
@@ -68,34 +69,35 @@ public enum LanguageVersion
///
CSharp7 = 7,
+ ///
+ /// C# language version 7.1
+ ///
+ CSharp7_1 = 701,
+
///
/// The latest version of the language supported.
///
Latest = int.MaxValue,
}
- internal static partial class LanguageVersionExtensions
+ internal static class LanguageVersionExtensionsInternal
{
- internal static LanguageVersion MapSpecifiedToEffectiveVersion(this LanguageVersion version)
+ internal static bool IsValid(this LanguageVersion value)
{
- switch (version)
+ switch (value)
{
- case LanguageVersion.Latest:
- case LanguageVersion.Default:
- return LanguageVersion.CSharp7;
- default:
- return version;
+ 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;
}
- }
- internal static bool IsValid(this LanguageVersion value)
- {
- return value >= LanguageVersion.CSharp1 && value <= LanguageVersion.CSharp7;
- }
-
- internal static object Localize(this LanguageVersion value)
- {
- return (int)value;
+ return false;
}
internal static ErrorCode GetErrorCode(this LanguageVersion version)
@@ -116,9 +118,123 @@ 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);
}
}
}
-}
+
+ internal class CSharpRequiredLanguageVersion : RequiredLanguageVersion
+ {
+ internal LanguageVersion Version { get; }
+
+ internal CSharpRequiredLanguageVersion(LanguageVersion version)
+ {
+ Version = version;
+ }
+
+ public override string ToString() => Version.ToDisplayString();
+ }
+
+ public static class LanguageVersionFacts
+ {
+ ///
+ /// Displays the version number in the format expected on the command-line (/langver flag).
+ /// For instance, "6", "7", "7.1", "latest".
+ ///
+ public static string ToDisplayString(this LanguageVersion version)
+ {
+ switch (version)
+ {
+ case LanguageVersion.CSharp1:
+ return "1";
+ case LanguageVersion.CSharp2:
+ return "2";
+ case LanguageVersion.CSharp3:
+ return "3";
+ case LanguageVersion.CSharp4:
+ return "4";
+ case LanguageVersion.CSharp5:
+ return "5";
+ case LanguageVersion.CSharp6:
+ return "6";
+ case LanguageVersion.CSharp7:
+ return "7";
+ case LanguageVersion.CSharp7_1:
+ return "7.1";
+ case LanguageVersion.Default:
+ return "default";
+ case LanguageVersion.Latest:
+ return "latest";
+ default:
+ throw ExceptionUtilities.UnexpectedValue(version);
+ }
+ }
+
+ ///
+ /// Parse a LanguageVersion from a string input, as the command-line compiler does.
+ ///
+ public static bool TryParse(this string version, out LanguageVersion result)
+ {
+ if (version == null)
+ {
+ result = LanguageVersion.Default;
+ return true;
+ }
+
+ switch (version.ToLowerInvariant())
+ {
+ case "iso-1":
+ result = LanguageVersion.CSharp1;
+ return true;
+
+ case "iso-2":
+ result = LanguageVersion.CSharp2;
+ return true;
+
+ case "default":
+ result = LanguageVersion.Default;
+ return true;
+
+ case "latest":
+ result = LanguageVersion.Latest;
+ return true;
+
+ case "7.1":
+ result = LanguageVersion.CSharp7_1;
+ return true;
+
+ default:
+ if (int.TryParse(version, NumberStyles.None, CultureInfo.InvariantCulture, out int versionNumber) && versionNumber <= 7)
+ {
+ result = (LanguageVersion)versionNumber;
+ if (result.IsValid())
+ {
+ return true;
+ }
+ }
+
+ result = LanguageVersion.Default;
+ return false;
+ }
+ }
+
+ ///
+ /// Map a language version (such as Default, Latest, or CSharpN) to a specific version (CSharpM).
+ ///
+ public static LanguageVersion MapSpecifiedToEffectiveVersion(this LanguageVersion version)
+ {
+ switch (version)
+ {
+ case LanguageVersion.Latest:
+ return LanguageVersion.CSharp7_1;
+ case LanguageVersion.Default:
+ return LanguageVersion.CSharp7;
+ default:
+ return version;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
index 5a323e0f3ff96..5decfac093449 100644
--- a/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/LanguageParser.cs
@@ -6488,7 +6488,7 @@ private TypeSyntax ParsePointerTypeMods(TypeSyntax type)
public StatementSyntax ParseStatement()
{
return ParseWithStackGuard(
- ParseStatementCore,
+ () => ParseStatementCore() ?? ParseExpressionStatement(),
() => SyntaxFactory.EmptyStatement(SyntaxFactory.MissingToken(SyntaxKind.SemicolonToken)));
}
@@ -7354,15 +7354,35 @@ private StatementSyntax ParseEmbeddedStatement(bool complexCheck)
statement = SyntaxFactory.EmptyStatement(EatToken(SyntaxKind.SemicolonToken));
}
- // An "embedded" statement is simply a statement that is not a labelled
- // statement or a declaration statement.
switch (statement.Kind)
{
+ // An "embedded" statement is simply a statement that is not a labelled
+ // statement or a declaration statement.
case SyntaxKind.LabeledStatement:
case SyntaxKind.LocalDeclarationStatement:
case SyntaxKind.LocalFunctionStatement:
statement = this.AddError(statement, ErrorCode.ERR_BadEmbeddedStmt);
break;
+ // In scripts, stand-alone expression statements may not be followed by semicolons.
+ // ParseExpressionStatement hides the error.
+ // However, embedded expression statements are required to be followed by semicolon.
+ case SyntaxKind.ExpressionStatement:
+ if (IsScript)
+ {
+ var expressionStatementSyntax = (ExpressionStatementSyntax)statement;
+ var semicolonToken = expressionStatementSyntax.SemicolonToken;
+
+ // Do not add a new error if the same error was already added.
+ if (semicolonToken.IsMissing
+ && (!semicolonToken.ContainsDiagnostics
+ || !semicolonToken.GetDiagnostics()
+ .Contains(diagnosticInfo => (ErrorCode)diagnosticInfo.Code == ErrorCode.ERR_SemicolonExpected)))
+ {
+ semicolonToken = this.AddError(semicolonToken, ErrorCode.ERR_SemicolonExpected);
+ statement = expressionStatementSyntax.Update(expressionStatementSyntax.Expression, semicolonToken);
+ }
+ }
+ break;
}
return statement;
@@ -9393,7 +9413,7 @@ private ExpressionSyntax ParsePostFixExpression(ExpressionSyntax expr)
// there is a new declaration on the next line.
if (this.CurrentToken.TrailingTrivia.Any((int)SyntaxKind.EndOfLineTrivia) &&
this.PeekToken(1).Kind == SyntaxKind.IdentifierToken &&
- this.PeekToken(2).Kind == SyntaxKind.IdentifierToken)
+ this.PeekToken(2).ContextualKind == SyntaxKind.IdentifierToken)
{
expr = _syntaxFactory.MemberAccessExpression(
SyntaxKind.SimpleMemberAccessExpression, expr, this.EatToken(),
diff --git a/src/Compilers/CSharp/Portable/Parser/Lexer.cs b/src/Compilers/CSharp/Portable/Parser/Lexer.cs
index 3b37c3087b6f4..d5e1b6ce1ac11 100644
--- a/src/Compilers/CSharp/Portable/Parser/Lexer.cs
+++ b/src/Compilers/CSharp/Portable/Parser/Lexer.cs
@@ -916,7 +916,8 @@ private void CheckFeatureAvailability(MessageID feature)
var requiredVersion = feature.RequiredVersion();
if (availableVersion >= requiredVersion) return;
var featureName = feature.Localize();
- this.AddError(availableVersion.GetErrorCode(), featureName, requiredVersion.Localize());
+
+ this.AddError(availableVersion.GetErrorCode(), featureName, new CSharpRequiredLanguageVersion(requiredVersion));
}
private bool ScanInteger()
diff --git a/src/Compilers/CSharp/Portable/Parser/SyntaxParser.cs b/src/Compilers/CSharp/Portable/Parser/SyntaxParser.cs
index f55e18caa6aea..7b50d32ebef8c 100644
--- a/src/Compilers/CSharp/Portable/Parser/SyntaxParser.cs
+++ b/src/Compilers/CSharp/Portable/Parser/SyntaxParser.cs
@@ -1074,11 +1074,12 @@ protected TNode CheckFeatureAvailability(TNode node, MessageID feature, b
if (forceWarning)
{
- SyntaxDiagnosticInfo rawInfo = new SyntaxDiagnosticInfo(availableVersion.GetErrorCode(), featureName, requiredVersion.Localize());
+ SyntaxDiagnosticInfo rawInfo = new SyntaxDiagnosticInfo(availableVersion.GetErrorCode(), featureName,
+ new CSharpRequiredLanguageVersion(requiredVersion));
return this.AddError(node, ErrorCode.WRN_ErrorOverride, rawInfo, rawInfo.Code);
}
- return this.AddError(node, availableVersion.GetErrorCode(), featureName, requiredVersion.Localize());
+ return this.AddError(node, availableVersion.GetErrorCode(), featureName, new CSharpRequiredLanguageVersion(requiredVersion));
}
}
diff --git a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
index 852cc70b12dd2..05206cd42bdcd 100644
--- a/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
@@ -13,8 +13,10 @@ 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
Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax.ExpressionBody.get -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax.Update(Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.SyntaxToken keyword, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody, Microsoft.CodeAnalysis.SyntaxToken semicolonToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax.WithExpressionBody(Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
@@ -260,6 +262,9 @@ static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Mic
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.TupleElementSyntax declarationSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.ISymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetDeclaredSymbol(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.TupleExpressionSyntax declaratorSyntax, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.INamedTypeSymbol
static Microsoft.CodeAnalysis.CSharp.CSharpExtensions.GetForEachStatementInfo(this Microsoft.CodeAnalysis.SemanticModel semanticModel, Microsoft.CodeAnalysis.CSharp.Syntax.CommonForEachStatementSyntax forEachStatement) -> Microsoft.CodeAnalysis.CSharp.ForEachStatementInfo
+static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts.MapSpecifiedToEffectiveVersion(this Microsoft.CodeAnalysis.CSharp.LanguageVersion version) -> Microsoft.CodeAnalysis.CSharp.LanguageVersion
+static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts.ToDisplayString(this Microsoft.CodeAnalysis.CSharp.LanguageVersion version) -> string
+static Microsoft.CodeAnalysis.CSharp.LanguageVersionFacts.TryParse(this string version, out Microsoft.CodeAnalysis.CSharp.LanguageVersion result) -> bool
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AccessorDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AccessorDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.CSharp.Syntax.BlockSyntax body) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
static Microsoft.CodeAnalysis.CSharp.SyntaxFactory.AccessorDeclaration(Microsoft.CodeAnalysis.CSharp.SyntaxKind kind, Microsoft.CodeAnalysis.SyntaxList attributeLists, Microsoft.CodeAnalysis.SyntaxTokenList modifiers, Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax expressionBody) -> Microsoft.CodeAnalysis.CSharp.Syntax.AccessorDeclarationSyntax
diff --git a/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs b/src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
index 930f4710de55c..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,50 +1290,106 @@ 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]
- public void RememberToUpdateDiagnosticsWhenUpdatingLangVersion()
+ public void LanguageVersionAdded_Canary()
{
- // When new language versions are added, this test will fail. Remember to update the diagnostics message (ERR_BadCompatMode).
- Assert.Equal(LanguageVersion.CSharp7, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion());
+ // When a new version is added, this test will break. This list must be checked:
+ // - update the command-line error for bad /langver flag ()
+ // - 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_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", "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"
+ }
+
+ [Fact]
+ public void LanguageVersion_MapSpecifiedToEffectiveVersion()
+ {
+ Assert.Equal(LanguageVersion.CSharp1, LanguageVersion.CSharp1.MapSpecifiedToEffectiveVersion());
+ Assert.Equal(LanguageVersion.CSharp2, LanguageVersion.CSharp2.MapSpecifiedToEffectiveVersion());
+ Assert.Equal(LanguageVersion.CSharp3, LanguageVersion.CSharp3.MapSpecifiedToEffectiveVersion());
+ Assert.Equal(LanguageVersion.CSharp4, LanguageVersion.CSharp4.MapSpecifiedToEffectiveVersion());
+ Assert.Equal(LanguageVersion.CSharp5, LanguageVersion.CSharp5.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_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();
+ }
+
+ [Theory,
+ InlineData("iso-1", true, LanguageVersion.CSharp1),
+ InlineData("ISO-1", true, LanguageVersion.CSharp1),
+ InlineData("iso-2", true, LanguageVersion.CSharp2),
+ InlineData("1", true, LanguageVersion.CSharp1),
+ InlineData("2", true, LanguageVersion.CSharp2),
+ InlineData("3", true, LanguageVersion.CSharp3),
+ InlineData("4", true, LanguageVersion.CSharp4),
+ InlineData("5", true, LanguageVersion.CSharp5),
+ InlineData("05", true, LanguageVersion.CSharp5),
+ InlineData("6", true, LanguageVersion.CSharp6),
+ InlineData("7", true, LanguageVersion.CSharp7),
+ 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),
+ InlineData("bad", false, LanguageVersion.Default)]
+ public void LanguageVersion_TryParseDisplayString(string input, bool success, LanguageVersion expected)
+ {
+ Assert.Equal(success, input.TryParse(out var version));
+ Assert.Equal(expected, version);
+
+ // The canary check is a reminder that this test needs to be updated when a language version is added
+ LanguageVersionAdded_Canary();
+ }
+
[Fact]
[WorkItem(546961, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546961")]
public void Define()
@@ -1384,7 +1442,7 @@ public void Define()
var nonCompliant = "def1;;def2;";
parsed = CSharpCommandLineParser.ParseConditionalCompilationSymbols(nonCompliant, out diagnostics);
diagnostics.Verify(
- // warning CS2029: Invalid value for '/define'; '' is not a valid identifier
+ // warning CS2029: Invalid name for a preprocessing symbol; '' is not a valid identifier
Diagnostic(ErrorCode.WRN_DefineIdentifierRequired).WithArguments(""));
Assert.Equal(new[] { "def1", "def2" }, parsed);
@@ -6363,7 +6421,7 @@ public void InvalidDefineSwitch()
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), @"/define:""""" }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal("warning CS2029: Invalid value for '/define'; '' is not a valid identifier", outWriter.ToString().Trim());
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; '' is not a valid identifier", outWriter.ToString().Trim());
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), "/define: " }).Run(outWriter);
@@ -6378,29 +6436,32 @@ public void InvalidDefineSwitch()
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), "/define:,,," }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal("warning CS2029: Invalid value for '/define'; '' is not a valid identifier", outWriter.ToString().Trim());
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; '' is not a valid identifier", outWriter.ToString().Trim());
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), "/define:,blah,Blah" }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal("warning CS2029: Invalid value for '/define'; '' is not a valid identifier", outWriter.ToString().Trim());
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; '' is not a valid identifier", outWriter.ToString().Trim());
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), "/define:a;;b@" }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal("warning CS2029: Invalid value for '/define'; '' is not a valid identifier", outWriter.ToString().Trim());
+ var errorLines = outWriter.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; '' is not a valid identifier", errorLines[0]);
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; 'b@' is not a valid identifier", errorLines[1]);
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), "/define:a,b@;" }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal("warning CS2029: Invalid value for '/define'; 'b@' is not a valid identifier", outWriter.ToString().Trim());
+ Assert.Equal("warning CS2029: Invalid name for a preprocessing symbol; 'b@' is not a valid identifier", outWriter.ToString().Trim());
//Bug 531612 - Native would normally not give the 2nd warning
outWriter = new StringWriter(CultureInfo.InvariantCulture);
exitCode = new MockCSharpCompiler(null, _baseDirectory, new[] { "/nologo", "/preferreduilang:en", "/t:library", src.ToString(), @"/define:OE_WIN32=-1:LANG_HOST_EN=-1:LANG_OE_EN=-1:LANG_PRJ_EN=-1:HOST_COM20SDKEVERETT=-1:EXEMODE=-1:OE_NT5=-1:Win32=-1", @"/d:TRACE=TRUE,DEBUG=TRUE" }).Run(outWriter);
Assert.Equal(0, exitCode);
- Assert.Equal(@"warning CS2029: Invalid value for '/define'; 'OE_WIN32=-1:LANG_HOST_EN=-1:LANG_OE_EN=-1:LANG_PRJ_EN=-1:HOST_COM20SDKEVERETT=-1:EXEMODE=-1:OE_NT5=-1:Win32=-1' is not a valid identifier
-warning CS2029: Invalid value for '/define'; 'TRACE=TRUE' is not a valid identifier", outWriter.ToString().Trim());
+ errorLines = outWriter.ToString().Trim().Split(new string[] { Environment.NewLine }, StringSplitOptions.None);
+ Assert.Equal(@"warning CS2029: Invalid name for a preprocessing symbol; 'OE_WIN32=-1:LANG_HOST_EN=-1:LANG_OE_EN=-1:LANG_PRJ_EN=-1:HOST_COM20SDKEVERETT=-1:EXEMODE=-1:OE_NT5=-1:Win32=-1' is not a valid identifier", errorLines[0]);
+ Assert.Equal(@"warning CS2029: Invalid name for a preprocessing symbol; 'TRACE=TRUE' is not a valid identifier", errorLines[1]);
CleanupAllGeneratedFiles(src.Path);
}
@@ -8883,6 +8944,37 @@ public void Version()
}
}
+ [Fact]
+ public void CompilingCodeWithInvalidPreProcessorSymbolsShouldProvideDiagnostics()
+ {
+ var parsedArgs = DefaultParse(new[] { "/define:1", "a.cs" }, _baseDirectory);
+ parsedArgs.Errors.Verify(
+ // warning CS2029: Invalid name for a preprocessing symbol; '1' is not a valid identifier
+ Diagnostic(ErrorCode.WRN_DefineIdentifierRequired).WithArguments("1").WithLocation(1, 1));
+ }
+
+ [Fact]
+ 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.
+ Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("1000").WithLocation(1, 1));
+ }
+
+ [Fact, WorkItem(16913, "https://github.com/dotnet/roslyn/issues/16913")]
+ public void CompilingCodeWithMultipleInvalidPreProcessorSymbolsShouldErrorOut()
+ {
+ var parsedArgs = DefaultParse(new[] { "/define:valid1,2invalid,valid3", "/define:4,5,valid6", "a.cs" }, _baseDirectory);
+ parsedArgs.Errors.Verify(
+ // warning CS2029: Invalid value for '/define'; '2invalid' is not a valid identifier
+ Diagnostic(ErrorCode.WRN_DefineIdentifierRequired).WithArguments("2invalid"),
+ // warning CS2029: Invalid value for '/define'; '4' is not a valid identifier
+ Diagnostic(ErrorCode.WRN_DefineIdentifierRequired).WithArguments("4"),
+ // warning CS2029: Invalid value for '/define'; '5' is not a valid identifier
+ Diagnostic(ErrorCode.WRN_DefineIdentifierRequired).WithArguments("5"));
+ }
+
public class QuotedArgumentTests
{
private void VerifyQuotedValid(string name, string value, T expected, Func getValue)
diff --git a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
index 3b9eeb1c190b0..f7387c4b2a074 100644
--- a/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
+++ b/src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
@@ -9219,6 +9219,10 @@ static void Main()
// CS0151ERR_IntegralTypeValueExpected}
Diagnostic(ErrorCode.ERR_InvalidMemberDecl, "}").WithArguments("}").WithLocation(8, 36)
);
+
+ Assert.Equal("7", Compilation.GetRequiredLanguageVersion(comp.GetDiagnostics()[0]));
+ Assert.Null(Compilation.GetRequiredLanguageVersion(comp.GetDiagnostics()[2]));
+ Assert.Throws(() => Compilation.GetRequiredLanguageVersion(null));
}
[Fact]
diff --git a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
index a0fa5bba7f79f..bd7c85b7f815f 100644
--- a/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
+++ b/src/Compilers/CSharp/Test/Emit/PDB/PDBTests.cs
@@ -14,6 +14,7 @@
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
+using Microsoft.DiaSymReader.Tools;
using Roslyn.Test.PdbUtilities;
using Roslyn.Test.Utilities;
using Xunit;
diff --git a/src/Compilers/CSharp/Test/Semantic/Diagnostics/GetDiagnosticsTests.cs b/src/Compilers/CSharp/Test/Semantic/Diagnostics/GetDiagnosticsTests.cs
index 1b8205d5cdb91..c527dffe9b8ec 100644
--- a/src/Compilers/CSharp/Test/Semantic/Diagnostics/GetDiagnosticsTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Diagnostics/GetDiagnosticsTests.cs
@@ -299,5 +299,100 @@ public void TestEventQueueCompletionForEmptyCompilation()
Assert.True(compilation.EventQueue.IsCompleted);
}
+
+ [Fact]
+ public void CompilingCodeWithInvalidPreProcessorSymbolsShouldProvideDiagnostics()
+ {
+ var compilation = CreateCompilation(string.Empty, parseOptions: new CSharpParseOptions().WithPreprocessorSymbols(new[] { "1" }));
+
+ compilation.VerifyDiagnostics(
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '1' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("1").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void CompilingCodeWithInvalidSourceCodeKindShouldProvideDiagnostics()
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ var compilation = CreateCompilationWithMscorlib45(string.Empty, parseOptions: new CSharpParseOptions().WithKind(SourceCodeKind.Interactive));
+#pragma warning restore CS0618 // Type or member is obsolete
+
+ compilation.VerifyDiagnostics(
+ // (1,1): error CS8190: Provided source code kind is unsupported or invalid: 'Interactive'
+ //
+ Diagnostic(ErrorCode.ERR_BadSourceCodeKind, "").WithArguments("Interactive").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void CompilingCodeWithInvalidLanguageVersionShouldProvideDiagnostics()
+ {
+ var compilation = CreateCompilation(string.Empty, parseOptions: new CSharpParseOptions().WithLanguageVersion((LanguageVersion)10000));
+ compilation.VerifyDiagnostics(
+ // (1,1): error CS8192: Provided language version is unsupported or invalid: '10000'.
+ //
+ Diagnostic(ErrorCode.ERR_BadLanguageVersion, "").WithArguments("10000").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void CompilingCodeWithInvalidDocumentationModeShouldProvideDiagnostics()
+ {
+ var compilation = CreateCompilation(string.Empty, parseOptions: new CSharpParseOptions().WithDocumentationMode(unchecked((DocumentationMode)100)));
+ compilation.VerifyDiagnostics(
+ // (1,1): error CS8191: Provided documentation mode is unsupported or invalid: '100'.
+ //
+ Diagnostic(ErrorCode.ERR_BadDocumentationMode, "").WithArguments("100").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void CompilingCodeWithInvalidParseOptionsInMultipleSyntaxTreesShouldReportThemAll()
+ {
+ var syntaxTree1 = Parse(string.Empty, options: new CSharpParseOptions().WithPreprocessorSymbols(new[] { "1" }));
+ var syntaxTree2 = Parse(string.Empty, options: new CSharpParseOptions().WithPreprocessorSymbols(new[] { "2" }));
+ var syntaxTree3 = Parse(string.Empty, options: new CSharpParseOptions().WithPreprocessorSymbols(new[] { "3" }));
+
+ var compilation = CreateCompilation(new[] { syntaxTree1, syntaxTree2, syntaxTree3 });
+ var diagnostics = compilation.GetDiagnostics();
+
+ diagnostics.Verify(
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '1' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("1").WithLocation(1, 1),
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '2' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("2").WithLocation(1, 1),
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '3' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("3").WithLocation(1, 1));
+
+ Assert.True(diagnostics[0].Location.SourceTree.Equals(syntaxTree1));
+ Assert.True(diagnostics[1].Location.SourceTree.Equals(syntaxTree2));
+ Assert.True(diagnostics[2].Location.SourceTree.Equals(syntaxTree3));
+ }
+
+ [Fact]
+ public void CompilingCodeWithSameParseOptionsInMultipleSyntaxTreesShouldReportOnlyNonDuplicates()
+ {
+ var parseOptions1 = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "1" });
+ var parseOptions2 = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "2" });
+
+ var syntaxTree1 = Parse(string.Empty, options: parseOptions1);
+ var syntaxTree2 = Parse(string.Empty, options: parseOptions2);
+ var syntaxTree3 = Parse(string.Empty, options: parseOptions2);
+
+ var compilation = CreateCompilationWithMscorlib(new[] { syntaxTree1, syntaxTree2, syntaxTree3 });
+ var diagnostics = compilation.GetDiagnostics();
+
+ diagnostics.Verify(
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '1' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("1").WithLocation(1, 1),
+ // (1,1): error CS8301: Invalid name for a preprocessing symbol; '2' is not a valid identifier
+ //
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol, "").WithArguments("2").WithLocation(1, 1));
+
+ Assert.True(diagnostics[0].Location.SourceTree.Equals(syntaxTree1));
+ Assert.True(diagnostics[1].Location.SourceTree.Equals(syntaxTree2));
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs
index 481617dd9330a..2aa11ad5a61de 100644
--- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs
@@ -10,7 +10,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
- public partial class IOperationTests : CompilingTestBase
+ public partial class IOperationTests : SemanticModelTestBase
{
[Fact]
[WorkItem(382240, "https://devdiv.visualstudio.com/DevDiv/_workitems?id=382240")]
diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs
index c24cc6deae1ef..786a849684702 100644
--- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs
+++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.cs
@@ -9,7 +9,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
- public partial class IOperationTests : CompilingTestBase
+ public partial class IOperationTests : SemanticModelTestBase
{
[Fact, WorkItem(17595, "https://github.com/dotnet/roslyn/issues/17595")]
public void NoInitializers()
diff --git a/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs b/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs
index f8a07cfbc7b57..17afc57dd7443 100644
--- a/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs
+++ b/src/Compilers/CSharp/Test/Semantic/Semantics/ScriptSemanticsTests.cs
@@ -1150,15 +1150,6 @@ public void Errors_03()
);
}
- [Fact]
- [WorkItem(10023, "https://github.com/dotnet/roslyn/issues/10023")]
- public void NoNeedToTestSourceCodeKindInteractive()
- {
-#pragma warning disable CS0618
- Assert.Throws(() => new CSharp.CSharpParseOptions(kind: SourceCodeKind.Interactive));
-#pragma warning restore CS0618
- }
-
private static MemberAccessExpressionSyntax ErrorTestsGetNode(SyntaxTree syntaxTree)
{
var node1 = (CompilationUnitSyntax)syntaxTree.GetRoot();
diff --git a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs
index 513938589da49..b85f0344d0f3f 100644
--- a/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/IncrementalParsing/IncrementalParsingTests.cs
@@ -13,7 +13,7 @@
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
- public class IncrementalParsingTests
+ public class IncrementalParsingTests : TestBase
{
private CSharpParseOptions GetOptions(string[] defines)
{
@@ -2341,6 +2341,93 @@ public void InsertOpenBraceBeforeCodes()
CompareIncToFullParseErrors(reparsedTree, parsedTree);
}
+ [WorkItem(6676, "https://github.com/dotnet/roslyn/issues/6676")]
+ [Fact]
+ public void InsertExpressionStatementWithoutSemicolonBefore()
+ {
+ SourceText oldText = SourceText.From(@"System.Console.WriteLine(true)
+");
+ var startTree = SyntaxFactory.ParseSyntaxTree(oldText, options: TestOptions.Script);
+
+ startTree.GetDiagnostics().Verify();
+
+ var newText = oldText.WithChanges(new TextChange(new TextSpan(0, 0), @"System.Console.WriteLine(false)
+"));
+
+ AssertEx.AreEqual(@"System.Console.WriteLine(false)
+System.Console.WriteLine(true)
+",
+newText.ToString());
+
+ var reparsedTree = startTree.WithChangedText(newText);
+ var parsedTree = SyntaxFactory.ParseSyntaxTree(newText, options: TestOptions.Script);
+
+ parsedTree.GetDiagnostics().Verify(
+ // (1,32): error CS1002: ; expected
+ // System.Console.WriteLine(false)
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 32));
+
+ CompareIncToFullParseErrors(reparsedTree, parsedTree);
+ }
+
+ [WorkItem(6676, "https://github.com/dotnet/roslyn/issues/6676")]
+ [Fact]
+ public void InsertExpressionStatementWithoutSemicolonAfter()
+ {
+ SourceText oldText = SourceText.From(@"System.Console.WriteLine(true)
+");
+ var startTree = SyntaxFactory.ParseSyntaxTree(oldText, options: TestOptions.Script);
+
+ startTree.GetDiagnostics().Verify();
+
+ var newText = oldText.WithInsertAt(
+ oldText.Length,
+ @"System.Console.WriteLine(false)
+");
+
+ AssertEx.Equal(@"System.Console.WriteLine(true)
+System.Console.WriteLine(false)
+", newText.ToString());
+
+ var reparsedTree = startTree.WithChangedText(newText);
+
+ var parsedTree = SyntaxFactory.ParseSyntaxTree(newText, options: TestOptions.Script);
+ parsedTree.GetDiagnostics().Verify(
+ // (1,31): error CS1002: ; expected
+ // System.Console.WriteLine(true)
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(1, 31));
+
+ CompareIncToFullParseErrors(reparsedTree, parsedTree);
+ }
+
+ [WorkItem(6676, "https://github.com/dotnet/roslyn/issues/6676")]
+ [Fact]
+ public void MakeEmbeddedExpressionStatementWithoutSemicolon()
+ {
+ SourceText oldText = SourceText.From(@"System.Console.WriteLine(true)
+");
+ var startTree = SyntaxFactory.ParseSyntaxTree(oldText, options: TestOptions.Script);
+
+ startTree.GetDiagnostics().Verify();
+
+ var newText = oldText.WithChanges(new TextChange(new TextSpan(0, 0), @"if (false)
+"));
+
+ AssertEx.Equal(@"if (false)
+System.Console.WriteLine(true)
+", newText.ToString());
+
+ var reparsedTree = startTree.WithChangedText(newText);
+ var parsedTree = SyntaxFactory.ParseSyntaxTree(newText, options: TestOptions.Script);
+
+ parsedTree.GetDiagnostics().Verify(
+ // (2,31): error CS1002: ; expected
+ // System.Console.WriteLine(true)
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "").WithLocation(2, 31));
+
+ CompareIncToFullParseErrors(reparsedTree, parsedTree);
+ }
+
[WorkItem(531404, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/531404")]
[Fact]
public void AppendDisabledText()
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/CSharpParseOptionsTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/CSharpParseOptionsTests.cs
index 33d35123ee37a..8d47f1cef4058 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/CSharpParseOptionsTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/CSharpParseOptionsTests.cs
@@ -21,6 +21,17 @@ private void TestProperty(Func fac
Assert.Same(newOpt2, newOpt1);
}
+ [Fact]
+ [WorkItem(15358, "https://github.com/dotnet/roslyn/issues/15358")]
+ public void WithDocumentationModeDoesntChangeFeatures()
+ {
+ var kvp = new KeyValuePair("IOperation", "true");
+ var po = new CSharpParseOptions().WithFeatures(new[] { kvp });
+ Assert.Equal(po.Features.AsSingleton(), kvp);
+ var po2 = po.WithDocumentationMode(DocumentationMode.Diagnose);
+ Assert.Equal(po2.Features.AsSingleton(), kvp);
+ }
+
[Fact]
public void WithXxx()
{
@@ -29,32 +40,11 @@ public void WithXxx()
TestProperty((old, value) => old.WithDocumentationMode(value), opt => opt.DocumentationMode, DocumentationMode.None);
TestProperty((old, value) => old.WithPreprocessorSymbols(value), opt => opt.PreprocessorSymbols, ImmutableArray.Create("A", "B", "C"));
- Assert.Throws(() => CSharpParseOptions.Default.WithKind((SourceCodeKind)Int32.MaxValue));
- Assert.Throws(() => CSharpParseOptions.Default.WithLanguageVersion((LanguageVersion)1000));
-
Assert.Equal(0, CSharpParseOptions.Default.WithPreprocessorSymbols(ImmutableArray.Create("A", "B")).WithPreprocessorSymbols(default(ImmutableArray)).PreprocessorSymbols.Length);
Assert.Equal(0, CSharpParseOptions.Default.WithPreprocessorSymbols(ImmutableArray.Create("A", "B")).WithPreprocessorSymbols((IEnumerable)null).PreprocessorSymbols.Length);
Assert.Equal(0, CSharpParseOptions.Default.WithPreprocessorSymbols(ImmutableArray.Create("A", "B")).WithPreprocessorSymbols((string[])null).PreprocessorSymbols.Length);
}
- [Fact]
- public void ConstructorValidation()
- {
- Assert.Throws(() => new CSharpParseOptions(kind: (SourceCodeKind)Int32.MaxValue));
- Assert.Throws(() => new CSharpParseOptions(languageVersion: (LanguageVersion)1000));
- }
-
- [Fact(), WorkItem(546206, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/546206")]
- public void InvalidDefineSymbols()
- {
- // command line gives CS2029: Invalid value for '/define'; 'xxx' is not a valid identifier
- Assert.Throws(() => new CSharpParseOptions(preprocessorSymbols: ImmutableArray.Create("")));
- Assert.Throws(() => new CSharpParseOptions(preprocessorSymbols: ImmutableArray.Create(" ")));
- Assert.Throws(() => new CSharpParseOptions(preprocessorSymbols: ImmutableArray.Create("Good", "Bad.Symbol")));
- Assert.Throws(() => new CSharpParseOptions(preprocessorSymbols: ImmutableArray.Create("123", "Good")));
- Assert.Throws(() => new CSharpParseOptions(preprocessorSymbols: ImmutableArray.Create("Good", null, @"Bad\Symbol")));
- }
-
///
/// If this test fails, please update the
/// and methods to
@@ -73,5 +63,203 @@ public void TestFieldsForEqualsAndGetHashCode()
"PreprocessorSymbols",
"SpecifiedLanguageVersion");
}
+
+ [Fact]
+ public void SpecifiedKindIsMappedCorrectly()
+ {
+ var options = new CSharpParseOptions();
+ Assert.Equal(SourceCodeKind.Regular, options.Kind);
+ Assert.Equal(SourceCodeKind.Regular, options.SpecifiedKind);
+
+ options.Errors.Verify();
+
+ options = new CSharpParseOptions(kind: SourceCodeKind.Regular);
+ Assert.Equal(SourceCodeKind.Regular, options.Kind);
+ Assert.Equal(SourceCodeKind.Regular, options.SpecifiedKind);
+
+ options.Errors.Verify();
+
+ options = new CSharpParseOptions(kind: SourceCodeKind.Script);
+ Assert.Equal(SourceCodeKind.Script, options.Kind);
+ Assert.Equal(SourceCodeKind.Script, options.SpecifiedKind);
+
+ options.Errors.Verify();
+
+#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
+ options = new CSharpParseOptions(kind: SourceCodeKind.Interactive);
+ Assert.Equal(SourceCodeKind.Script, options.Kind);
+ Assert.Equal(SourceCodeKind.Interactive, options.SpecifiedKind);
+#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
+
+ options.Errors.Verify(
+ // error CS8190: Provided source code kind is unsupported or invalid: 'Interactive'.
+ Diagnostic(ErrorCode.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1));
+
+ options = new CSharpParseOptions(kind: (SourceCodeKind)int.MinValue);
+ Assert.Equal(SourceCodeKind.Regular, options.Kind);
+ Assert.Equal((SourceCodeKind)int.MinValue, options.SpecifiedKind);
+
+ options.Errors.Verify(
+ // warning CS8190: Provided source code kind is unsupported or invalid: '-2147483648'
+ Diagnostic(ErrorCode.ERR_BadSourceCodeKind).WithArguments("-2147483648").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void TwoOptionsWithDifferentSpecifiedKindShouldNotHaveTheSameHashCodes()
+ {
+ var options1 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+ var options2 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+
+ Assert.Equal(options1.GetHashCode(), options2.GetHashCode());
+
+ // They both map internally to SourceCodeKind.Script
+#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
+ options1 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+ options2 = new CSharpParseOptions(kind: SourceCodeKind.Interactive);
+#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
+
+ Assert.NotEqual(options1.GetHashCode(), options2.GetHashCode());
+ }
+
+ [Fact]
+ public void TwoOptionsWithDifferentSpecifiedKindShouldNotBeEqual()
+ {
+ var options1 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+ var options2 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+
+ Assert.True(options1.Equals(options2));
+
+ // They both map internally to SourceCodeKind.Script
+#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
+ options1 = new CSharpParseOptions(kind: SourceCodeKind.Script);
+ options2 = new CSharpParseOptions(kind: SourceCodeKind.Interactive);
+#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
+
+ Assert.False(options1.Equals(options2));
+ }
+
+ [Fact]
+ public void BadSourceCodeKindShouldProduceDiagnostics()
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ var options = new CSharpParseOptions(kind: SourceCodeKind.Interactive);
+#pragma warning restore CS0618 // Type or member is obsolete
+
+ options.Errors.Verify(
+ // error CS8190: Provided source code kind is unsupported or invalid: 'Interactive'.
+ Diagnostic(ErrorCode.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadDocumentationModeShouldProduceDiagnostics()
+ {
+ var options = new CSharpParseOptions(documentationMode: unchecked((DocumentationMode)100));
+
+ options.Errors.Verify(
+ // error CS8191: Provided documentation mode is unsupported or invalid: '100'.
+ Diagnostic(ErrorCode.ERR_BadDocumentationMode).WithArguments("100").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadLanguageVersionShouldProduceDiagnostics()
+ {
+ var options = new CSharpParseOptions(languageVersion: unchecked((LanguageVersion)10000));
+
+ options.Errors.Verify(
+ // error CS8191: Provided language version is unsupported or invalid: '10000'.
+ Diagnostic(ErrorCode.ERR_BadLanguageVersion).WithArguments("10000").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics()
+ {
+ var options = new CSharpParseOptions(preprocessorSymbols: new[] { "test", "1" });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; '1' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments("1").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadSourceCodeKindShouldProduceDiagnostics_WithVariation()
+ {
+#pragma warning disable CS0618 // Type or member is obsolete
+ var options = new CSharpParseOptions().WithKind(SourceCodeKind.Interactive);
+#pragma warning restore CS0618 // Type or member is obsolete
+
+ options.Errors.Verify(
+ // error CS8190: Provided source code kind is unsupported or invalid: 'Interactive'.
+ Diagnostic(ErrorCode.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadDocumentationModeShouldProduceDiagnostics_WithVariation()
+ {
+ var options = new CSharpParseOptions().WithDocumentationMode(unchecked((DocumentationMode)100));
+
+ options.Errors.Verify(
+ // error CS8191: Provided documentation mode is unsupported or invalid: '100'.
+ Diagnostic(ErrorCode.ERR_BadDocumentationMode).WithArguments("100").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadLanguageVersionShouldProduceDiagnostics_WithVariation()
+ {
+ var options = new CSharpParseOptions().WithLanguageVersion(unchecked((LanguageVersion)10000));
+
+ options.Errors.Verify(
+ // error CS8191: Provided language version is unsupported or invalid: '10000'.
+ Diagnostic(ErrorCode.ERR_BadLanguageVersion).WithArguments("10000").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics_EmptyString()
+ {
+ var options = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "" });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; '' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments("").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics_WhiteSpacetring()
+ {
+ var options = new CSharpParseOptions().WithPreprocessorSymbols(new[] { " " });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; ' ' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments(" ").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics_SymbolWithDots()
+ {
+ var options = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "Good", "Bad.Symbol" });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; 'Bad.Symbol' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments("Bad.Symbol").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics_SymbolWithSlashes()
+ {
+ var options = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "Good", "Bad\\Symbol" });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; 'Bad\Symbol' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments("Bad\\Symbol").WithLocation(1, 1));
+ }
+
+ [Fact]
+ public void BadPreProcessorSymbolsShouldProduceDiagnostics_NullSymbol()
+ {
+ var options = new CSharpParseOptions().WithPreprocessorSymbols(new[] { "Good", null });
+
+ options.Errors.Verify(
+ // error CS8301: Invalid name for a preprocessing symbol; 'null' is not a valid identifier
+ Diagnostic(ErrorCode.ERR_InvalidPreprocessingSymbol).WithArguments("null").WithLocation(1, 1));
+ }
}
}
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/ExpressionParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/ExpressionParsingTests.cs
index 184cbd0c2a940..15abb2c6810b9 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/ExpressionParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/ExpressionParsingTests.cs
@@ -3533,5 +3533,127 @@ void M()
EOF();
}
+ [Fact, WorkItem(17683, "https://github.com/dotnet/roslyn/issues/17683")]
+ public void Bug17683a()
+ {
+ var source =
+@"from t in e
+where
+t == Int32.
+MinValue
+select t";
+ UsingExpression(source);
+ N(SyntaxKind.QueryExpression);
+ {
+ N(SyntaxKind.FromClause);
+ {
+ N(SyntaxKind.FromKeyword);
+ N(SyntaxKind.IdentifierToken, "t");
+ N(SyntaxKind.InKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ }
+ N(SyntaxKind.QueryBody);
+ {
+ N(SyntaxKind.WhereClause);
+ {
+ N(SyntaxKind.WhereKeyword);
+ N(SyntaxKind.EqualsExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ N(SyntaxKind.EqualsEqualsToken);
+ N(SyntaxKind.SimpleMemberAccessExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Int32");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "MinValue");
+ }
+ }
+ }
+ }
+ N(SyntaxKind.SelectClause);
+ {
+ N(SyntaxKind.SelectKeyword);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "t");
+ }
+ }
+ }
+ }
+ EOF();
+ }
+
+ [Fact]
+ public void Bug17683b()
+ {
+ var source =
+@"switch (e)
+{
+ case Int32.
+ MaxValue when true:
+ break;
+}";
+ UsingStatement(source);
+ N(SyntaxKind.SwitchStatement);
+ {
+ N(SyntaxKind.SwitchKeyword);
+ N(SyntaxKind.OpenParenToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "e");
+ }
+ N(SyntaxKind.CloseParenToken);
+ N(SyntaxKind.OpenBraceToken);
+ N(SyntaxKind.SwitchSection);
+ {
+ N(SyntaxKind.CasePatternSwitchLabel);
+ {
+ N(SyntaxKind.CaseKeyword);
+ N(SyntaxKind.ConstantPattern);
+ {
+ N(SyntaxKind.SimpleMemberAccessExpression);
+ {
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "Int32");
+ }
+ N(SyntaxKind.DotToken);
+ N(SyntaxKind.IdentifierName);
+ {
+ N(SyntaxKind.IdentifierToken, "MaxValue");
+ }
+ }
+ }
+ N(SyntaxKind.WhenClause);
+ {
+ N(SyntaxKind.WhenKeyword);
+ N(SyntaxKind.TrueLiteralExpression);
+ {
+ N(SyntaxKind.TrueKeyword);
+ }
+ }
+ N(SyntaxKind.ColonToken);
+ }
+ N(SyntaxKind.BreakStatement);
+ {
+ N(SyntaxKind.BreakKeyword);
+ N(SyntaxKind.SemicolonToken);
+ }
+ }
+ N(SyntaxKind.CloseBraceToken);
+ }
+ EOF();
+ }
}
}
\ No newline at end of file
diff --git a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
index 6e27cef45f88d..61105c0f14c16 100644
--- a/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
+++ b/src/Compilers/CSharp/Test/Syntax/Parsing/StatementParsingTests.cs
@@ -6,16 +6,45 @@
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
+using Xunit.Abstractions;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
- public class StatementParsingTests
+ public class StatementParsingTests : ParsingTests
{
+ public StatementParsingTests(ITestOutputHelper output) : base(output) { }
+
private StatementSyntax ParseStatement(string text, int offset = 0, ParseOptions options = null)
{
return SyntaxFactory.ParseStatement(text, offset, options);
}
+ [Fact]
+ [WorkItem(17458, "https://github.com/dotnet/roslyn/issues/17458")]
+ public void ParsePrivate()
+ {
+ UsingStatement("private",
+ // (1,1): error CS1073: Unexpected token 'private'
+ // private
+ Diagnostic(ErrorCode.ERR_UnexpectedToken, "").WithArguments("private").WithLocation(1, 1),
+ // (1,1): error CS1525: Invalid expression term 'private'
+ // private
+ Diagnostic(ErrorCode.ERR_InvalidExprTerm, "private").WithArguments("private").WithLocation(1, 1),
+ // (1,1): error CS1002: ; expected
+ // private
+ Diagnostic(ErrorCode.ERR_SemicolonExpected, "private").WithLocation(1, 1)
+ );
+ M(SyntaxKind.ExpressionStatement);
+ {
+ M(SyntaxKind.IdentifierName);
+ {
+ M(SyntaxKind.IdentifierToken);
+ }
+ M(SyntaxKind.SemicolonToken);
+ }
+ EOF();
+ }
+
[Fact]
public void TestName()
{
@@ -2661,6 +2690,21 @@ protected override void M()
CSharpTestBase.Diagnostic(ErrorCode.ERR_RbraceExpected, "").WithLocation(9, 10));
}
+ [WorkItem(6676, "https://github.com/dotnet/roslyn/issues/6676")]
+ [Fact]
+ public void TestRunEmbeddedStatementNotFollowedBySemicolon()
+ {
+ var text = @"if (true)
+System.Console.WriteLine(true)";
+ var statement = this.ParseStatement(text);
+
+ Assert.NotNull(statement);
+ Assert.Equal(SyntaxKind.IfStatement, statement.Kind());
+ Assert.Equal(text, statement.ToString());
+ Assert.Equal(1, statement.Errors().Length);
+ Assert.Equal((int)ErrorCode.ERR_SemicolonExpected, statement.Errors()[0].Code);
+ }
+
private sealed class TokenAndTriviaWalker : CSharpSyntaxWalker
{
public int Tokens;
diff --git a/src/Compilers/Core/CodeAnalysisTest/CommonParseOptionsTests.cs b/src/Compilers/Core/CodeAnalysisTest/CommonParseOptionsTests.cs
index e1057ad8f3d66..bdbaf7ea375b6 100644
--- a/src/Compilers/Core/CodeAnalysisTest/CommonParseOptionsTests.cs
+++ b/src/Compilers/Core/CodeAnalysisTest/CommonParseOptionsTests.cs
@@ -19,10 +19,12 @@ public void TestFieldsForEqualsAndGetHashCode()
ReflectionAssert.AssertPublicAndInternalFieldsAndProperties(
typeof(ParseOptions),
"DocumentationMode",
- "Language",
+ "Errors",
"Features",
"Kind",
- "PreprocessorSymbolNames");
+ "Language",
+ "PreprocessorSymbolNames",
+ "SpecifiedKind");
}
}
}
diff --git a/src/Compilers/Core/Portable/Compilation/Compilation.cs b/src/Compilers/Core/Portable/Compilation/Compilation.cs
index 4eeb2bfd0298b..c270b6573f891 100644
--- a/src/Compilers/Core/Portable/Compilation/Compilation.cs
+++ b/src/Compilers/Core/Portable/Compilation/Compilation.cs
@@ -2803,5 +2803,34 @@ public ImmutableArray GetUnreferencedAssemblyIdentities(Diagno
}
internal abstract bool IsUnreferencedAssemblyIdentityDiagnosticCode(int code);
+
+ ///
+ /// Returns the required language version found in a , if any is found.
+ /// Returns null if none is found.
+ ///
+ public static string GetRequiredLanguageVersion(Diagnostic diagnostic)
+ {
+ if (diagnostic == null)
+ {
+ throw new ArgumentNullException(nameof(diagnostic));
+ }
+
+ bool found = false;
+ string foundVersion = null;
+ if (diagnostic.Arguments != null)
+ {
+ foreach (var argument in diagnostic.Arguments)
+ {
+ if (argument is RequiredLanguageVersion versionDiagnostic)
+ {
+ Debug.Assert(!found); // only one required language version in a given diagnostic
+ found = true;
+ foundVersion = versionDiagnostic.ToString();
+ }
+ }
+ }
+
+ return foundVersion;
+ }
}
}
\ No newline at end of file
diff --git a/src/Compilers/Core/Portable/Compilation/ParseOptions.cs b/src/Compilers/Core/Portable/Compilation/ParseOptions.cs
index 0de52ad0c257f..c22c8772414a9 100644
--- a/src/Compilers/Core/Portable/Compilation/ParseOptions.cs
+++ b/src/Compilers/Core/Portable/Compilation/ParseOptions.cs
@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
+using System.Collections.Immutable;
using System.ComponentModel;
using System.Linq;
using Roslyn.Utilities;
@@ -13,11 +14,19 @@ namespace Microsoft.CodeAnalysis
///
public abstract class ParseOptions
{
+ private readonly Lazy> _lazyErrors;
+
///
/// Specifies whether to parse as regular code files, script files or interactive code.
///
public SourceCodeKind Kind { get; protected set; }
+ ///
+ /// Gets the specified source code kind, which is the value that was specified in
+ /// the call to the constructor, or modified using the method.
+ ///
+ public SourceCodeKind SpecifiedKind { get; protected set; }
+
///
/// Gets a value indicating whether the documentation comments are parsed.
///
@@ -26,8 +35,16 @@ public abstract class ParseOptions
internal ParseOptions(SourceCodeKind kind, DocumentationMode documentationMode)
{
- this.Kind = kind;
+ this.SpecifiedKind = kind;
+ this.Kind = kind.MapSpecifiedToEffectiveKind();
this.DocumentationMode = documentationMode;
+
+ _lazyErrors = new Lazy>(() =>
+ {
+ var builder = ArrayBuilder.GetInstance();
+ ValidateOptions(builder);
+ return builder.ToImmutableAndFree();
+ });
}
///
@@ -35,6 +52,14 @@ internal ParseOptions(SourceCodeKind kind, DocumentationMode documentationMode)
///
public abstract string Language { get; }
+ ///
+ /// Errors collection related to an incompatible set of parse options
+ ///
+ public ImmutableArray Errors
+ {
+ get { return _lazyErrors.Value; }
+ }
+
///
/// Creates a new options instance with the specified source code kind.
///
@@ -43,6 +68,25 @@ public ParseOptions WithKind(SourceCodeKind kind)
return CommonWithKind(kind);
}
+ ///
+ /// Performs validation of options compatibilities and generates diagnostics if needed
+ ///
+ internal abstract void ValidateOptions(ArrayBuilder builder);
+
+ internal void ValidateOptions(ArrayBuilder builder, CommonMessageProvider messageProvider)
+ {
+ // Validate SpecifiedKind not Kind, to catch deprecated specified kinds:
+ if (!SpecifiedKind.IsValid())
+ {
+ builder.Add(messageProvider.CreateDiagnostic(messageProvider.ERR_BadSourceCodeKind, Location.None, SpecifiedKind.ToString()));
+ }
+
+ if (!DocumentationMode.IsValid())
+ {
+ builder.Add(messageProvider.CreateDiagnostic(messageProvider.ERR_BadDocumentationMode, Location.None, DocumentationMode.ToString()));
+ }
+ }
+
// It was supposed to be a protected implementation detail.
// The "pattern" we have for these is the public With* method is the only public callable one,
// and that forwards to the protected Common* like all the other methods in the class.
@@ -92,7 +136,7 @@ protected bool EqualsHelper(ParseOptions other)
}
return
- this.Kind == other.Kind &&
+ this.SpecifiedKind == other.SpecifiedKind &&
this.DocumentationMode == other.DocumentationMode &&
this.Features.SequenceEqual(other.Features) &&
(this.PreprocessorSymbolNames == null ? other.PreprocessorSymbolNames == null : this.PreprocessorSymbolNames.SequenceEqual(other.PreprocessorSymbolNames, StringComparer.Ordinal));
@@ -103,7 +147,7 @@ protected bool EqualsHelper(ParseOptions other)
protected int GetHashCodeHelper()
{
return
- Hash.Combine((int)this.Kind,
+ Hash.Combine((int)this.SpecifiedKind,
Hash.Combine((int)this.DocumentationMode,
Hash.Combine(HashFeatures(this.Features),
Hash.Combine(Hash.CombineValues(this.PreprocessorSymbolNames, StringComparer.Ordinal), 0))));
diff --git a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
index 8d729577a9634..94182e4719dc8 100644
--- a/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
+++ b/src/Compilers/Core/Portable/Diagnostic/CommonMessageProvider.cs
@@ -159,6 +159,10 @@ public DiagnosticInfo FilterDiagnosticInfo(DiagnosticInfo diagnosticInfo, Compil
public abstract int ERR_CantReadRulesetFile { get; }
public abstract int ERR_CompileCancelled { get; }
+ // parse options:
+ public abstract int ERR_BadSourceCodeKind { get; }
+ public abstract int ERR_BadDocumentationMode { get; }
+
// compilation options:
public abstract int ERR_BadCompilationOptionValue { get; }
public abstract int ERR_MutuallyExclusiveOptions { get; }
diff --git a/src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs b/src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs
index 63c07987f9a5e..16c5e418ab109 100644
--- a/src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs
+++ b/src/Compilers/Core/Portable/Diagnostic/Diagnostic.cs
@@ -507,4 +507,13 @@ internal virtual bool IsNotConfigurable()
return AnalyzerManager.HasNotConfigurableTag(this.CustomTags);
}
}
+
+ ///
+ /// This type is attached to diagnostics for required language version and should only be used
+ /// on such diagnostics, as they are recognized by .
+ ///
+ internal abstract class RequiredLanguageVersion : IMessageSerializable
+ {
+ public abstract override string ToString();
+ }
}
diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
index 04a4963d5f804..319ae4115b891 100644
--- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt
@@ -188,6 +188,8 @@ Microsoft.CodeAnalysis.OperationKind.VariableDeclarationStatement = 3 -> Microso
Microsoft.CodeAnalysis.OperationKind.WithStatement = 82 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.YieldBreakStatement = 12 -> Microsoft.CodeAnalysis.OperationKind
Microsoft.CodeAnalysis.OperationKind.YieldReturnStatement = 16 -> Microsoft.CodeAnalysis.OperationKind
+Microsoft.CodeAnalysis.ParseOptions.Errors.get -> System.Collections.Immutable.ImmutableArray
+Microsoft.CodeAnalysis.ParseOptions.SpecifiedKind.get -> Microsoft.CodeAnalysis.SourceCodeKind
Microsoft.CodeAnalysis.PortableExecutableReference.GetMetadataId() -> Microsoft.CodeAnalysis.MetadataId
Microsoft.CodeAnalysis.SemanticModel.GetOperation(Microsoft.CodeAnalysis.SyntaxNode node, System.Threading.CancellationToken cancellationToken = default(System.Threading.CancellationToken)) -> Microsoft.CodeAnalysis.IOperation
Microsoft.CodeAnalysis.Semantics.ArgumentKind
@@ -813,6 +815,7 @@ override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitWithStatement(Mic
override Microsoft.CodeAnalysis.Semantics.OperationWalker.VisitYieldBreakStatement(Microsoft.CodeAnalysis.Semantics.IReturnStatement operation) -> void
override Microsoft.CodeAnalysis.SyntaxNode.ToString() -> string
static Microsoft.CodeAnalysis.CaseInsensitiveComparison.StartsWith(string value, string possibleStart) -> bool
+static Microsoft.CodeAnalysis.Compilation.GetRequiredLanguageVersion(Microsoft.CodeAnalysis.Diagnostic diagnostic) -> string
static Microsoft.CodeAnalysis.EmbeddedText.FromBytes(string filePath, System.ArraySegment bytes, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1) -> Microsoft.CodeAnalysis.EmbeddedText
static Microsoft.CodeAnalysis.EmbeddedText.FromSource(string filePath, Microsoft.CodeAnalysis.Text.SourceText text) -> Microsoft.CodeAnalysis.EmbeddedText
static Microsoft.CodeAnalysis.EmbeddedText.FromStream(string filePath, System.IO.Stream stream, Microsoft.CodeAnalysis.Text.SourceHashAlgorithm checksumAlgorithm = Microsoft.CodeAnalysis.Text.SourceHashAlgorithm.Sha1) -> Microsoft.CodeAnalysis.EmbeddedText
diff --git a/src/Compilers/Core/Portable/SourceCodeKind.cs b/src/Compilers/Core/Portable/SourceCodeKind.cs
index ea36e0ce340c0..a32e5aff28195 100644
--- a/src/Compilers/Core/Portable/SourceCodeKind.cs
+++ b/src/Compilers/Core/Portable/SourceCodeKind.cs
@@ -32,6 +32,22 @@ public enum SourceCodeKind
internal static partial class SourceCodeKindExtensions
{
+ internal static SourceCodeKind MapSpecifiedToEffectiveKind(this SourceCodeKind kind)
+ {
+ switch (kind)
+ {
+ case SourceCodeKind.Script:
+#pragma warning disable CS0618 // SourceCodeKind.Interactive is obsolete
+ case SourceCodeKind.Interactive:
+#pragma warning restore CS0618 // SourceCodeKind.Interactive is obsolete
+ return SourceCodeKind.Script;
+
+ case SourceCodeKind.Regular:
+ default:
+ return SourceCodeKind.Regular;
+ }
+ }
+
internal static bool IsValid(this SourceCodeKind value)
{
return value >= SourceCodeKind.Regular && value <= SourceCodeKind.Script;
diff --git a/src/Compilers/Core/Portable/Syntax/SyntaxNodeExtensions.cs b/src/Compilers/Core/Portable/Syntax/SyntaxNodeExtensions.cs
index 6c99fab9767ef..423b6ef022b7a 100644
--- a/src/Compilers/Core/Portable/Syntax/SyntaxNodeExtensions.cs
+++ b/src/Compilers/Core/Portable/Syntax/SyntaxNodeExtensions.cs
@@ -409,9 +409,7 @@ public static TSyntax WithTrailingTrivia(
///
/// Creates a new node from this node with the trailing trivia removed.
///
- public static TSyntax WithoutTrailingTrivia(
- this TSyntax node
- ) where TSyntax : SyntaxNode
+ public static TSyntax WithoutTrailingTrivia(this TSyntax node) where TSyntax : SyntaxNode
{
return node.WithTrailingTrivia((IEnumerable)null);
}
diff --git a/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs b/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
index 7994fd0ecdf71..d9c8e73587e5f 100644
--- a/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
+++ b/src/Compilers/Test/Utilities/CSharp/SemanticModelTestBase.cs
@@ -6,9 +6,8 @@
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
-using Microsoft.CodeAnalysis.Text;
+using Microsoft.CodeAnalysis.Test.Utilities;
using Xunit;
-using Roslyn.Test.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
@@ -220,5 +219,41 @@ protected CompilationUtils.SemanticInfoSummary GetSemanticInfoForTest(string tes
{
return GetSemanticInfoForTest(testSrc);
}
+
+ protected string GetOperationTreeForTest(CSharpCompilation compilation)
+ where TSyntaxNode: SyntaxNode
+ {
+ var tree = compilation.SyntaxTrees[0];
+ var model = compilation.GetSemanticModel(tree);
+ SyntaxNode syntaxNode = GetSyntaxNodeOfTypeForBinding(GetSyntaxNodeList(tree));
+ if (syntaxNode == null)
+ {
+ return null;
+ }
+
+ var operation = model.GetOperationInternal(syntaxNode);
+ return operation != null ? OperationTreeVerifier.GetOperationTree(operation) : null;
+ }
+
+ protected string GetOperationTreeForTest(string testSrc, string expectedOperationTree, CSharpParseOptions parseOptions = null)
+ where TSyntaxNode : SyntaxNode
+ {
+ var compilation = CreateCompilationWithMscorlib(testSrc, new[] { SystemCoreRef }, parseOptions: parseOptions);
+ return GetOperationTreeForTest(compilation);
+ }
+
+ protected void VerifyOperationTreeForTest(CSharpCompilation compilation, string expectedOperationTree)
+ where TSyntaxNode : SyntaxNode
+ {
+ var actualOperationTree = GetOperationTreeForTest(compilation);
+ OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree);
+ }
+
+ protected void VerifyOperationTreeForTest(string testSrc, string expectedOperationTree, CSharpParseOptions parseOptions = null)
+ where TSyntaxNode : SyntaxNode
+ {
+ var actualOperationTree = GetOperationTreeForTest(testSrc, expectedOperationTree, parseOptions);
+ OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree);
+ }
}
}
diff --git a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
index 355601740cd89..5bc2250edcab2 100644
--- a/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
+++ b/src/Compilers/Test/Utilities/VisualBasic/CompilationTestUtils.vb
@@ -100,6 +100,15 @@ Friend Module CompilationUtils
Return VisualBasicCompilation.Create(If(assemblyName, GetUniqueName()), sourceTrees, If(references Is Nothing, additionalRefs, additionalRefs.Concat(references)), options)
End Function
+ Public Function CreateCompilationWithMscorlib45(source As String,
+ Optional references As IEnumerable(Of MetadataReference) = Nothing,
+ Optional options As VisualBasicCompilationOptions = Nothing,
+ Optional assemblyName As String = Nothing,
+ Optional parseOptions As VisualBasicParseOptions = Nothing) As VisualBasicCompilation
+ Dim additionalRefs = {MscorlibRef_v4_0_30316_17626}
+ Return VisualBasicCompilation.Create(If(assemblyName, GetUniqueName()), {Parse(source, parseOptions)}, If(references Is Nothing, additionalRefs, additionalRefs.Concat(references)), options)
+ End Function
+
Public Function CreateCompilationWithMscorlib45AndVBRuntime(sourceTrees As IEnumerable(Of SyntaxTree),
Optional references As IEnumerable(Of MetadataReference) = Nothing,
Optional options As VisualBasicCompilationOptions = Nothing) As VisualBasicCompilation
@@ -180,6 +189,14 @@ Friend Module CompilationUtils
Return CreateCompilationWithReferences(sources, references, options, parseOptions:=parseOptions)
End Function
+ Public Function CreateCompilationWithMscorlibAndVBRuntime(trees As IEnumerable(Of SyntaxTree),
+ options As VisualBasicCompilationOptions,
+ Optional assemblyName As String = Nothing) As VisualBasicCompilation
+
+ Dim references = {MscorlibRef, SystemRef, MsvbRef}
+ Return CreateCompilation(trees, references, options, assemblyName)
+ End Function
+
Public Function CreateCompilationWithMscorlibAndVBRuntime(sources As XElement,
options As VisualBasicCompilationOptions) As VisualBasicCompilation
Return CreateCompilationWithMscorlibAndVBRuntime(sources, Nothing, options, parseOptions:=If(options Is Nothing, Nothing, options.ParseOptions))
diff --git a/src/Compilers/Test/Utilities/VisualBasic/SemanticModelTestBase.vb b/src/Compilers/Test/Utilities/VisualBasic/SemanticModelTestBase.vb
index 7df729311b49b..f3ec8a71cb2b7 100644
--- a/src/Compilers/Test/Utilities/VisualBasic/SemanticModelTestBase.vb
+++ b/src/Compilers/Test/Utilities/VisualBasic/SemanticModelTestBase.vb
@@ -1,5 +1,6 @@
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
@@ -151,4 +152,32 @@ Public MustInherit Class SemanticModelTestBase : Inherits BasicTestBase
).Where(Function(s) anyArity OrElse DirectCast(s, Symbol).GetArity() = arity.Value).ToList()
End Function
+ Friend Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, Optional which As Integer = 0) As String
+ Dim node As SyntaxNode = CompilationUtils.FindBindingText(Of TSyntaxNode)(compilation, fileName, which)
+ If node Is Nothing Then
+ Return Nothing
+ End If
+
+ Dim tree = (From t In compilation.SyntaxTrees Where t.FilePath = fileName).Single()
+ Dim semanticModel = compilation.GetSemanticModel(tree)
+ Dim operation = semanticModel.GetOperationInternal(node)
+ Return If(operation IsNot Nothing, OperationTreeVerifier.GetOperationTree(operation), Nothing)
+ End Function
+
+ Friend Function GetOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0) As String
+ Dim fileName = "a.vb"
+ Dim syntaxTree = Parse(testSrc, fileName, parseOptions)
+ Dim compilation = CreateCompilationWithMscorlib(syntaxTree)
+ Return GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, which)
+ End Function
+
+ Friend Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(compilation As VisualBasicCompilation, fileName As String, expectedOperationTree As String, Optional which As Integer = 0)
+ Dim actualOperationTree = GetOperationTreeForTest(Of TSyntaxNode)(compilation, fileName, which)
+ OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree)
+ End Sub
+
+ Friend Sub VerifyOperationTreeForTest(Of TSyntaxNode As SyntaxNode)(testSrc As String, expectedOperationTree As String, Optional parseOptions As VisualBasicParseOptions = Nothing, Optional which As Integer = 0)
+ Dim actualOperationTree = GetOperationTreeForTest(Of TSyntaxNode)(testSrc, parseOptions, which)
+ OperationTreeVerifier.Verify(expectedOperationTree, actualOperationTree)
+ End Sub
End Class
diff --git a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
index 0ff31b101c10c..4e2c3feffe17a 100644
--- a/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
+++ b/src/Compilers/VisualBasic/Portable/CommandLine/VisualBasicCommandLineParser.vb
@@ -807,26 +807,9 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
If String.IsNullOrEmpty(value) Then
AddDiagnostic(diagnostics, ERRID.ERR_ArgumentRequired, "langversion", ":")
Else
- Select Case value.ToLowerInvariant()
- Case "9", "9.0"
- languageVersion = LanguageVersion.VisualBasic9
- Case "10", "10.0"
- languageVersion = LanguageVersion.VisualBasic10
- Case "11", "11.0"
- languageVersion = LanguageVersion.VisualBasic11
- Case "12", "12.0"
- languageVersion = LanguageVersion.VisualBasic12
- Case "14", "14.0"
- languageVersion = LanguageVersion.VisualBasic14
- Case "15", "15.0"
- languageVersion = LanguageVersion.VisualBasic15
- Case "default"
- languageVersion = LanguageVersion.Default
- Case "latest"
- languageVersion = LanguageVersion.Latest
- Case Else
- AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "langversion", value)
- End Select
+ If Not value.TryParse(languageVersion) Then
+ AddDiagnostic(diagnostics, ERRID.ERR_InvalidSwitchValue, "langversion", value)
+ End If
End If
Continue For
@@ -1307,12 +1290,10 @@ lVbRuntimePlus:
Dim parseOptions = New VisualBasicParseOptions(
languageVersion:=languageVersion,
documentationMode:=If(parseDocumentationComments, DocumentationMode.Diagnose, DocumentationMode.None),
- kind:=SourceCodeKind.Regular,
+ kind:=If(IsScriptRunner, SourceCodeKind.Script, SourceCodeKind.Regular),
preprocessorSymbols:=AddPredefinedPreprocessorSymbols(outputKind, defines.AsImmutableOrEmpty()),
features:=parsedFeatures)
- Dim scriptParseOptions = parseOptions.WithKind(SourceCodeKind.Script)
-
' We want to report diagnostics with source suppression in the error log file.
' However, these diagnostics won't be reported on the command line.
Dim reportSuppressedDiagnostics = errorLogPath IsNot Nothing
@@ -1355,7 +1336,7 @@ lVbRuntimePlus:
runtimeMetadataVersion:=Nothing,
instrumentationKinds:=instrumentationKinds.ToImmutableAndFree())
- ' add option incompatibility errors if any
+ ' add option incompatibility errors if any (parse options will be included in options.Errors)
diagnostics.AddRange(options.Errors)
If documentationPath Is GenerateFileNameForDocComment Then
@@ -1398,7 +1379,7 @@ lVbRuntimePlus:
.DisplayVersion = displayVersion,
.ManifestResources = managedResources.AsImmutable(),
.CompilationOptions = options,
- .ParseOptions = If(IsScriptRunner, scriptParseOptions, parseOptions),
+ .ParseOptions = parseOptions,
.EmitOptions = emitOptions,
.ScriptArguments = scriptArgs.AsImmutableOrEmpty(),
.TouchedFilesPath = touchedFilesPath,
@@ -1674,7 +1655,7 @@ lVbRuntimePlus:
'''
''' Invalid value provided.
Private Shared Function PublicSymbolsToInternalDefines(symbols As IEnumerable(Of KeyValuePair(Of String, Object)),
- parameterName As String) As ImmutableDictionary(Of String, InternalSyntax.CConst)
+ diagnosticBuilder As ArrayBuilder(Of Diagnostic)) As ImmutableDictionary(Of String, InternalSyntax.CConst)
Dim result = ImmutableDictionary.CreateBuilder(Of String, InternalSyntax.CConst)(CaseInsensitiveComparison.Comparer)
@@ -1683,7 +1664,7 @@ lVbRuntimePlus:
Dim constant = InternalSyntax.CConst.TryCreate(symbol.Value)
If constant Is Nothing Then
- Throw New ArgumentException(String.Format(ErrorFactory.IdToString(ERRID.IDS_InvalidPreprocessorConstantType, Culture), symbol.Key, symbol.Value.GetType()), parameterName)
+ diagnosticBuilder.Add(Diagnostic.Create(VisualBasic.MessageProvider.Instance, ERRID.ERR_InvalidPreprocessorConstantType, symbol.Key, symbol.Value.GetType()))
End If
result(symbol.Key) = constant
@@ -1727,7 +1708,7 @@ lVbRuntimePlus:
Dim diagnosticBuilder = ArrayBuilder(Of Diagnostic).GetInstance()
Dim parsedTokensAsString As New StringBuilder
- Dim defines As ImmutableDictionary(Of String, InternalSyntax.CConst) = PublicSymbolsToInternalDefines(symbols, "symbols")
+ Dim defines As ImmutableDictionary(Of String, InternalSyntax.CConst) = PublicSymbolsToInternalDefines(symbols, diagnosticBuilder)
' remove quotes around the whole /define argument (incl. nested)
Dim unquotedString As String
@@ -1769,7 +1750,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedEOS),
parsedTokensAsString.ToString),
Location.None))
@@ -1793,7 +1774,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedIdentifier),
parsedTokensAsString.ToString),
Location.None))
@@ -1822,7 +1803,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedIdentifier),
parsedTokensAsString.ToString),
Location.None))
@@ -1839,7 +1820,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedIdentifier),
parsedTokensAsString.ToString),
Location.None))
@@ -1894,7 +1875,7 @@ lVbRuntimePlus:
Dim errorSkipped As Boolean = False
For Each diag In expression.VbGreen.GetSyntaxErrors
If diag.Code <> ERRID.ERR_ExpectedExpression AndAlso diag.Code <> ERRID.ERR_BadCCExpression Then
- diagnosticBuilder.Add(New DiagnosticWithInfo(ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1, diag, parsedTokensAsString.ToString), Location.None))
+ diagnosticBuilder.Add(New DiagnosticWithInfo(ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid, diag, parsedTokensAsString.ToString), Location.None))
Else
errorSkipped = True
End If
@@ -1903,7 +1884,7 @@ lVbRuntimePlus:
If errorSkipped Then
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(If(atTheEndOrSeparator, ERRID.ERR_ExpectedExpression, ERRID.ERR_BadCCExpression)),
parsedTokensAsString.ToString),
Location.None))
@@ -1924,7 +1905,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(err, value.ErrorArgs),
parsedTokensAsString.ToString),
Location.None))
@@ -1952,7 +1933,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_IllegalChar),
parsedTokensAsString.ToString),
Location.None))
@@ -1962,7 +1943,7 @@ lVbRuntimePlus:
diagnosticBuilder.Add(
New DiagnosticWithInfo(
- ErrorFactory.ErrorInfo(ERRID.ERR_ProjectCCError1,
+ ErrorFactory.ErrorInfo(ERRID.ERR_ConditionalCompilationConstantNotValid,
ErrorFactory.ErrorInfo(ERRID.ERR_ExpectedEOS),
parsedTokensAsString.ToString),
Location.None))
diff --git a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
index 499cd9b6671f3..40154db79f08f 100644
--- a/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
+++ b/src/Compilers/VisualBasic/Portable/Compilation/VisualBasicCompilation.vb
@@ -1929,6 +1929,21 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
builder.AddRange(tree.GetDiagnostics(cancellationToken))
Next
End If
+
+ Dim parseOptionsReported = New HashSet(Of ParseOptions)
+ If Options.ParseOptions IsNot Nothing Then
+ parseOptionsReported.Add(Options.ParseOptions) ' This is reported in Options.Errors at CompilationStage.Declare
+ End If
+
+ For Each tree In SyntaxTrees
+ cancellationToken.ThrowIfCancellationRequested()
+ If Not tree.Options.Errors.IsDefaultOrEmpty AndAlso parseOptionsReported.Add(tree.Options) Then
+ Dim location = tree.GetLocation(TextSpan.FromBounds(0, 0))
+ For Each err In tree.Options.Errors
+ builder.Add(err.WithLocation(location))
+ Next
+ End If
+ Next
End If
' Add declaration errors
diff --git a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
index 1d21dcb6380ec..ac5800186dd39 100644
--- a/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
+++ b/src/Compilers/VisualBasic/Portable/Errors/Errors.vb
@@ -753,7 +753,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
'ERR_UnableToCreateMetaDataAPI = 31024
'ERR_UnableToOpenFile1 = 31027
ERR_EventHandlerSignatureIncompatible2 = 31029
- ERR_ProjectCCError1 = 31030
+ ERR_ConditionalCompilationConstantNotValid = 31030
'ERR_ProjectCCError0 = 31031
ERR_InterfaceImplementedTwice1 = 31033
ERR_InterfaceNotImplemented1 = 31035
@@ -1726,6 +1726,11 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
ERR_Merge_conflict_marker_encountered = 37284
+ ERR_BadSourceCodeKind = 37285
+ ERR_BadDocumentationMode = 37286
+ ERR_BadLanguageVersion = 37287
+ ERR_InvalidPreprocessorConstantType = 37288
+
'// WARNINGS BEGIN HERE
WRN_UseOfObsoleteSymbol2 = 40000
WRN_InvalidOverrideDueToTupleNames2 = 40001
@@ -1968,7 +1973,7 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
IDS_LogoLine1 = 56007
IDS_LogoLine2 = 56008
IDS_VBCHelp = 56009
- IDS_InvalidPreprocessorConstantType = 56010
+ ' available: 56010
IDS_ToolName = 56011
' Feature codes
diff --git a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
index 8a69e2e5de128..5b8af88023e6c 100644
--- a/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
+++ b/src/Compilers/VisualBasic/Portable/Errors/MessageProvider.vb
@@ -232,6 +232,20 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ ' parse options:
+
+ Public Overrides ReadOnly Property ERR_BadSourceCodeKind As Integer
+ Get
+ Return ERRID.ERR_BadSourceCodeKind
+ End Get
+ End Property
+
+ Public Overrides ReadOnly Property ERR_BadDocumentationMode As Integer
+ Get
+ Return ERRID.ERR_BadDocumentationMode
+ End Get
+ End Property
+
' compilation options:
Public Overrides ReadOnly Property ERR_BadCompilationOptionValue As Integer
diff --git a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb
index 34d1e1b7c3ed1..8fcfc4f1848e7 100644
--- a/src/Compilers/VisualBasic/Portable/LanguageVersion.vb
+++ b/src/Compilers/VisualBasic/Portable/LanguageVersion.vb
@@ -56,9 +56,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Select
End Function
+ End Module
+
+ Public Module LanguageVersionFacts
+ '''
+ ''' Map a language version (such as Default, Latest, Or VisualBasicN) to a specific version (VisualBasicN).
+ '''
- Friend Function MapSpecifiedToEffectiveVersion(version As LanguageVersion) As LanguageVersion
+ Public Function MapSpecifiedToEffectiveVersion(version As LanguageVersion) As LanguageVersion
Select Case version
Case LanguageVersion.Latest, LanguageVersion.Default
Return LanguageVersion.VisualBasic15
@@ -67,5 +73,81 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Select
End Function
+ '''
+ ''' Displays the version number in the format understood on the command-line (/langver flag).
+ ''' For instance, "9", "15", "latest".
+ '''
+
+ Public Function ToDisplayString(version As LanguageVersion) As String
+ Select Case version
+ Case LanguageVersion.VisualBasic9
+ Return "9"
+ Case LanguageVersion.VisualBasic10
+ Return "10"
+ Case LanguageVersion.VisualBasic11
+ Return "11"
+ Case LanguageVersion.VisualBasic12
+ Return "12"
+ Case LanguageVersion.VisualBasic14
+ Return "14"
+ Case LanguageVersion.VisualBasic15
+ Return "15"
+ Case LanguageVersion.Default
+ Return "default"
+ Case LanguageVersion.Latest
+ Return "latest"
+ Case Else
+ Throw ExceptionUtilities.UnexpectedValue(version)
+ End Select
+ End Function
+
+ '''
+ ''' Parse a LanguageVersion from a string input, as the command-line compiler does.
+ '''
+
+ Public Function TryParse(version As String, ByRef result As LanguageVersion) As Boolean
+ If version Is Nothing Then
+ result = LanguageVersion.Default
+ Return False
+ End If
+
+ Select Case version.ToLowerInvariant()
+ Case "9", "9.0"
+ result = LanguageVersion.VisualBasic9
+ Case "10", "10.0"
+ result = LanguageVersion.VisualBasic10
+ Case "11", "11.0"
+ result = LanguageVersion.VisualBasic11
+ Case "12", "12.0"
+ result = LanguageVersion.VisualBasic12
+ Case "14", "14.0"
+ result = LanguageVersion.VisualBasic14
+ Case "15", "15.0"
+ result = LanguageVersion.VisualBasic15
+ Case "default"
+ result = LanguageVersion.Default
+ Case "latest"
+ result = LanguageVersion.Latest
+ Case Else
+ result = LanguageVersion.Default
+ Return False
+ End Select
+ Return True
+ End Function
+
End Module
+
+ Friend Class VisualBasicRequiredLanguageVersion
+ Inherits RequiredLanguageVersion
+
+ Friend ReadOnly Property Version As LanguageVersion
+
+ Friend Sub New(version As LanguageVersion)
+ Me.Version = version
+ End Sub
+
+ Public Overrides Function ToString() As String
+ Return Version.ToDisplayString()
+ End Function
+ End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb
index 16f8c1dfdcd55..64f17ec899001 100644
--- a/src/Compilers/VisualBasic/Portable/Parser/Parser.vb
+++ b/src/Compilers/VisualBasic/Portable/Parser/Parser.vb
@@ -6171,7 +6171,8 @@ checkNullable:
If feature = Feature.InterpolatedStrings Then
' Bug: It is too late in the release cycle to update localized strings. As a short term measure we will output
' an unlocalized string and fix this to be localized in the next release.
- Return ReportSyntaxError(node, ERRID.ERR_LanguageVersion, languageVersion.GetErrorName(), "interpolated strings")
+ Dim requiredVersion = New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion())
+ Return ReportSyntaxError(node, ERRID.ERR_LanguageVersion, languageVersion.GetErrorName(), "interpolated strings", requiredVersion)
Else
Return ReportFeatureUnavailable(feature, node, languageVersion)
End If
@@ -6179,7 +6180,8 @@ checkNullable:
Private Shared Function ReportFeatureUnavailable(Of TNode As VisualBasicSyntaxNode)(feature As Feature, node As TNode, languageVersion As LanguageVersion) As TNode
Dim featureName = ErrorFactory.ErrorInfo(feature.GetResourceId())
- Return ReportSyntaxError(node, ERRID.ERR_LanguageVersion, languageVersion.GetErrorName(), featureName)
+ Dim requiredVersion = New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion())
+ Return ReportSyntaxError(node, ERRID.ERR_LanguageVersion, languageVersion.GetErrorName(), featureName, requiredVersion)
End Function
Friend Function ReportFeatureUnavailable(Of TNode As VisualBasicSyntaxNode)(feature As Feature, node As TNode) As TNode
@@ -6201,7 +6203,8 @@ checkNullable:
Friend Shared Function CheckFeatureAvailability(diagnostics As DiagnosticBag, location As Location, languageVersion As LanguageVersion, feature As Feature) As Boolean
If Not CheckFeatureAvailability(languageVersion, feature) Then
Dim featureName = ErrorFactory.ErrorInfo(feature.GetResourceId())
- diagnostics.Add(ERRID.ERR_LanguageVersion, location, languageVersion.GetErrorName(), featureName)
+ Dim requiredVersion = New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion())
+ diagnostics.Add(ERRID.ERR_LanguageVersion, location, languageVersion.GetErrorName(), featureName, requiredVersion)
Return False
End If
Return True
diff --git a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt
index 9a65b044b9274..bbcc5881382a8 100644
--- a/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt
+++ b/src/Compilers/VisualBasic/Portable/PublicAPI.Unshipped.txt
@@ -6,6 +6,10 @@
Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.Default = 0 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion
Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.Latest = 2147483647 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion
Microsoft.CodeAnalysis.VisualBasic.LanguageVersion.VisualBasic15 = 15 -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion
+Microsoft.CodeAnalysis.VisualBasic.LanguageVersionFacts
+Microsoft.CodeAnalysis.VisualBasic.LanguageVersionFacts.MapSpecifiedToEffectiveVersion(version As Microsoft.CodeAnalysis.VisualBasic.LanguageVersion) -> Microsoft.CodeAnalysis.VisualBasic.LanguageVersion
+Microsoft.CodeAnalysis.VisualBasic.LanguageVersionFacts.ToDisplayString(version As Microsoft.CodeAnalysis.VisualBasic.LanguageVersion) -> String
+Microsoft.CodeAnalysis.VisualBasic.LanguageVersionFacts.TryParse(version As String, ByRef result As Microsoft.CodeAnalysis.VisualBasic.LanguageVersion) -> Boolean
Microsoft.CodeAnalysis.VisualBasic.Syntax.NamedTupleElementSyntax
Microsoft.CodeAnalysis.VisualBasic.Syntax.NamedTupleElementSyntax.AsClause() -> Microsoft.CodeAnalysis.VisualBasic.Syntax.SimpleAsClauseSyntax
Microsoft.CodeAnalysis.VisualBasic.Syntax.NamedTupleElementSyntax.Identifier() -> Microsoft.CodeAnalysis.SyntaxToken
diff --git a/src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb b/src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb
index a12c45769da2f..3b9243bd23337 100644
--- a/src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb
+++ b/src/Compilers/VisualBasic/Portable/Scanner/Scanner.vb
@@ -2650,7 +2650,11 @@ baddate:
If CheckFeatureAvailability(feature) Then
Return token
End If
- Dim errorInfo = ErrorFactory.ErrorInfo(ERRID.ERR_LanguageVersion, _options.LanguageVersion.GetErrorName(), ErrorFactory.ErrorInfo(feature.GetResourceId()))
+ Dim requiredVersion = New VisualBasicRequiredLanguageVersion(feature.GetLanguageVersion())
+ Dim errorInfo = ErrorFactory.ErrorInfo(ERRID.ERR_LanguageVersion,
+ _options.LanguageVersion.GetErrorName(),
+ ErrorFactory.ErrorInfo(feature.GetResourceId()),
+ requiredVersion)
Return DirectCast(token.AddError(errorInfo), SyntaxToken)
End Function
diff --git a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
index d0a6f6a7876b2..11ad746856e2e 100644
--- a/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
+++ b/src/Compilers/VisualBasic/Portable/VBResources.Designer.vb
@@ -1035,6 +1035,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Provided documentation mode is unsupported or invalid: '{0}'..
+ '''
+ Friend ReadOnly Property ERR_BadDocumentationMode() As String
+ Get
+ Return ResourceManager.GetString("ERR_BadDocumentationMode", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Enum '{0}' must contain at least one member..
'''
@@ -1278,6 +1287,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Provided language version is unsupported or invalid: '{0}'..
+ '''
+ Friend ReadOnly Property ERR_BadLanguageVersion() As String
+ Get
+ Return ResourceManager.GetString("ERR_BadLanguageVersion", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to '{0}' is not valid on a local constant declaration..
'''
@@ -1485,6 +1503,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Provided source code kind is unsupported or invalid: '{0}'.
+ '''
+ Friend ReadOnly Property ERR_BadSourceCodeKind() As String
+ Get
+ Return ResourceManager.GetString("ERR_BadSourceCodeKind", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to '{0}' and '{1}' cannot be combined..
'''
@@ -2341,6 +2368,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Conditional compilation constant '{1}' is not valid: {0}.
+ '''
+ Friend ReadOnly Property ERR_ConditionalCompilationConstantNotValid() As String
+ Get
+ Return ResourceManager.GetString("ERR_ConditionalCompilationConstantNotValid", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Type '{0}' must define operator '{1}' to be used in a '{2}' expression..
'''
@@ -6269,6 +6305,15 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+ '''
+ ''' Looks up a localized string similar to Preprocessor constant '{0}' of type '{1}' is not supported, only primitive types are allowed..
+ '''
+ Friend ReadOnly Property ERR_InvalidPreprocessorConstantType() As String
+ Get
+ Return ResourceManager.GetString("ERR_InvalidPreprocessorConstantType", resourceCulture)
+ End Get
+ End Property
+
'''
''' Looks up a localized string similar to Invalid signature public key specified in AssemblySignatureKeyAttribute..
'''
@@ -9252,15 +9297,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
- '''
- ''' Looks up a localized string similar to Project-level conditional compilation constant '{1}' is not valid: {0}.
- '''
- Friend ReadOnly Property ERR_ProjectCCError1() As String
- Get
- Return ResourceManager.GetString("ERR_ProjectCCError1", resourceCulture)
- End Get
- End Property
-
'''
''' Looks up a localized string similar to Property access must assign to the property or use its value..
'''
@@ -12180,15 +12216,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
- '''
- ''' Looks up a localized string similar to Preprocessor constant '{0}' of type '{1}' is not supported, only primitive types are allowed..
- '''
- Friend ReadOnly Property IDS_InvalidPreprocessorConstantType() As String
- Get
- Return ResourceManager.GetString("IDS_InvalidPreprocessorConstantType", resourceCulture)
- End Get
- End Property
-
'''
''' Looks up a localized string similar to {0} version {1}.
'''
diff --git a/src/Compilers/VisualBasic/Portable/VBResources.resx b/src/Compilers/VisualBasic/Portable/VBResources.resx
index 766722e4338af..ba8f8bb0fd788 100644
--- a/src/Compilers/VisualBasic/Portable/VBResources.resx
+++ b/src/Compilers/VisualBasic/Portable/VBResources.resx
@@ -1857,8 +1857,8 @@
Method '{0}' cannot handle event '{1}' because they do not have a compatible signature.
-
- Project-level conditional compilation constant '{1}' is not valid: {0}
+
+ Conditional compilation constant '{1}' is not valid: {0}
Interface '{0}' can be implemented only once by this type.
@@ -5263,7 +5263,7 @@
'{0}' is not a valid format specifier
-
+
Preprocessor constant '{0}' of type '{1}' is not supported, only primitive types are allowed.
@@ -5467,4 +5467,13 @@
Merge conflict marker encountered
+
+ Provided documentation mode is unsupported or invalid: '{0}'.
+
+
+ Provided language version is unsupported or invalid: '{0}'.
+
+
+ Provided source code kind is unsupported or invalid: '{0}'
+
\ No newline at end of file
diff --git a/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb b/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb
index 3d58fef3cfd39..0d2f70a5e0b80 100644
--- a/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb
+++ b/src/Compilers/VisualBasic/Portable/VisualBasicCompilationOptions.vb
@@ -913,6 +913,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Friend Overrides Sub ValidateOptions(builder As ArrayBuilder(Of Diagnostic))
ValidateOptions(builder, MessageProvider.Instance)
+ If ParseOptions IsNot Nothing Then
+ builder.AddRange(ParseOptions.Errors)
+ End If
+
If Me.EmbedVbCoreRuntime AndAlso Me.OutputKind.IsNetModule() Then
builder.Add(Diagnostic.Create(MessageProvider.Instance, ERRID.ERR_VBCoreNetModuleConflict))
End If
diff --git a/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb b/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb
index 4549f790d7f98..8ab58bc088815 100644
--- a/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb
+++ b/src/Compilers/VisualBasic/Portable/VisualBasicParseOptions.vb
@@ -40,18 +40,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
kind,
If(preprocessorSymbols Is Nothing, DefaultPreprocessorSymbols, ImmutableArray.CreateRange(preprocessorSymbols)),
ImmutableDictionary(Of String, String).Empty)
-
- ' We test the mapped value, _languageVersion, rather than the parameter, languageVersion,
- ' which has not had "Latest" mapped to the latest version yet.
- If Not _languageVersion.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(languageVersion))
- End If
-
- If Not kind.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(kind))
- End If
-
- ValidatePreprocessorSymbols(preprocessorSymbols, NameOf(preprocessorSymbols))
End Sub
Friend Sub New(
@@ -61,66 +49,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
preprocessorSymbols As IEnumerable(Of KeyValuePair(Of String, Object)),
features As ImmutableDictionary(Of String, String))
- MyClass.New(languageVersion,
- documentationMode,
- kind,
- If(preprocessorSymbols Is Nothing, DefaultPreprocessorSymbols, ImmutableArray.CreateRange(preprocessorSymbols)),
- features)
-
- ' We test the mapped value, _languageVersion, rather than the parameter, languageVersion,
- ' which has not had "Latest" mapped to the latest version yet.
- If Not _languageVersion.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(languageVersion))
- End If
-
- If Not kind.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(kind))
- End If
-
- ValidatePreprocessorSymbols(preprocessorSymbols, NameOf(preprocessorSymbols))
-
- If features Is Nothing Then
- Throw New ArgumentException(NameOf(features))
- End If
- End Sub
-
- Private Shared Sub ValidatePreprocessorSymbols(preprocessorSymbols As IEnumerable(Of KeyValuePair(Of String, Object)),
- parameterName As String)
- If preprocessorSymbols Is Nothing Then
- Return
- End If
-
- For Each symbol In preprocessorSymbols
- If Not IsValidIdentifier(symbol.Key) OrElse
- SyntaxFacts.GetKeywordKind(symbol.Key) <> SyntaxKind.None Then
-
- Throw New ArgumentException(parameterName)
- End If
-
- Debug.Assert(SyntaxFactory.ParseTokens(symbol.Key).Select(Function(t) t.Kind).SequenceEqual({SyntaxKind.IdentifierToken, SyntaxKind.EndOfFileToken}))
-
- Dim constant = InternalSyntax.CConst.TryCreate(symbol.Value)
- If constant Is Nothing Then
- Throw New ArgumentException(String.Format(VBResources.IDS_InvalidPreprocessorConstantType, symbol.Key, symbol.Value.GetType()), parameterName)
- End If
- Next
- End Sub
-
- ' Does not perform validation.
- Private Sub New(
- languageVersion As LanguageVersion,
- documentationMode As DocumentationMode,
- kind As SourceCodeKind,
- preprocessorSymbols As ImmutableArray(Of KeyValuePair(Of String, Object)),
- features As ImmutableDictionary(Of String, String))
-
MyBase.New(kind, documentationMode)
- Debug.Assert(Not preprocessorSymbols.IsDefault)
_specifiedLanguageVersion = languageVersion
_languageVersion = languageVersion.MapSpecifiedToEffectiveVersion
- _preprocessorSymbols = preprocessorSymbols
- _features = features
+ _preprocessorSymbols = preprocessorSymbols.ToImmutableArrayOrEmpty
+ _features = If(features, ImmutableDictionary(Of String, String).Empty)
End Sub
Private Sub New(other As VisualBasicParseOptions)
@@ -200,10 +134,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End If
Dim effectiveVersion = version.MapSpecifiedToEffectiveVersion()
- If Not effectiveVersion.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(version))
- End If
-
Return New VisualBasicParseOptions(Me) With {._specifiedLanguageVersion = version, ._languageVersion = effectiveVersion}
End Function
@@ -213,15 +143,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
''' The parser source code kind.
''' A new instance of VisualBasicParseOptions if source code kind is different; otherwise current instance.
Public Shadows Function WithKind(kind As SourceCodeKind) As VisualBasicParseOptions
- If kind = Me.Kind Then
+ If kind = Me.SpecifiedKind Then
Return Me
End If
- If Not kind.IsValid Then
- Throw New ArgumentOutOfRangeException(NameOf(kind))
- End If
-
- Return New VisualBasicParseOptions(Me) With {.Kind = kind}
+ Dim effectiveKind = kind.MapSpecifiedToEffectiveKind
+ Return New VisualBasicParseOptions(Me) With {.SpecifiedKind = kind, .Kind = effectiveKind}
End Function
'''
@@ -234,10 +161,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return Me
End If
- If Not documentationMode.IsValid() Then
- Throw New ArgumentOutOfRangeException(NameOf(documentationMode))
- End If
-
Return New VisualBasicParseOptions(Me) With {.DocumentationMode = documentationMode}
End Function
@@ -273,8 +196,6 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return Me
End If
- ValidatePreprocessorSymbols(symbols, NameOf(symbols))
-
Return New VisualBasicParseOptions(Me) With {._preprocessorSymbols = symbols}
End Function
@@ -306,10 +227,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Public Shadows Function WithFeatures(features As IEnumerable(Of KeyValuePair(Of String, String))) As VisualBasicParseOptions
' there are currently no parse options for experimental features
If features Is Nothing Then
- Throw New ArgumentException(NameOf(features))
+ Return New VisualBasicParseOptions(Me) With {._features = ImmutableDictionary(Of String, String).Empty}
+ Else
+ Return New VisualBasicParseOptions(Me) With {._features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase)}
End If
-
- Return New VisualBasicParseOptions(Me) With {._features = features.ToImmutableDictionary(StringComparer.OrdinalIgnoreCase)}
End Function
Public Overrides ReadOnly Property Features As IReadOnlyDictionary(Of String, String)
@@ -318,6 +239,30 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Get
End Property
+
+ Friend Overrides Sub ValidateOptions(builder As ArrayBuilder(Of Diagnostic))
+ ValidateOptions(builder, MessageProvider.Instance)
+
+ ' Validate LanguageVersion Not SpecifiedLanguageVersion, after Latest/Default has been converted
+ If Not LanguageVersion.IsValid Then
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, ERRID.ERR_BadLanguageVersion, LanguageVersion.ToString))
+ End If
+
+ If Not PreprocessorSymbols.IsDefaultOrEmpty Then
+ For Each symbol In PreprocessorSymbols
+ If Not IsValidIdentifier(symbol.Key) OrElse SyntaxFacts.GetKeywordKind(symbol.Key) <> SyntaxKind.None Then
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, ERRID.ERR_ConditionalCompilationConstantNotValid, VBResources.ERR_ExpectedIdentifier, symbol.Key))
+ Else
+ Debug.Assert(SyntaxFactory.ParseTokens(symbol.Key).Select(Function(t) t.Kind).SequenceEqual({SyntaxKind.IdentifierToken, SyntaxKind.EndOfFileToken}))
+ End If
+
+ If InternalSyntax.CConst.TryCreate(symbol.Value) Is Nothing Then
+ builder.Add(Diagnostic.Create(MessageProvider.Instance, ERRID.ERR_InvalidPreprocessorConstantType, symbol.Key, symbol.Value.GetType))
+ End If
+ Next
+ End If
+ End Sub
+
'''
''' Determines whether the current object is equal to another object of the same type.
'''
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineArgumentsTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineArgumentsTests.vb
index 2ea9b15293616..d1cb760943c31 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineArgumentsTests.vb
+++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineArgumentsTests.vb
@@ -45,26 +45,26 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine.UnitTests
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(0, dict.Count)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", "= ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "= ^^ ^^ "))
Dim previousSymbols As New Dictionary(Of String, Object)() From {{"Foo", 1}, {"Bar", "Foo"}}
text = ",,,=,,,"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors, previousSymbols)
Assert.Equal(2, dict.Count)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", "= ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "= ^^ ^^ "))
text = "OnlyEqualsNoValue1=, Bar=foo"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(0, dict.Count)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Expression expected.", "OnlyEqualsNoValue1= ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Expression expected.", "OnlyEqualsNoValue1= ^^ ^^ "))
text = "Bar=foo, OnlyEqualsNoValue1="
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(1, dict.Count)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Expression expected.", "OnlyEqualsNoValue1= ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Expression expected.", "OnlyEqualsNoValue1= ^^ ^^ "))
text = """""OnlyEqualsNoValue1"""""
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
@@ -81,12 +81,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine.UnitTests
text = "then=bar" ' keyword :)
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", "then ^^ ^^ =bar"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "then ^^ ^^ =bar"))
text = "bar=then" ' keyword :)
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Syntax error in conditional compilation expression.", "bar= ^^ ^^ then"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Syntax error in conditional compilation expression.", "bar= ^^ ^^ then"))
text = "FOO:BAR"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
@@ -107,12 +107,12 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine.UnitTests
text = "FOO=23::,,:::BAR"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", "FOO=23:: ^^ , ^^ ,:::"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "FOO=23:: ^^ , ^^ ,:::"))
text = "FOO=23,:BAR"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
Assert.Equal(1, errors.Count)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", "FOO=23, ^^ : ^^ BAR"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "FOO=23, ^^ : ^^ BAR"))
text = "FOO::BAR,,BAZ"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
@@ -179,38 +179,38 @@ Namespace Microsoft.CodeAnalysis.VisualBasic.CommandLine.UnitTests
text = "A=""A"",B=""B"",T=IF(1>0, A, B)+B+""C"",RRR=1+""3"""
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Conversion from 'String' to 'Double' cannot occur in a constant expression.", "RRR=1+""3"" ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Conversion from 'String' to 'Double' cannot occur in a constant expression.", "RRR=1+""3"" ^^ ^^ "))
text = "A=""A"",B=""B"",T=IF(1>0, A, B)+B+""C"",X=IF(1,,,,,RRR=1"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
errors.Verify(
- Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("')' expected.", "X=IF(1,,,,,RRR=1 ^^ ^^ "),
- Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("'If' operator requires either two or three operands.", "X=IF(1,,,,,RRR=1 ^^ ^^ "),
- Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Expression expected.", "X=IF(1,,,,,RRR=1 ^^ ^^ "))
+ Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("')' expected.", "X=IF(1,,,,,RRR=1 ^^ ^^ "),
+ Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("'If' operator requires either two or three operands.", "X=IF(1,,,,,RRR=1 ^^ ^^ "),
+ Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Expression expected.", "X=IF(1,,,,,RRR=1 ^^ ^^ "))
text = "A=CHR(128)"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("End of statement expected.", "A=CHR ^^ ^^ (128)"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("End of statement expected.", "A=CHR ^^ ^^ (128)"))
text = "A=ASCW(""G"")"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("End of statement expected.", "A=ASCW ^^ ^^ (""G"")"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("End of statement expected.", "A=ASCW ^^ ^^ (""G"")"))
text = "A=1--1,B=1 1"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("End of statement expected.", "B=1 ^^ ^^ 1"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("End of statement expected.", "B=1 ^^ ^^ 1"))
text = "A=1--1,B=1 C=1"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("End of statement expected.", "B=1 ^^ ^^ C=1"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("End of statement expected.", "B=1 ^^ ^^ C=1"))
text = "A=111111111111111111111111"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Overflow.", "A=111111111111111111111111 ^^ ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Overflow.", "A=111111111111111111111111 ^^ ^^ "))
text = "A= 2 + " + vbCrLf + "2"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Syntax error in conditional compilation expression.", "A= 2 + " + vbCrLf + " ^^ ^^ 2"))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Syntax error in conditional compilation expression.", "A= 2 + " + vbCrLf + " ^^ ^^ 2"))
text = "A= 2 + _" + vbCrLf + "2"
dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
@@ -280,7 +280,7 @@ blah
Dim text = "'Blah'"
Dim dict = VisualBasicCommandLineParser.ParseConditionalCompilationSymbols(text, errors)
- errors.Verify(Diagnostic(ERRID.ERR_ProjectCCError1).WithArguments("Identifier expected.", " ^^ 'Blah' ^^ "))
+ errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", " ^^ 'Blah' ^^ "))
End Sub
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
index 63e30a52155f2..ddf22605b7bee 100644
--- a/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
+++ b/src/Compilers/VisualBasic/Test/CommandLine/CommandLineTests.vb
@@ -1606,6 +1606,66 @@ End Module").Path
Private Const s_VBC_VER As Double = PredefinedPreprocessorSymbols.CurrentVersionNumber
+
+ Public Sub LanguageVersionAdded_Canary()
+ ' When a new version is added, this test will break. This list must be checked:
+ ' - 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.VisualBasic15, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic15, LanguageVersion.Default.MapSpecifiedToEffectiveVersion())
+ End Sub
+
+
+ Public Sub LanguageVersion_DisplayString()
+ AssertEx.SetEqual({"default", "9", "10", "11", "12", "14", "15", "latest"},
+ System.Enum.GetValues(GetType(LanguageVersion)).Cast(Of LanguageVersion)().Select(Function(v) v.ToDisplayString()))
+ ' For minor versions, the format should be "x.y", such as "15.1"
+ End Sub
+
+
+ Public Sub LanguageVersion_MapSpecifiedToEffectiveVersion()
+ Assert.Equal(LanguageVersion.VisualBasic9, LanguageVersion.VisualBasic9.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic10, LanguageVersion.VisualBasic10.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic11, LanguageVersion.VisualBasic11.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic12, LanguageVersion.VisualBasic12.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic14, LanguageVersion.VisualBasic14.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic15, LanguageVersion.VisualBasic15.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic15, LanguageVersion.Default.MapSpecifiedToEffectiveVersion())
+ Assert.Equal(LanguageVersion.VisualBasic15, LanguageVersion.Latest.MapSpecifiedToEffectiveVersion())
+
+ ' The canary check Is a reminder that this test needs to be updated when a language version Is added
+ LanguageVersionAdded_Canary()
+ End Sub
+
+
+ Public Sub LanguageVersion_TryParseDisplayString(input As String, success As Boolean, expected As LanguageVersion)
+ Dim version As LanguageVersion
+ Assert.Equal(success, input.TryParse(version))
+ Assert.Equal(expected, version)
+
+ ' The canary check is a reminder that this test needs to be updated when a language version is added
+ LanguageVersionAdded_Canary()
+ End Sub
+
Public Sub TestDefine()
TestDefines({"/D:a=True,b=1", "a.vb"},
@@ -6025,7 +6085,7 @@ Imports System
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"-nologo", "/preferreduilang:en", "/t:libraRY", "/define:_a,", source})
output = New StringWriter()
@@ -6037,31 +6097,31 @@ Imports System
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ a' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ a' is not valid: Identifier expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"-nologo", "/preferreduilang:en", "/t:libraRY", "/define:a,_,b", source})
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"-nologo", "/preferreduilang:en", "/t:libraRY", "/define:_", source})
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"-nologo", "/preferreduilang:en", "/t:libraRY", "/define:_ ", source})
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"-nologo", "/preferreduilang:en", "/t:libraRY", "/define:a,_", source})
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant '_ ^^ ^^ ' is not valid: Identifier expected.", output.ToString().Trim())
CleanupAllGeneratedFiles(source)
End Sub
@@ -6196,13 +6256,13 @@ End Module
Dim output As New StringWriter()
Dim exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant 'I ^^ ^^ ' is not valid: End of statement expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant 'I ^^ ^^ ' is not valid: End of statement expected.", output.ToString().Trim())
vbc = New MockVisualBasicCompiler(Nothing, _baseDirectory, {"/nologo", "/preferreduilang:en", "/define:I*", source})
output = New StringWriter()
exitCode = vbc.Run(output, Nothing)
Assert.Equal(1, exitCode)
- Assert.Equal("vbc : error BC31030: Project-level conditional compilation constant 'I ^^ ^^ ' is not valid: End of statement expected.", output.ToString().Trim())
+ Assert.Equal("vbc : error BC31030: Conditional compilation constant 'I ^^ ^^ ' is not valid: End of statement expected.", output.ToString().Trim())
End Sub
@@ -8118,6 +8178,18 @@ End Module
Assert.Equal($"error BC2012: can't open '{sourceLinkPath}' for writing: Fake IOException{Environment.NewLine}", outWriter.ToString())
End Sub
+
+ Public Sub CompilingCodeWithInvalidPreProcessorSymbolsShouldProvideDiagnostics()
+ Dim parsedArgs = DefaultParse({"/define:1", "a.cs"}, _baseDirectory)
+ parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "1 ^^ ^^ ").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub CompilingCodeWithInvalidLanguageVersionShouldProvideDiagnostics()
+ Dim parsedArgs = DefaultParse({"/langversion:1000", "a.cs"}, _baseDirectory)
+ parsedArgs.Errors.Verify(Diagnostic(ERRID.ERR_InvalidSwitchValue).WithArguments("langversion", "1000").WithLocation(1, 1))
+ End Sub
+
Private Function MakeTrivialExe(Optional directory As String = Nothing) As String
Return Temp.CreateFile(directory:=directory, prefix:="", extension:=".vb").WriteAllText("
Class Program
diff --git a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb
index a94a53ed856d0..e88b9998af2a1 100644
--- a/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/CodeGen/CodeGenTuples.vb
@@ -13587,6 +13587,7 @@ Imports System
Public Class C
Shared Sub Main()
Dim x As (Integer, Integer) = (1, 1)
+ Else
End Sub
End Class
@@ -13602,8 +13603,14 @@ BC36716: Visual Basic 14.0 does not support tuples.
BC36716: Visual Basic 14.0 does not support tuples.
Dim x As (Integer, Integer) = (1, 1)
~~~~~~
+BC30086: 'Else' must be preceded by a matching 'If' or 'ElseIf'.
+ Else
+ ~~~~
)
-
+ Dim x = comp.GetDiagnostics()
+ Assert.Equal("15", Compilation.GetRequiredLanguageVersion(comp.GetDiagnostics()(0)))
+ Assert.Null(Compilation.GetRequiredLanguageVersion(comp.GetDiagnostics()(2)))
+ Assert.Throws(Of ArgumentNullException)(Sub() Compilation.GetRequiredLanguageVersion(Nothing))
End Sub
diff --git a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
index 1da9cb85cdd1e..9798f188c1201 100644
--- a/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
+++ b/src/Compilers/VisualBasic/Test/Emit/PDB/PDBTests.vb
@@ -8,6 +8,7 @@ Imports System.Text
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.Text
Imports Microsoft.CodeAnalysis.VisualBasic.Symbols
+Imports Microsoft.DiaSymReader.Tools
Imports Roslyn.Test.PdbUtilities
Imports Roslyn.Test.Utilities
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/GetDiagnosticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/GetDiagnosticsTests.vb
index 082ddf9a9482f..c768157c0b588 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/GetDiagnosticsTests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Diagnostics/GetDiagnosticsTests.vb
@@ -224,6 +224,189 @@ End Namespace
Assert.True(completedCompilationUnits.Contains(tree.FilePath))
End Sub
+
+ Public Sub CompilingCodeWithInvalidPreProcessorSymbolsShouldProvideDiagnostics()
+ Dim dict = New Dictionary(Of String, Object)
+ dict.Add("1", Nothing)
+ Dim compilation = CreateCompilation(String.Empty, parseOptions:=New VisualBasicParseOptions().WithPreprocessorSymbols(dict))
+
+ CompilationUtils.AssertTheseDiagnostics(compilation,
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+
+~
+)
+ End Sub
+
+
+ Public Sub CompilingCodeWithInvalidSourceCodeKindShouldProvideDiagnostics()
+#Disable Warning BC40000 ' Type or member is obsolete
+ Dim compilation = CreateCompilationWithMscorlib45(String.Empty, parseOptions:=New VisualBasicParseOptions().WithKind(SourceCodeKind.Interactive))
+#Enable Warning BC40000 ' Type or member is obsolete
+
+ CompilationUtils.AssertTheseDiagnostics(compilation,
+BC37285: Provided source code kind is unsupported or invalid: 'Interactive'
+
+~
+)
+ End Sub
+
+
+ Public Sub CompilingCodeWithInvalidLanguageVersionShouldProvideDiagnostics()
+ Dim compilation = CreateCompilation(String.Empty, parseOptions:=New VisualBasicParseOptions().WithLanguageVersion(DirectCast(10000, LanguageVersion)))
+
+ CompilationUtils.AssertTheseDiagnostics(compilation,
+BC37287: Provided language version is unsupported or invalid: '10000'.
+
+~
+)
+ End Sub
+
+
+ Public Sub CompilingCodeWithInvalidDocumentationModeShouldProvideDiagnostics()
+ Dim compilation = CreateCompilation(String.Empty, parseOptions:=New VisualBasicParseOptions().WithDocumentationMode(CType(100, DocumentationMode)))
+
+ CompilationUtils.AssertTheseDiagnostics(compilation,
+BC37286: Provided documentation mode is unsupported or invalid: '100'.
+
+~
+)
+ End Sub
+
+
+ Public Sub CompilingCodeWithInvalidParseOptionsInMultipleSyntaxTreesShouldReportThemAll()
+ Dim dict1 = New Dictionary(Of String, Object)
+ dict1.Add("1", Nothing)
+ Dim dict2 = New Dictionary(Of String, Object)
+ dict2.Add("2", Nothing)
+ Dim dict3 = New Dictionary(Of String, Object)
+ dict3.Add("3", Nothing)
+
+ Dim syntaxTree1 = Parse(String.Empty, options:=New VisualBasicParseOptions().WithPreprocessorSymbols(dict1))
+ Dim syntaxTree2 = Parse(String.Empty, options:=New VisualBasicParseOptions().WithPreprocessorSymbols(dict2))
+ Dim syntaxTree3 = Parse(String.Empty, options:=New VisualBasicParseOptions().WithPreprocessorSymbols(dict3))
+
+ Dim options = New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
+ Dim compilation = CreateCompilationWithMscorlib({syntaxTree1, syntaxTree2, syntaxTree3}, options:=options)
+ Dim diagnostics = compilation.GetDiagnostics()
+
+ CompilationUtils.AssertTheseDiagnostics(diagnostics,
+
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+
+~
+BC31030: Conditional compilation constant '2' is not valid: Identifier expected.
+
+~
+BC31030: Conditional compilation constant '3' is not valid: Identifier expected.
+
+~
+)
+
+ Assert.True(diagnostics(0).Location.SourceTree.Equals(syntaxTree1))
+ Assert.True(diagnostics(1).Location.SourceTree.Equals(syntaxTree2))
+ Assert.True(diagnostics(2).Location.SourceTree.Equals(syntaxTree3))
+ End Sub
+
+
+ Public Sub CompilingCodeWithSameParseOptionsInMultipleSyntaxTreesShouldReportOnlyNonDuplicates()
+ Dim dict1 = New Dictionary(Of String, Object)
+ dict1.Add("1", Nothing)
+ Dim dict2 = New Dictionary(Of String, Object)
+ dict2.Add("2", Nothing)
+
+ Dim parseOptions1 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict1)
+ Dim parseOptions2 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict2)
+
+ Dim syntaxTree1 = Parse(String.Empty, options:=parseOptions1)
+ Dim syntaxTree2 = Parse(String.Empty, options:=parseOptions2)
+ Dim syntaxTree3 = Parse(String.Empty, options:=parseOptions2)
+
+ Dim options = New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary)
+ Dim compilation = CreateCompilationWithMscorlib({syntaxTree1, syntaxTree2, syntaxTree3}, options:=options)
+ Dim diagnostics = compilation.GetDiagnostics()
+
+ CompilationUtils.AssertTheseDiagnostics(diagnostics,
+
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+
+~
+BC31030: Conditional compilation constant '2' is not valid: Identifier expected.
+
+~
+)
+
+ Assert.True(diagnostics(0).Location.SourceTree.Equals(syntaxTree1))
+ Assert.True(diagnostics(1).Location.SourceTree.Equals(syntaxTree2))
+ End Sub
+
+
+ Public Sub DiagnositcsInCompilationOptionsParseOptionsAreDedupedWithParseTreesParseOptions()
+ Dim dict1 = New Dictionary(Of String, Object)
+ dict1.Add("1", Nothing)
+ Dim dict2 = New Dictionary(Of String, Object)
+ dict2.Add("2", Nothing)
+
+ Dim parseOptions1 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict1)
+ Dim parseOptions2 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict2)
+
+ Dim syntaxTree1 = Parse(String.Empty, options:=parseOptions1)
+ Dim syntaxTree2 = Parse(String.Empty, options:=parseOptions2)
+
+ Dim options = New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary, parseOptions:=parseOptions1)
+ Dim compilation = CreateCompilationWithMscorlibAndVBRuntime({syntaxTree1, syntaxTree2}, options:=options)
+ Dim diagnostics = compilation.GetDiagnostics()
+
+ CompilationUtils.AssertTheseDiagnostics(diagnostics,
+
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+BC31030: Conditional compilation constant '2' is not valid: Identifier expected.
+
+~
+)
+
+ Assert.Equal(diagnostics(0).Arguments, {"Identifier expected.", "2"})
+ Assert.True(diagnostics(0).Location.SourceTree.Equals(syntaxTree2)) ' Syntax tree parse options are reported in CompilationStage.Parse
+
+ Assert.Equal(diagnostics(1).Arguments, {"Identifier expected.", "1"})
+ Assert.Null(diagnostics(1).Location.SourceTree) ' Compilation parse options are reported in CompilationStage.Declare
+ End Sub
+
+
+ Public Sub DiagnositcsInCompilationOptionsParseOptionsAreReportedSeparately()
+ Dim dict1 = New Dictionary(Of String, Object)
+ dict1.Add("1", Nothing)
+ Dim dict2 = New Dictionary(Of String, Object)
+ dict2.Add("2", Nothing)
+
+ Dim parseOptions1 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict1)
+ Dim parseOptions2 = New VisualBasicParseOptions().WithPreprocessorSymbols(dict2)
+
+ Dim options = New VisualBasicCompilationOptions(OutputKind.DynamicallyLinkedLibrary, parseOptions:=parseOptions1)
+
+ CompilationUtils.AssertTheseDiagnostics(options.Errors,
+
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+)
+
+ Dim syntaxTree = Parse(String.Empty, options:=parseOptions2)
+ Dim compilation = CreateCompilationWithMscorlibAndVBRuntime({syntaxTree}, options:=options)
+ Dim diagnostics = compilation.GetDiagnostics()
+
+ CompilationUtils.AssertTheseDiagnostics(diagnostics,
+
+BC31030: Conditional compilation constant '1' is not valid: Identifier expected.
+BC31030: Conditional compilation constant '2' is not valid: Identifier expected.
+
+~
+)
+
+ Assert.Equal(diagnostics(0).Arguments, {"Identifier expected.", "2"})
+ Assert.True(diagnostics(0).Location.SourceTree.Equals(syntaxTree)) ' Syntax tree parse options are reported in CompilationStage.Parse
+
+ Assert.Equal(diagnostics(1).Arguments, {"Identifier expected.", "1"})
+ Assert.Null(diagnostics(1).Location.SourceTree) ' Compilation parse options are reported in CompilationStage.Declare
+ End Sub
+
Private Shared Function DequeueCompilationEvents(eventQueue As AsyncQueue(Of CompilationEvent), ByRef compilationStartedFired As Boolean, ByRef declaredSymbolNames As HashSet(Of String), ByRef completedCompilationUnits As HashSet(Of String)) As Boolean
compilationStartedFired = False
declaredSymbolNames = New HashSet(Of String)()
diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb
index 13ba1cd65eff8..4a136b584d8ad 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb
@@ -8,7 +8,7 @@ Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
- Inherits BasicTestBase
+ Inherits SemanticModelTestBase
Public Sub InvalidUserDefinedOperators()
diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb
index e4f2330030e18..808597b00435b 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests_ISymbolInitializer.vb
@@ -8,7 +8,7 @@ Imports Roslyn.Test.Utilities
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
- Inherits BasicTestBase
+ Inherits SemanticModelTestBase
Public Sub NoInitializers()
diff --git a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb
index b671645b96aa7..dc2eb37ff93d7 100644
--- a/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb
+++ b/src/Compilers/VisualBasic/Test/Semantic/Semantics/ScriptSemanticsTests.vb
@@ -172,14 +172,6 @@ System.Console.WriteLine(1)
Return node5
End Function
-
-
- Public Sub NoNeedToTestSourceCodeKindInteractive()
-#Disable Warning BC40000
- Assert.Throws(Of ArgumentOutOfRangeException)(Function() New VisualBasicParseOptions(kind:=SourceCodeKind.Interactive))
-#Enable Warning BC40000
- End Sub
-
End Class
End Namespace
diff --git a/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseLanguageVersionTests.vb b/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseLanguageVersionTests.vb
index 5be70a5393bf5..194c43b2084b9 100644
--- a/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseLanguageVersionTests.vb
+++ b/src/Compilers/VisualBasic/Test/Syntax/Parser/ParseLanguageVersionTests.vb
@@ -23,8 +23,8 @@ Class C1
End Class
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas").WithLocation(3, 5),
- Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas").WithLocation(7, 5))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas", "11").WithLocation(3, 5),
+ Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas", "11").WithLocation(7, 5))
End Sub
<[Fact]>
@@ -40,10 +40,10 @@ Module M1
End Module
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "Iterator").WithArguments("9.0", "iterators").WithLocation(3, 13),
- Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators").WithLocation(4, 9),
- Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators").WithLocation(5, 9),
- Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators").WithLocation(6, 9))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Iterator").WithArguments("9.0", "iterators", "11").WithLocation(3, 13),
+ Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators", "11").WithLocation(4, 9),
+ Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators", "11").WithLocation(5, 9),
+ Diagnostic(ERRID.ERR_LanguageVersion, "Yield").WithArguments("9.0", "iterators", "11").WithLocation(6, 9))
End Sub
<[Fact]>
@@ -57,7 +57,7 @@ Module M1
End Module
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "From").WithArguments("9.0", "collection initializers").WithLocation(4, 51))
+ Diagnostic(ERRID.ERR_LanguageVersion, "From").WithArguments("9.0", "collection initializers", "10").WithLocation(4, 51))
End Sub
<[Fact]>
@@ -71,8 +71,8 @@ Interface IVariant(Of Out R, In A)
End Interface
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "Out").WithArguments("9.0", "variance").WithLocation(2, 23),
- Diagnostic(ERRID.ERR_LanguageVersion, "In").WithArguments("9.0", "variance").WithLocation(2, 30))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Out").WithArguments("9.0", "variance", "10").WithLocation(2, 23),
+ Diagnostic(ERRID.ERR_LanguageVersion, "In").WithArguments("9.0", "variance", "10").WithLocation(2, 30))
End Sub
<[Fact]>
@@ -95,7 +95,7 @@ Module M1
End Module
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas").WithLocation(3, 13))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Async").WithArguments("9.0", "async methods or lambdas", "11").WithLocation(3, 13))
End Sub
<[Fact]>
@@ -137,8 +137,8 @@ Class C1
End Class
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "Public Property Name As String").WithArguments("9.0", "auto-implemented properties").WithLocation(3, 5),
- Diagnostic(ERRID.ERR_LanguageVersion, "Public Property Owner As String = ""DefaultName""").WithArguments("9.0", "auto-implemented properties").WithLocation(4, 5))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Public Property Name As String").WithArguments("9.0", "auto-implemented properties", "10").WithLocation(3, 5),
+ Diagnostic(ERRID.ERR_LanguageVersion, "Public Property Owner As String = ""DefaultName""").WithArguments("9.0", "auto-implemented properties", "10").WithLocation(4, 5))
End Sub
<[Fact]>
@@ -215,7 +215,7 @@ Class C1
End Class
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "NameOf").WithArguments("9.0", "'nameof' expressions").WithLocation(5, 41))
+ Diagnostic(ERRID.ERR_LanguageVersion, "NameOf").WithArguments("9.0", "'nameof' expressions", "14").WithLocation(5, 41))
End Sub
<[Fact]>
@@ -231,8 +231,8 @@ Class C1
End Class
]]>.Value,
LanguageVersion.VisualBasic9,
- Diagnostic(ERRID.ERR_LanguageVersion, "?").WithArguments("9.0", "null conditional operations").WithLocation(4, 31),
- Diagnostic(ERRID.ERR_LanguageVersion, "?").WithArguments("9.0", "null conditional operations").WithLocation(5, 22))
+ Diagnostic(ERRID.ERR_LanguageVersion, "?").WithArguments("9.0", "null conditional operations", "14").WithLocation(4, 31),
+ Diagnostic(ERRID.ERR_LanguageVersion, "?").WithArguments("9.0", "null conditional operations", "14").WithLocation(5, 22))
End Sub
<[Fact]>
@@ -251,7 +251,7 @@ End Namespace"
For Each version In {LanguageVersion.VisualBasic9, LanguageVersion.VisualBasic10}
ParseAndVerify(source, version,
- Diagnostic(ERRID.ERR_LanguageVersion, "Global").WithArguments($"{CInt(version)}.0", "declaring a Global namespace").WithLocation(4, 11))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Global").WithArguments($"{CInt(version)}.0", "declaring a Global namespace", "11").WithLocation(4, 11))
Next
For Each version In {LanguageVersion.VisualBasic11, LanguageVersion.VisualBasic12, LanguageVersion.VisualBasic14, VisualBasicParseOptions.Default.LanguageVersion}
@@ -292,7 +292,7 @@ End Namespace"
For Each version In {LanguageVersion.VisualBasic9, LanguageVersion.VisualBasic10}
ParseAndVerify(source, version,
- Diagnostic(ERRID.ERR_LanguageVersion, "Global").WithArguments($"{CInt(version)}.0", "declaring a Global namespace").WithLocation(4, 11))
+ Diagnostic(ERRID.ERR_LanguageVersion, "Global").WithArguments($"{CInt(version)}.0", "declaring a Global namespace", "11").WithLocation(4, 11))
Next
For Each version In {LanguageVersion.VisualBasic11, LanguageVersion.VisualBasic12, LanguageVersion.VisualBasic14, LanguageVersion.VisualBasic15,
@@ -315,8 +315,8 @@ Module Module1
End Module
]]>.Value,
LanguageVersion.VisualBasic12,
- Diagnostic(ERRID.ERR_LanguageVersion, "$""world""").WithArguments("12.0", "interpolated strings").WithLocation(4, 18),
- Diagnostic(ERRID.ERR_LanguageVersion, "$""hello {x1}""").WithArguments("12.0", "interpolated strings").WithLocation(5, 18))
+ Diagnostic(ERRID.ERR_LanguageVersion, "$""world""").WithArguments("12.0", "interpolated strings", "14").WithLocation(4, 18),
+ Diagnostic(ERRID.ERR_LanguageVersion, "$""hello {x1}""").WithArguments("12.0", "interpolated strings", "14").WithLocation(5, 18))
End Sub
@@ -334,8 +334,8 @@ Module Module1
End Module
]]>.Value,
LanguageVersion.VisualBasic14,
- Diagnostic(ERRID.ERR_LanguageVersion, "(1, 2)").WithArguments("14.0", "tuples").WithLocation(4, 18),
- Diagnostic(ERRID.ERR_LanguageVersion, "(A:=1, B:=2)").WithArguments("14.0", "tuples").WithLocation(5, 18))
+ Diagnostic(ERRID.ERR_LanguageVersion, "(1, 2)").WithArguments("14.0", "tuples", "15").WithLocation(4, 18),
+ Diagnostic(ERRID.ERR_LanguageVersion, "(A:=1, B:=2)").WithArguments("14.0", "tuples", "15").WithLocation(5, 18))
End Sub
@@ -353,7 +353,7 @@ Module Module1
End Module
]]>.Value,
LanguageVersion.VisualBasic14,
- Diagnostic(ERRID.ERR_LanguageVersion, "(Integer, Integer)").WithArguments("14.0", "tuples").WithLocation(4, 19),
- Diagnostic(ERRID.ERR_LanguageVersion, "(A As Integer, B As Integer)").WithArguments("14.0", "tuples").WithLocation(5, 19))
+ Diagnostic(ERRID.ERR_LanguageVersion, "(Integer, Integer)").WithArguments("14.0", "tuples", "15").WithLocation(4, 19),
+ Diagnostic(ERRID.ERR_LanguageVersion, "(A As Integer, B As Integer)").WithArguments("14.0", "tuples", "15").WithLocation(5, 19))
End Sub
End Class
\ No newline at end of file
diff --git a/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb b/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb
index 2003a22a49467..08e78851026b1 100644
--- a/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb
+++ b/src/Compilers/VisualBasic/Test/Syntax/Parser/VisualBasicParseOptionsTests.vb
@@ -20,9 +20,6 @@ Public Class VisualBasicParseOptionsTests
TestProperty(Function(old, value) old.WithKind(value), Function(opt) opt.Kind, SourceCodeKind.Script)
TestProperty(Function(old, value) old.WithLanguageVersion(value), Function(opt) opt.LanguageVersion, LanguageVersion.VisualBasic9)
TestProperty(Function(old, value) old.WithDocumentationMode(value), Function(opt) opt.DocumentationMode, DocumentationMode.None)
-
- Assert.Throws(Of ArgumentOutOfRangeException)(Function() VisualBasicParseOptions.Default.WithKind(DirectCast(Integer.MaxValue, SourceCodeKind)))
- Assert.Throws(Of ArgumentOutOfRangeException)(Function() VisualBasicParseOptions.Default.WithLanguageVersion(DirectCast(1000, LanguageVersion)))
End Sub
@@ -51,44 +48,6 @@ Public Class VisualBasicParseOptionsTests
Assert.Equal(0, VisualBasicParseOptions.Default.WithPreprocessorSymbols(syms).WithPreprocessorSymbols(CType(Nothing, ImmutableArray(Of KeyValuePair(Of String, Object)))).PreprocessorSymbols.Length)
Assert.Equal(0, VisualBasicParseOptions.Default.WithPreprocessorSymbols(syms).WithPreprocessorSymbols(DirectCast(Nothing, IEnumerable(Of KeyValuePair(Of String, Object)))).PreprocessorSymbols.Length)
Assert.Equal(0, VisualBasicParseOptions.Default.WithPreprocessorSymbols(syms).WithPreprocessorSymbols(DirectCast(Nothing, KeyValuePair(Of String, Object)())).PreprocessorSymbols.Length)
-
- Dim syms2 = {New KeyValuePair(Of String, Object)("A", 1),
- New KeyValuePair(Of String, Object)("B", New List(Of String)()),
- New KeyValuePair(Of String, Object)("C", 3)}
-
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms2))
- Assert.Throws(Of ArgumentException)(Function() VisualBasicParseOptions.Default.WithPreprocessorSymbols(syms2))
- End Sub
-
-
- Public Sub ConstructorValidation()
- Assert.Throws(Of ArgumentOutOfRangeException)(Function() New VisualBasicParseOptions(kind:=DirectCast(Int32.MaxValue, SourceCodeKind)))
- Assert.Throws(Of ArgumentOutOfRangeException)(Function() New VisualBasicParseOptions(languageVersion:=DirectCast(1000, LanguageVersion)))
- End Sub
-
-
- Public Sub InvalidDefineSymbols()
-
- ' Command line: error BC31030: Project-level conditional compilation constant 'xxx' is not valid: Identifier expected
-
- Dim syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)("", 1))
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms))
-
- syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)(" ", 1))
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms))
-
- syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)("Good", 1),
- New KeyValuePair(Of String, Object)(Nothing, 2))
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms))
-
- syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)("Good", 1),
- New KeyValuePair(Of String, Object)("Bad.Symbol", 2))
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms))
-
- syms = ImmutableArray.Create(New KeyValuePair(Of String, Object)("123", 1),
- New KeyValuePair(Of String, Object)("Bad/Symbol", 2),
- New KeyValuePair(Of String, Object)("Good", 3))
- Assert.Throws(Of ArgumentException)(Function() New VisualBasicParseOptions(preprocessorSymbols:=syms))
End Sub
@@ -264,4 +223,166 @@ Public Class VisualBasicParseOptionsTests
"PreprocessorSymbols",
"SpecifiedLanguageVersion")
End Sub
+
+
+ Public Sub SpecifiedKindIsMappedCorrectly()
+ Dim options = New VisualBasicParseOptions()
+ Assert.Equal(SourceCodeKind.Regular, options.Kind)
+ Assert.Equal(SourceCodeKind.Regular, options.SpecifiedKind)
+
+ options.Errors.Verify()
+
+ options = New VisualBasicParseOptions(kind:=SourceCodeKind.Regular)
+ Assert.Equal(SourceCodeKind.Regular, options.Kind)
+ Assert.Equal(SourceCodeKind.Regular, options.SpecifiedKind)
+
+ options.Errors.Verify()
+
+ options = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+ Assert.Equal(SourceCodeKind.Script, options.Kind)
+ Assert.Equal(SourceCodeKind.Script, options.SpecifiedKind)
+
+ options.Errors.Verify()
+
+#Disable Warning BC40000 ' SourceCodeKind.Interactive is obsolete
+ options = New VisualBasicParseOptions(kind:=SourceCodeKind.Interactive)
+ Assert.Equal(SourceCodeKind.Script, options.Kind)
+ Assert.Equal(SourceCodeKind.Interactive, options.SpecifiedKind)
+#Enable Warning BC40000 ' SourceCodeKind.Interactive is obsolete
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1))
+
+ options = New VisualBasicParseOptions(kind:=CType(Int32.MinValue, SourceCodeKind))
+ Assert.Equal(SourceCodeKind.Regular, options.Kind)
+ Assert.Equal(CType(Int32.MinValue, SourceCodeKind), options.SpecifiedKind)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadSourceCodeKind).WithArguments("-2147483648").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub TwoOptionsWithDifferentSpecifiedKindShouldNotHaveTheSameHashCodes()
+ Dim options1 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+ Dim options2 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+
+ Assert.Equal(options1.GetHashCode(), options2.GetHashCode())
+
+ ' They both map internally to SourceCodeKind.Script
+#Disable Warning BC40000 ' SourceCodeKind.Interactive is obsolete
+ options1 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+ options2 = New VisualBasicParseOptions(kind:=SourceCodeKind.Interactive)
+#Enable Warning BC40000 ' SourceCodeKind.Interactive Is obsolete
+
+ Assert.NotEqual(options1.GetHashCode(), options2.GetHashCode())
+ End Sub
+
+
+ Public Sub TwoOptionsWithDifferentSpecifiedKindShouldNotBeEqual()
+ Dim options1 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+ Dim options2 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+
+ Assert.True(options1.Equals(options2))
+
+ ' They both map internally to SourceCodeKind.Script
+#Disable Warning BC40000 ' SourceCodeKind.Interactive is obsolete
+ options1 = New VisualBasicParseOptions(kind:=SourceCodeKind.Script)
+ options2 = New VisualBasicParseOptions(kind:=SourceCodeKind.Interactive)
+#Enable Warning BC40000 ' SourceCodeKind.Interactive Is obsolete
+
+ Assert.False(options1.Equals(options2))
+ End Sub
+
+
+ Public Sub BadSourceCodeKindShouldProduceDiagnostics()
+#Disable Warning BC40000 ' Type Or member Is obsolete
+ Dim options = New VisualBasicParseOptions(kind:=SourceCodeKind.Interactive)
+#Enable Warning BC40000 ' Type Or member Is obsolete
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadDocumentationModeShouldProduceDiagnostics()
+ Dim options = New VisualBasicParseOptions(documentationMode:=CType(100, DocumentationMode))
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadDocumentationMode).WithArguments("100").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadLanguageVersionShouldProduceDiagnostics()
+ Dim options = New VisualBasicParseOptions(languageVersion:=DirectCast(10000, LanguageVersion))
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadLanguageVersion).WithArguments("10000").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadPreProcessorSymbolsShouldProduceDiagnostics()
+ Dim symbols = New Dictionary(Of String, Object)
+ symbols.Add("test", Nothing)
+ symbols.Add("1", Nothing)
+ Dim options = New VisualBasicParseOptions(preprocessorSymbols:=symbols)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "1").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadSourceCodeKindShouldProduceDiagnostics_WithVariation()
+#Disable Warning BC40000 ' Type Or member Is obsolete
+ Dim options = New VisualBasicParseOptions().WithKind(SourceCodeKind.Interactive)
+#Enable Warning BC40000 ' Type Or member Is obsolete
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadSourceCodeKind).WithArguments("Interactive").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadDocumentationModeShouldProduceDiagnostics_WithVariation()
+ Dim options = New VisualBasicParseOptions().WithDocumentationMode(CType(100, DocumentationMode))
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadDocumentationMode).WithArguments("100").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadLanguageVersionShouldProduceDiagnostics_WithVariation()
+ Dim options = New VisualBasicParseOptions().WithLanguageVersion(DirectCast(10000, LanguageVersion))
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_BadLanguageVersion).WithArguments("10000").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadPreProcessorSymbolsShouldProduceDiagnostics_EmptyString()
+ Dim symbols = New Dictionary(Of String, Object)
+ symbols.Add("", Nothing)
+ Dim options = New VisualBasicParseOptions().WithPreprocessorSymbols(symbols)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadPreProcessorSymbolsShouldProduceDiagnostics_WhiteSpacetring()
+ Dim symbols = New Dictionary(Of String, Object)
+ symbols.Add(" ", Nothing)
+ Dim options = New VisualBasicParseOptions().WithPreprocessorSymbols(symbols)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", " ").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadPreProcessorSymbolsShouldProduceDiagnostics_SymbolWithDots()
+ Dim symbols = New Dictionary(Of String, Object)
+ symbols.Add("Good", Nothing)
+ symbols.Add("Bad.Symbol", Nothing)
+ Dim options = New VisualBasicParseOptions().WithPreprocessorSymbols(symbols)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "Bad.Symbol").WithLocation(1, 1))
+ End Sub
+
+
+ Public Sub BadPreProcessorSymbolsShouldProduceDiagnostics_SymbolWithSlashes()
+ Dim symbols = New Dictionary(Of String, Object)
+ symbols.Add("Good", Nothing)
+ symbols.Add("Bad\\Symbol", Nothing)
+ Dim options = New VisualBasicParseOptions().WithPreprocessorSymbols(symbols)
+
+ options.Errors.Verify(Diagnostic(ERRID.ERR_ConditionalCompilationConstantNotValid).WithArguments("Identifier expected.", "Bad\\Symbol").WithLocation(1, 1))
+ End Sub
+
End Class
diff --git a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
index 3813a1af181ec..9e0ad1df1f55b 100644
--- a/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
+++ b/src/EditorFeatures/CSharpTest/CSharpEditorServicesTest.csproj
@@ -204,6 +204,7 @@
+
diff --git a/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
new file mode 100644
index 0000000000000..ce971a1e8b182
--- /dev/null
+++ b/src/EditorFeatures/CSharpTest/Diagnostics/UpgradeProject/UpgradeProjectTests.cs
@@ -0,0 +1,249 @@
+// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
+
+using System.Linq;
+using System.Threading.Tasks;
+using Microsoft.CodeAnalysis.CodeFixes;
+using Microsoft.CodeAnalysis.CSharp;
+using Microsoft.CodeAnalysis.CSharp.UpgradeProject;
+using Microsoft.CodeAnalysis.Diagnostics;
+using Roslyn.Test.Utilities;
+using Xunit;
+
+namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.Async
+{
+ public partial class UpgradeProjectTests : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest
+ {
+ internal override (DiagnosticAnalyzer, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace)
+ => (null, new CSharpUpgradeProjectCodeFixProvider());
+
+ private async Task TestLanguageVersionUpgradedAsync(
+ string initialMarkup,
+ LanguageVersion expected,
+ ParseOptions parseOptions,
+ int index = 0)
+ {
+ var parameters = new TestParameters(parseOptions: parseOptions);
+ using (var workspace = CreateWorkspaceFromOptions(initialMarkup, parameters))
+ {
+ var actions = await GetCodeActionsAsync(workspace, parameters);
+ var operations = await VerifyInputsAndGetOperationsAsync(index, actions, priority: null);
+
+ var appliedChanges = ApplyOperationsAndGetSolution(workspace, operations);
+ var oldSolution = appliedChanges.Item1;
+ var newSolution = appliedChanges.Item2;
+ Assert.True(newSolution.Projects.Where(p => p.Language == LanguageNames.CSharp)
+ .All(p => ((CSharpParseOptions)p.ParseOptions).SpecifiedLanguageVersion == expected));
+ }
+
+ await TestAsync(initialMarkup, initialMarkup, parseOptions); // no change to markup
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task UpgradeProjectToDefault()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"
+class Program
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}",
+ LanguageVersion.Default,
+ new CSharpParseOptions(LanguageVersion.CSharp6));
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task UpgradeProjectToCSharp7()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"
+class Program
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}",
+ LanguageVersion.CSharp7,
+ new CSharpParseOptions(LanguageVersion.CSharp6),
+ index: 1);
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task UpgradeAllProjectsToDefault()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+
+
+
+
+
+
+",
+ LanguageVersion.Default,
+ parseOptions: null,
+ index: 2);
+
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task UpgradeAllProjectsToCSharp7()
+ {
+ await TestLanguageVersionUpgradedAsync(
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+
+
+
+
+
+
+",
+ LanguageVersion.Default,
+ parseOptions: null,
+ index: 2);
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task ListAllSuggestions()
+ {
+ await TestExactActionSetOfferedAsync(
+
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+
+
+",
+ new[] {
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "default"),
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "7"),
+ string.Format(CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0, "default"),
+ string.Format(CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0, "7")
+ });
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task FixAllProjectsNotOffered()
+ {
+ await TestExactActionSetOfferedAsync(
+
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+",
+ new[] {
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "default"),
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "7")
+ });
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task OnlyOfferFixAllProjectsToCSharp7WhenApplicable()
+ {
+ await TestExactActionSetOfferedAsync(
+
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+
+
+",
+ new[] {
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "default"),
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "7"),
+ string.Format(CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0, "default")
+ });
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUpgradeProject)]
+ public async Task OnlyOfferFixAllProjectsToDefaultWhenApplicable()
+ {
+ await TestExactActionSetOfferedAsync(
+
+@"
+
+
+class C
+{
+ void A()
+ {
+ var x = [|(1, 2)|];
+ }
+}
+
+
+
+
+
+
+",
+ new[] {
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "default"),
+ string.Format(CSharpFeaturesResources.Upgrade_this_project_to_csharp_language_version_0, "7"),
+ string.Format(CSharpFeaturesResources.Upgrade_all_csharp_projects_to_language_version_0, "7")
+ });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs b/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
index f2d5bbf56e157..6c66c5e9405d6 100644
--- a/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
+++ b/src/EditorFeatures/CSharpTest/UseCollectionInitializer/UseCollectionInitializerTests.cs
@@ -699,6 +699,74 @@ static void Main(string[] args)
var myStringList = myStringArray?.ToList() ?? new [||]List();
myStringList.Add(""Done"");
}
+}");
+ }
+
+ [Fact, Trait(Traits.Feature, Traits.Features.CodeActionsUseCollectionInitializer)]
+ [WorkItem(17823, "https://github.com/dotnet/roslyn/issues/17823")]
+ public async Task TestMissingWhenReferencedInInitializer()
+ {
+ await TestMissingInRegularAndScriptAsync(
+@"
+using System.Collections.Generic;
+
+class C
+{
+ static void M()
+ {
+ var items = new [||]List