Skip to content

Commit

Permalink
Merge pull request #12080 from jaredpar/patch
Browse files Browse the repository at this point in the history
Tie language features to the langver flag
  • Loading branch information
jaredpar authored Jun 19, 2016
2 parents 816218d + 0eae3a4 commit df88a0d
Show file tree
Hide file tree
Showing 30 changed files with 142 additions and 147 deletions.
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Binder/Binder_Symbols.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2090,7 +2090,7 @@ internal static void CheckFeatureAvailability(Location location, 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(), feature.RequiredFeatureLegacy() ?? requiredVersion.Localize());
}
}
}
Expand Down
21 changes: 1 addition & 20 deletions src/Compilers/CSharp/Portable/CSharpParseOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public override IEnumerable<string> PreprocessorSymbolNames
}

public CSharpParseOptions(
LanguageVersion languageVersion = LanguageVersion.CSharp6,
LanguageVersion languageVersion = LanguageVersion.CSharp7,
DocumentationMode documentationMode = DocumentationMode.Parse,
SourceCodeKind kind = SourceCodeKind.Regular,
IEnumerable<string> preprocessorSymbols = null)
Expand Down Expand Up @@ -211,25 +211,6 @@ public override IReadOnlyDictionary<string, string> Features

internal bool IsFeatureEnabled(MessageID feature)
{
switch (feature)
{
case MessageID.IDS_FeatureBinaryLiteral:
case MessageID.IDS_FeatureDigitSeparator:
case MessageID.IDS_FeatureLocalFunctions:
case MessageID.IDS_FeatureRefLocalsReturns:
case MessageID.IDS_FeaturePatternMatching:
case MessageID.IDS_FeatureTuples:
case MessageID.IDS_FeatureReplace:
// in "demo" mode enable proposed new C# 7 language features.
if (PreprocessorSymbols.Contains("__DEMO__"))
{
return true;
}
break;
default:
break;
}

string featureFlag = feature.RequiredFeature();
if (featureFlag != null)
{
Expand Down
3 changes: 3 additions & 0 deletions src/Compilers/CSharp/Portable/CSharpResources.resx
Original file line number Diff line number Diff line change
Expand Up @@ -4329,6 +4329,9 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_FeatureNotAvailableInVersion6" xml:space="preserve">
<value>Feature '{0}' is not available in C# 6. Please use language version {1} or greater.</value>
</data>
<data name="ERR_FeatureNotAvailableInVersion7" xml:space="preserve">
<value>Feature '{0}' is not available in C# 7. Please use language version {1} or greater.</value>
</data>
<data name="ERR_FeatureIsExperimental" xml:space="preserve">
<value>Feature '{0}' is experimental and unsupported; use '/features:{1}' to enable.</value>
</data>
Expand Down
3 changes: 2 additions & 1 deletion src/Compilers/CSharp/Portable/Errors/ErrorCode.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1287,7 +1287,8 @@ internal enum ErrorCode
ERR_FeatureIsExperimental = 8058,
ERR_FeatureNotAvailableInVersion6 = 8059,
ERR_FeatureIsUnimplemented = 8060,
// available 8061-8069
ERR_FeatureNotAvailableInVersion7 = 8061,
// available 8062-8069
ERR_SwitchFallOut = 8070,
// ERR_UnexpectedBoundGenericName = 8071, // for nameof - used in an early prototype
ERR_NullPropagatingOpInExpressionTree = 8072,
Expand Down
15 changes: 15 additions & 0 deletions src/Compilers/CSharp/Portable/Errors/MessageID.cs
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,11 @@ public static LocalizableErrorArgument Localize(this MessageID id)
// Features should be mutually exclusive between RequiredFeature and RequiredVersion.
// (hence the above rule - RequiredVersion throws when RequiredFeature returns non-null)
internal static string RequiredFeature(this MessageID feature)
{
return null;
}

internal static string RequiredFeatureLegacy(this MessageID feature)
{
switch (feature)
{
Expand Down Expand Up @@ -188,6 +193,16 @@ internal static LanguageVersion RequiredVersion(this MessageID feature)
// Checks are in the LanguageParser unless otherwise noted.
switch (feature)
{
// C# 7 features.
case MessageID.IDS_FeatureBinaryLiteral:
case MessageID.IDS_FeatureDigitSeparator:
case MessageID.IDS_FeatureLocalFunctions:
case MessageID.IDS_FeatureRefLocalsReturns:
case MessageID.IDS_FeaturePatternMatching:
case MessageID.IDS_FeatureTuples:
case MessageID.IDS_FeatureReplace:
return LanguageVersion.CSharp7;

// C# 6 features.
case MessageID.IDS_FeatureExceptionFilter:
case MessageID.IDS_FeatureAutoPropertyInitializer:
Expand Down
11 changes: 9 additions & 2 deletions src/Compilers/CSharp/Portable/LanguageVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -57,13 +57,17 @@ public enum LanguageVersion
/// </list>
/// </remarks>
CSharp6 = 6,
/// <summary>
/// C# language version 7.
/// </summary>
CSharp7 = 7,
}

internal static partial class LanguageVersionExtensions
{
internal static bool IsValid(this LanguageVersion value)
{
return value >= LanguageVersion.CSharp1 && value <= LanguageVersion.CSharp6;
return value >= LanguageVersion.CSharp1 && value <= LanguageVersion.CSharp7;
}

internal static object Localize(this LanguageVersion value)
Expand All @@ -86,7 +90,10 @@ internal static ErrorCode GetErrorCode(this LanguageVersion version)
case LanguageVersion.CSharp5:
return ErrorCode.ERR_FeatureNotAvailableInVersion5;
case LanguageVersion.CSharp6:
return ErrorCode.ERR_FeatureNotAvailableInVersion6;
case LanguageVersion.CSharp7:
// This is done for preview 3 only to reduce churn in the test suites. Real error will be used
// in the main branch.
return ErrorCode.ERR_FeatureIsExperimental;
default:
throw ExceptionUtilities.UnexpectedValue(version);
}
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Portable/Parser/Lexer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -913,7 +913,7 @@ 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, feature.RequiredFeatureLegacy() ?? requiredVersion.Localize());
}

private bool ScanInteger()
Expand Down
4 changes: 2 additions & 2 deletions src/Compilers/CSharp/Portable/Parser/SyntaxParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1052,11 +1052,11 @@ protected TNode CheckFeatureAvailability<TNode>(TNode node, MessageID feature, b

if (forceWarning)
{
SyntaxDiagnosticInfo rawInfo = new SyntaxDiagnosticInfo(availableVersion.GetErrorCode(), featureName, requiredVersion.Localize());
SyntaxDiagnosticInfo rawInfo = new SyntaxDiagnosticInfo(availableVersion.GetErrorCode(), featureName, feature.RequiredFeatureLegacy() ?? requiredVersion.Localize());
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, feature.RequiredFeatureLegacy() ?? requiredVersion.Localize());
}
}

Expand Down
1 change: 0 additions & 1 deletion src/Compilers/CSharp/Portable/PublicAPI.Shipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,6 @@ Microsoft.CodeAnalysis.CSharp.CSharpDiagnosticFormatter
Microsoft.CodeAnalysis.CSharp.CSharpExtensions
Microsoft.CodeAnalysis.CSharp.CSharpFileSystemExtensions
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion languageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp6, Microsoft.CodeAnalysis.DocumentationMode documentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, Microsoft.CodeAnalysis.SourceCodeKind kind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, System.Collections.Generic.IEnumerable<string> preprocessorSymbols = null) -> void
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.Equals(Microsoft.CodeAnalysis.CSharp.CSharpParseOptions other) -> bool
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.LanguageVersion.get -> Microsoft.CodeAnalysis.CSharp.LanguageVersion
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.WithDocumentationMode(Microsoft.CodeAnalysis.DocumentationMode documentationMode) -> Microsoft.CodeAnalysis.CSharp.CSharpParseOptions
Expand Down
2 changes: 2 additions & 0 deletions src/Compilers/CSharp/Portable/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
Microsoft.CodeAnalysis.CSharp.CSharpParseOptions.CSharpParseOptions(Microsoft.CodeAnalysis.CSharp.LanguageVersion languageVersion = Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp7, Microsoft.CodeAnalysis.DocumentationMode documentationMode = Microsoft.CodeAnalysis.DocumentationMode.Parse, Microsoft.CodeAnalysis.SourceCodeKind kind = Microsoft.CodeAnalysis.SourceCodeKind.Regular, System.Collections.Generic.IEnumerable<string> preprocessorSymbols = null) -> void
Microsoft.CodeAnalysis.CSharp.Conversion.IsTuple.get -> bool
Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp7 = 7 -> Microsoft.CodeAnalysis.CSharp.LanguageVersion
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.RefKeyword.get -> Microsoft.CodeAnalysis.SyntaxToken
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.Update(Microsoft.CodeAnalysis.SyntaxToken arrowToken, Microsoft.CodeAnalysis.SyntaxToken refKeyword, Microsoft.CodeAnalysis.CSharp.Syntax.ExpressionSyntax expression) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax.WithRefKeyword(Microsoft.CodeAnalysis.SyntaxToken refKeyword) -> Microsoft.CodeAnalysis.CSharp.Syntax.ArrowExpressionClauseSyntax
Expand Down
30 changes: 28 additions & 2 deletions src/Compilers/CSharp/Test/CommandLine/CommandLineTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1169,7 +1169,7 @@ public void ArgumentParsing()
[Fact]
public void LangVersion()
{
const LanguageVersion DefaultVersion = LanguageVersion.CSharp6;
const LanguageVersion DefaultVersion = LanguageVersion.CSharp7;

var parsedArgs = DefaultParse(new[] { "/langversion:1", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Expand All @@ -1195,6 +1195,22 @@ public void LangVersion()
parsedArgs.Errors.Verify();
Assert.Equal(LanguageVersion.CSharp6, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:6", "/langversion:7", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(LanguageVersion.CSharp7, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:7", "/langversion:6", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(LanguageVersion.CSharp6, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:7", "/langversion:1", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(LanguageVersion.CSharp1, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:7", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(LanguageVersion.CSharp7, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:default", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);
Expand Down Expand Up @@ -1228,6 +1244,11 @@ public void LangVersion()

// override value with default
parsedArgs = DefaultParse(new[] { "/langversion:6", "/langversion:default", "a.cs" }, _baseDirectory);
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);
parsedArgs.Errors.Verify();

// override value with default
parsedArgs = DefaultParse(new[] { "/langversion:7", "/langversion:default", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify();
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);

Expand All @@ -1246,9 +1267,14 @@ public void LangVersion()
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:7", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify(
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("0"));
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:8", "a.cs" }, _baseDirectory);
parsedArgs.Errors.Verify(
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("0"),
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("7"));
Diagnostic(ErrorCode.ERR_BadCompatMode).WithArguments("8"));
Assert.Equal(DefaultVersion, parsedArgs.ParseOptions.LanguageVersion);

parsedArgs = DefaultParse(new[] { "/langversion:0", "/langversion:1000", "a.cs" }, _baseDirectory);
Expand Down
2 changes: 1 addition & 1 deletion src/Compilers/CSharp/Test/Emit/CodeGen/CodeGenTupleTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6542,7 +6542,7 @@ static void Main()
}
" + trivial2uple;

var comp = CreateCompilationWithMscorlib(source);
var comp = CreateCompilationWithMscorlib(source, parseOptions: TestOptions.Regular6);
comp.VerifyDiagnostics(
// (6,9): error CS8058: Feature 'tuples' is experimental and unsupported; use '/features:tuples' to enable.
// (int, int) x = (1, 1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests
public class OperationAnalyzerTests : CompilingTestBase
{
private readonly static CSharpParseOptions patternParseOptions =
TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)
.WithFeature(MessageID.IDS_FeaturePatternMatching.RequiredFeature(), "true");
TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7);

[Fact]
public void EmptyArrayCSharp()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,7 @@ namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public class PatternMatchingTests : CSharpTestBase
{
private static CSharpParseOptions patternParseOptions =
TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp6)
.WithFeature(MessageID.IDS_FeaturePatternMatching.RequiredFeature(), "true");
private static CSharpParseOptions patternParseOptions = TestOptions.Regular.WithLanguageVersion(LanguageVersion.CSharp7);

[Fact]
public void DemoModes()
Expand Down Expand Up @@ -45,7 +43,7 @@ public static void Main()
public Vec(int x) {}
}
";
var regularParseOptions = TestOptions.Regular;
var regularParseOptions = TestOptions.Regular6;
CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: regularParseOptions).VerifyDiagnostics(
// (7,18): error CS8058: Feature 'binary literals' is experimental and unsupported; use '/features:binaryLiterals' to enable.
// int i1 = 0b001010; // binary literals
Expand All @@ -71,8 +69,7 @@ public Vec(int x) {}
);

// enables binary literals, digit separators, local functions, ref locals, pattern matching
var demoParseOptions = regularParseOptions
.WithPreprocessorSymbols(new[] { "__DEMO__" });
var demoParseOptions = regularParseOptions.WithLanguageVersion(LanguageVersion.CSharp7);
CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: demoParseOptions).VerifyDiagnostics(
// (8,13): warning CS0219: The variable 'i2' is assigned but its value is never used
// int i2 = 23_554; // digit separators
Expand Down Expand Up @@ -382,7 +379,7 @@ private static bool M(object o, bool result)
}
}
";
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions.WithFeature(MessageID.IDS_FeatureLocalFunctions.RequiredFeature(), "true"));
var compilation = CreateCompilationWithMscorlib45(source, options: TestOptions.DebugExe, parseOptions: patternParseOptions);
compilation.VerifyDiagnostics();
var expectedOutput =
@"False for 1
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2232,7 +2232,7 @@ public static int Main() {
return 1;
}

}")
}", parseOptions: TestOptions.Regular6)
.VerifyDiagnostics(
// (7,22): error CS0118: 'myTest' is a 'variable' but is used like a 'type'
Diagnostic(ErrorCode.ERR_BadSKknown, "myTest").WithArguments("myTest", "variable", "type"));
Expand Down Expand Up @@ -4038,7 +4038,10 @@ public static void Main()
}
}
}";
DiagnosticsUtils.VerifyErrorsAndGetCompilationWithMscorlib(text,
var comp = CSharpTestBase.CreateCompilationWithMscorlib(text, parseOptions: TestOptions.Regular6);
var actualErrors = comp.GetDiagnostics();
DiagnosticsUtils.VerifyErrorCodes(
actualErrors,
new ErrorDescription[] { new ErrorDescription { Code = (int)ErrorCode.ERR_SwitchGoverningTypeValueExpected, Line = 18, Column = 15 } });
}

Expand Down
Loading

0 comments on commit df88a0d

Please sign in to comment.