diff --git a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs index 40d2e275639251e0cf332e98af881d5234f0f4d8..0adf04c4494b38b6737b44c3beb4700040c1e084 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs +++ b/Src/Compilers/CSharp/Source/CSharpResources.Designer.cs @@ -10599,6 +10599,15 @@ internal class CSharpResources { } } + /// + /// Looks up a localized string similar to String or numeric literal expected. + /// + internal static string WRN_StringOrNumericLiteralExpected { + get { + return ResourceManager.GetString("WRN_StringOrNumericLiteralExpected", resourceCulture); + } + } + /// /// Looks up a localized string similar to Source file has exceeded the limit of 16,707,565 lines representable in the PDB; debug information will be incorrect. /// diff --git a/Src/Compilers/CSharp/Source/CSharpResources.resx b/Src/Compilers/CSharp/Source/CSharpResources.resx index cae81bc1183089e4868b5ce2b0fffd5bb40a42c0..a97630f8e13dff62d8e017135d46bd64516e685a 100644 --- a/Src/Compilers/CSharp/Source/CSharpResources.resx +++ b/Src/Compilers/CSharp/Source/CSharpResources.resx @@ -3779,4 +3779,7 @@ Operation caused a stack overflow. + + String or numeric literal expected + \ No newline at end of file diff --git a/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs b/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs index 5070718e82c6289a970541b35d9fe80fc615b4d2..4f107a92334e0c5c51294ab76da3551e09c9f8af 100644 --- a/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs +++ b/Src/Compilers/CSharp/Source/Errors/ErrorCode.cs @@ -644,6 +644,7 @@ internal enum ErrorCode ERR_DottedTypeNameNotFoundInNSFwd = 1069, ERR_SingleTypeNameNotFoundFwd = 1070, //ERR_NoSuchMemberOnNoPIAType = 1071, //EE + WRN_StringOrNumericLiteralExpected = 1072, // ERR_EOLExpected = 1099, // EE // ERR_NotSupportedinEE = 1100, // EE ERR_BadThisParam = 1100, diff --git a/Src/Compilers/CSharp/Source/Errors/ErrorFacts.cs b/Src/Compilers/CSharp/Source/Errors/ErrorFacts.cs index 30fe980b57da8781dc437dce9b64c4b6177aeec6..4655f5e8becad998420c88fccb95593384c44374 100644 --- a/Src/Compilers/CSharp/Source/Errors/ErrorFacts.cs +++ b/Src/Compilers/CSharp/Source/Errors/ErrorFacts.cs @@ -276,6 +276,7 @@ internal static int GetWarningLevel(ErrorCode code) case ErrorCode.WRN_RefCultureMismatch: case ErrorCode.WRN_ConflictingMachineAssembly: case ErrorCode.WRN_FilterIsConstant: + case ErrorCode.WRN_StringOrNumericLiteralExpected: return 1; default: return 0; diff --git a/Src/Compilers/CSharp/Source/Parser/DirectiveParser.cs b/Src/Compilers/CSharp/Source/Parser/DirectiveParser.cs index eb4977e23760ab556699fff53ffcd4c7d1fd6d2d..0e068b26ef5c5d50ba33f8d5c43994895e7fc7fe 100644 --- a/Src/Compilers/CSharp/Source/Parser/DirectiveParser.cs +++ b/Src/Compilers/CSharp/Source/Parser/DirectiveParser.cs @@ -1,4 +1,4 @@ -// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft Open Technologies, Inc. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using System; using System.Linq; @@ -374,32 +374,65 @@ private DirectiveTriviaSyntax ParsePragmaDirective(SyntaxToken hash, SyntaxToken if (this.CurrentToken.Kind == SyntaxKind.DisableKeyword || this.CurrentToken.Kind == SyntaxKind.RestoreKeyword) { style = this.EatToken(); - var codes = new SeparatedSyntaxListBuilder(10); + var ids = new SeparatedSyntaxListBuilder(10); while (this.CurrentToken.Kind != SyntaxKind.EndOfDirectiveToken) { - var code = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_InvalidNumber, reportError: isActive); - if (isActive && !code.IsMissing) + SyntaxToken id; + ExpressionSyntax idExpression; + + if (this.CurrentToken.Kind == SyntaxKind.NumericLiteralToken || this.CurrentToken.Kind == SyntaxKind.StringLiteralToken) { - int value = (int)code.Value; - if (ErrorFacts.GetSeverity((ErrorCode)value) != DiagnosticSeverity.Warning) + id = this.EatToken(); + if (isActive) { - code = this.AddError(code, ErrorCode.WRN_BadWarningNumber, value); + if (id.Kind == SyntaxKind.NumericLiteralToken) + { + int compilerWarningNumber = (int)id.Value; + if (ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning) + { + id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, compilerWarningNumber); + } + } + else + { + string value = (string)id.Value; + var messageProvider = MessageProvider.Instance; + if (value.StartsWith(messageProvider.CodePrefix)) + { + // For diagnostic IDs of the form "CS[0-9]*", verify the error code is that of a warning + int compilerWarningNumber; + if (int.TryParse(value.Substring(messageProvider.CodePrefix.Length), out compilerWarningNumber) && + (messageProvider.GetIdForErrorCode(compilerWarningNumber) != value || + ErrorFacts.GetSeverity((ErrorCode)compilerWarningNumber) != DiagnosticSeverity.Warning)) + { + id = this.AddError(id, ErrorCode.WRN_BadWarningNumber, value); + } + } + } } + + var expressionKind = id.Kind == SyntaxKind.NumericLiteralToken ? SyntaxKind.NumericLiteralExpression : SyntaxKind.StringLiteralExpression; + idExpression = SyntaxFactory.LiteralExpression(expressionKind, id); + } + else + { + id = this.EatToken(SyntaxKind.NumericLiteralToken, ErrorCode.WRN_StringOrNumericLiteralExpected, reportError: isActive); + idExpression = SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, id); } - hasError = hasError || code.ContainsDiagnostics; - codes.Add(SyntaxFactory.LiteralExpression(SyntaxKind.NumericLiteralExpression, code)); + hasError = hasError || id.ContainsDiagnostics; + ids.Add(idExpression); if (this.CurrentToken.Kind != SyntaxKind.CommaToken) { break; } - codes.AddSeparator(this.EatToken()); + ids.AddSeparator(this.EatToken()); } var end = this.ParseEndOfDirective(hasError || !isActive, afterPragma: true); - return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, codes.ToList(), end, isActive); + return SyntaxFactory.PragmaWarningDirectiveTrivia(hash, pragma, warning, style, ids.ToList(), end, isActive); } else { diff --git a/Src/Compilers/CSharp/Source/Syntax/CSharpPragmaWarningStateMap.cs b/Src/Compilers/CSharp/Source/Syntax/CSharpPragmaWarningStateMap.cs index 4f49cb0e833dc998f9dadb47226ef35bfcecddbe..c67e855c43579d84196617f40c10d902eb056b6c 100644 --- a/Src/Compilers/CSharp/Source/Syntax/CSharpPragmaWarningStateMap.cs +++ b/Src/Compilers/CSharp/Source/Syntax/CSharpPragmaWarningStateMap.cs @@ -96,8 +96,10 @@ private static WarningStateMapEntry[] CreatePragmaWarningStateEntries(ImmutableA if (currentDirective.ErrorCodes[x].IsMissing || currentDirective.ErrorCodes[x].ContainsDiagnostics) continue; - int errorCode = (int)((LiteralExpressionSyntax)currentDirective.ErrorCodes[x]).Token.Value; - string errorId = MessageProvider.Instance.GetIdForErrorCode(errorCode); + var token = ((LiteralExpressionSyntax)currentDirective.ErrorCodes[x]).Token; + string errorId = token.CSharpKind() == SyntaxKind.NumericLiteralToken ? + MessageProvider.Instance.GetIdForErrorCode((int)token.Value) : + (string)token.Value; // Update the state of this error code with the current directive state accumulatedSpecificWarningState = accumulatedSpecificWarningState.SetItem(errorId, directiveState); diff --git a/Src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs b/Src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs index d95abf117254d0e3c60b540c4174fa4071cd3d48..8b7e445fd26f4f1e775e4dd80fdf561f434ba8e7 100644 --- a/Src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs +++ b/Src/Compilers/CSharp/Test/Syntax/Diagnostics/DiagnosticTest.cs @@ -764,6 +764,119 @@ public static void Main() CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); } + [Fact] + public void PragmaWarning_9() + { + var text = @" +public class C +{ + public static void Main() + { +#pragma warning disable ""CS0168"" + int x; // CS0168 + int y = 0; // CS0219 +#pragma warning restore ""CS0168"" + int z; + } +} +"; + // Verify that a warning can be disabled/restored with a string literal + CSharpCompilationOptions commonoption = TestOptions.Exe; + CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( + // (8,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y"), + // (10,13): warning CS0168: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z")); + + var warnings = new Dictionary(); + warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); + CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (8,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y"), + // (10,13): error CS0168: Warning as Error: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z").WithWarningAsError(true)); + + option = commonoption.WithWarningLevel(3); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (8,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y"), + // (10,13): warning CS0168: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z")); + + option = commonoption.WithWarningLevel(2); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + + option = commonoption.WithWarningLevel(2).WithGeneralDiagnosticOption(ReportDiagnostic.Error); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + + option = commonoption.WithWarningLevel(2).WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + } + + [Fact] + public void PragmaWarning_10() + { + var text = @" +#pragma warning disable ""CS0465"", 168, ""CS0219"" +public class C +{ + public static void Run() + { + int _x; // CS0168 + } + + public virtual void Finalize() // CS0465 + { + } + + public static void Main() + { + int x; // CS0168 + int y = 0; // CS0219 + Run(); +#pragma warning restore + int z; + } +} +"; + // Verify that warnings can be disabled using a mixed list of numeric and string literals + CSharpCompilationOptions commonoption = TestOptions.Exe; + CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( + // (20,13): warning CS0168: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z")); + + var warnings = new Dictionary(); + warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); + CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (20,13): error CS0168: Warning as Error: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z").WithWarningAsError(true)); + + option = commonoption.WithWarningLevel(3); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (20,13): warning CS0168: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z")); + + option = commonoption.WithWarningLevel(2); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + + option = commonoption.WithWarningLevel(2).WithGeneralDiagnosticOption(ReportDiagnostic.Error); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + + option = commonoption.WithWarningLevel(2).WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); + } + [Fact] public void PragmaWarningWithErrors_1() { @@ -946,6 +1059,7 @@ public class C public static void Main() { #pragma warning disable 1 +#pragma warning disable ""CS168"" int x; // CS0168 int y = 0; // CS0219 #pragma warning restore all @@ -958,9 +1072,12 @@ public static void Main() // (6,25): warning CS1691: '1' is not a valid warning number // #pragma warning disable 1 Diagnostic(ErrorCode.WRN_BadWarningNumber, "1").WithArguments("1"), - // (9,25): warning CS1692: Invalid number + // (7,25): warning CS1691: 'CS168' is not a valid warning number + // #pragma warning disable "CS168" + Diagnostic(ErrorCode.WRN_BadWarningNumber, @"""CS168""").WithArguments("CS168"), + // (9,25): warning CS1072: String or numeric literal expected // #pragma warning restore all - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (7,13): warning CS0168: The variable 'x' is declared but never used // int x; // CS0168 Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x"), @@ -978,9 +1095,12 @@ public static void Main() // (6,25): warning CS1691: '1' is not a valid warning number // #pragma warning disable 1 Diagnostic(ErrorCode.WRN_BadWarningNumber, "1").WithArguments("1"), - // (9,25): warning CS1692: Invalid number + // (7,25): warning CS1691: 'CS168' is not a valid warning number + // #pragma warning disable "CS168" + Diagnostic(ErrorCode.WRN_BadWarningNumber, @"""CS168""").WithArguments("CS168"), + // (9,25): warning CS1072: String or numeric literal expected // #pragma warning restore all - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (7,13): error CS0168: Warning as Error: The variable 'x' is declared but never used // int x; // CS0168 Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithWarningAsError(true), @@ -996,9 +1116,12 @@ public static void Main() // (6,25): warning CS1691: '1' is not a valid warning number // #pragma warning disable 1 Diagnostic(ErrorCode.WRN_BadWarningNumber, "1").WithArguments("1"), - // (9,25): warning CS1692: Invalid number + // (7,25): warning CS1691: 'CS168' is not a valid warning number + // #pragma warning disable "CS168" + Diagnostic(ErrorCode.WRN_BadWarningNumber, @"""CS168""").WithArguments("CS168"), + // (9,25): warning CS1072: String or numeric literal expected // #pragma warning restore all - Diagnostic(ErrorCode.WRN_InvalidNumber, "all")); + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all")); } [Fact] @@ -1070,9 +1193,9 @@ public static void Main() CSharpCompilationOptions commonoption = TestOptions.Exe; CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( - // (7,25): warning CS1692: Invalid number + // (7,25): warning CS1072: String or numeric literal expected // #pragma warning disable all, 168 - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (8,13): warning CS0168: The variable 'x' is declared but never used // int x; // CS0168 Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x"), @@ -1087,9 +1210,9 @@ public static void Main() warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( - // (7,25): warning CS1692: Invalid number + // (7,25): warning CS1072: String or numeric literal expected // #pragma warning disable all, 168 - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (8,13): error CS0168: Warning as Error: The variable 'x' is declared but never used // int x; // CS0168 Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithWarningAsError(true), @@ -1102,9 +1225,9 @@ public static void Main() option = commonoption.WithWarningLevel(2); CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( - // (7,25): warning CS1692: Invalid number + // (7,25): warning CS1072: String or numeric literal expected // #pragma warning disable all, 168 - Diagnostic(ErrorCode.WRN_InvalidNumber, "all")); + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all")); } [Fact] @@ -1126,9 +1249,9 @@ public static void Main() CSharpCompilationOptions commonoption = TestOptions.Exe; CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( - // (7,30): warning CS1692: Invalid number + // (7,30): warning CS1072: String or numeric literal expected // #pragma warning disable 168, all - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (9,13): warning CS0219: The variable 'y' is assigned but its value is never used // int y = 0; // CS0219 Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y"), @@ -1140,9 +1263,9 @@ public static void Main() warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( - // (7,30): warning CS1692: Invalid number + // (7,30): warning CS1072: String or numeric literal expected // #pragma warning disable 168, all - Diagnostic(ErrorCode.WRN_InvalidNumber, "all"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all"), // (9,13): warning CS0219: The variable 'y' is assigned but its value is never used // int y = 0; // CS0219 Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y"), @@ -1152,9 +1275,9 @@ public static void Main() option = commonoption.WithWarningLevel(2); CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( - // (7,25): warning CS1692: Invalid number - // #pragma warning disable all, 168 - Diagnostic(ErrorCode.WRN_InvalidNumber, "all")); + // (7,30): warning CS1072: String or numeric literal expected + // #pragma warning disable 168, all + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "all")); } [Fact] @@ -1259,6 +1382,143 @@ public static void Main() CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics(); } + [Fact] + public void PragmaWarningWithErrors_11() + { + var text = @" + +public class C +{ + public static void Main() + { +#pragma warning disable ""CS0168 + int x; // CS0168 + int y = 0; // CS0219 +#pragma warning restore + } +}"; + CSharpCompilationOptions commonoption = TestOptions.Exe; + CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( + // (7,25): error CS1010: Newline in constant + // #pragma warning disable "CS0168 + Diagnostic(ErrorCode.ERR_NewlineInConst, ""), + // (8,13): warning CS0168: The variable 'x' is declared but never used + // int x; // CS0168 + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x"), + // (9,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y")); + + var warnings = new Dictionary(); + warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); + CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (7,25): error CS1010: Newline in constant + // #pragma warning disable "CS0168 + Diagnostic(ErrorCode.ERR_NewlineInConst, ""), + // (8,13): error CS0168: Warning as Error: The variable 'x' is declared but never used + // int x; // CS0168 + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithWarningAsError(true), + // (9,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y")); + + warnings[MessageProvider.Instance.GetIdForErrorCode(168)] = ReportDiagnostic.Suppress; + option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (7,25): error CS1010: Newline in constant + // #pragma warning disable "CS0168 + Diagnostic(ErrorCode.ERR_NewlineInConst, ""), + // (9,13): warning CS0219: The variable 'y' is assigned but its value is never used + // int y = 0; // CS0219 + Diagnostic(ErrorCode.WRN_UnreferencedVarAssg, "y").WithArguments("y")); + + option = commonoption.WithWarningLevel(2); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (7,25): error CS1010: Newline in constant + // #pragma warning disable "CS0168 + Diagnostic(ErrorCode.ERR_NewlineInConst, "")); + } + + [Fact] + public void PragmaWarningWithErrors_12() + { + var text = @" +public class C +{ + public static void Main() + { +#pragma warning disable , + int x; // CS0168 +#pragma warning restore , , + int z; + } +}"; + + CSharpCompilationOptions commonoption = TestOptions.Exe; + CreateCompilationWithMscorlib(text, compOptions: commonoption).VerifyDiagnostics( + // (6,25): warning CS1072: String or numeric literal expected + // #pragma warning disable , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,25): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,27): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (7,13): warning CS0168: The variable 'x' is declared but never used + // int x; // CS0168 + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x"), + // (9,13): warning CS0168: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z")); + + var warnings = new Dictionary(); + warnings.Add(MessageProvider.Instance.GetIdForErrorCode(168), ReportDiagnostic.Error); + CSharpCompilationOptions option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (6,25): warning CS1072: String or numeric literal expected + // #pragma warning disable , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,25): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,27): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (7,13): error CS0168: Warning as Error: The variable 'x' is declared but never used + // int x; // CS0168 + Diagnostic(ErrorCode.WRN_UnreferencedVar, "x").WithArguments("x").WithWarningAsError(true), + // (9,13): error CS0168: Warning as Error: The variable 'z' is declared but never used + // int z; + Diagnostic(ErrorCode.WRN_UnreferencedVar, "z").WithArguments("z").WithWarningAsError(true)); + + warnings[MessageProvider.Instance.GetIdForErrorCode(168)] = ReportDiagnostic.Suppress; + option = commonoption.WithSpecificDiagnosticOptions(warnings); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (6,25): warning CS1072: String or numeric literal expected + // #pragma warning disable , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,25): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,27): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ",")); + + option = commonoption.WithWarningLevel(2); + CreateCompilationWithMscorlib(text, compOptions: option).VerifyDiagnostics( + // (6,25): warning CS1072: String or numeric literal expected + // #pragma warning disable , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,25): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ","), + // (8,27): warning CS1072: String or numeric literal expected + // #pragma warning restore , , + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, ",")); + } + [WorkItem(546814)] [Fact] public void PragmaWarningAlign_0() diff --git a/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DisabledRegionTests.cs b/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DisabledRegionTests.cs index d1a76c5a87ef04df5ecf4298e58102df4f316670..d013882b86a6a32fdcadd6fc986cf68a34bf5d33 100644 --- a/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DisabledRegionTests.cs +++ b/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/DisabledRegionTests.cs @@ -92,7 +92,7 @@ class C { } ParserErrorMessageTests.ParseAndValidate(source, Diagnostic(ErrorCode.WRN_IllegalPragma, ""), Diagnostic(ErrorCode.WRN_IllegalPPWarning, ""), - Diagnostic(ErrorCode.WRN_InvalidNumber, "foo"), + Diagnostic(ErrorCode.WRN_StringOrNumericLiteralExpected, "foo"), Diagnostic(ErrorCode.WRN_BadWarningNumber, "0").WithArguments("0"), Diagnostic(ErrorCode.WRN_IllegalPPChecksum, ""), Diagnostic(ErrorCode.WRN_IllegalPPChecksum, ""), diff --git a/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs b/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs index d4c69e39cce1c5a8fb02e875d94ba583f0b939e7..9a1bc4ad3352df2b18fcc8978e583031c96e0726 100644 --- a/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs +++ b/Src/Compilers/CSharp/Test/Syntax/LexicalAndXml/PreprocessorTests.cs @@ -45,7 +45,7 @@ internal struct PragmaInfo public SyntaxKind PragmaKind; public SyntaxKind WarningOrChecksumKind; public SyntaxKind DisableOrRestoreKind; - public int[] WarnginList; + public int[] WarningList; public string[] FileGuidByte; } @@ -248,23 +248,34 @@ private void VerifyDirectivePragma(CSharpSyntaxNode node, PragmaInfo expected) Assert.Equal(expected.DisableOrRestoreKind, pwd.DisableOrRestoreKeyword.CSharpKind()); } - if (expected.WarnginList == null || expected.WarnginList.Length == 0) + if (expected.WarningList == null || expected.WarningList.Length == 0) { Assert.Equal(0, pwd.ErrorCodes.Count); } else { - Assert.Equal(expected.WarnginList.Length, pwd.ErrorCodes.Count); + Assert.Equal(expected.WarningList.Length, pwd.ErrorCodes.Count); int idx = 0; - foreach (var w in expected.WarnginList) + foreach (var warningNumber in expected.WarningList) { - var wc = ((LiteralExpressionSyntax)pwd.ErrorCodes[idx++]).Token; + var token = ((LiteralExpressionSyntax)pwd.ErrorCodes[idx++]).Token; - // not check if <=0 - if (w > 0) + if (warningNumber > 0) { - Assert.Equal(w, wc.Value); - Assert.Equal(w, Int32.Parse(wc.Text)); + var tokenKind = token.CSharpKind(); + if (tokenKind == SyntaxKind.NumericLiteralToken) + { + Assert.Equal(warningNumber, token.Value); + Assert.Equal(warningNumber, int.Parse(token.Text)); + } + else if (tokenKind == SyntaxKind.StringLiteralToken) + { + Assert.Equal(MessageProvider.Instance.GetIdForErrorCode(warningNumber), token.Value); + } + else + { + Assert.True(false, "Warning ID must be a string or numeric literal"); + } } } } @@ -3291,7 +3302,7 @@ public void TestPragmaWarningDisable() PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.DisableKeyword, - WarnginList = new int[] { 114 } + WarningList = new int[] { 114 } }); } @@ -3307,7 +3318,7 @@ public void TestPragmaWarningDisableWithMultipleCodes() PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.DisableKeyword, - WarnginList = new int[] { 114, 162, 168 } + WarningList = new int[] { 114, 162, 168 } }); } @@ -3335,7 +3346,7 @@ class A PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.DisableKeyword, - WarnginList = new int[] { 440 } + WarningList = new int[] { 440 } }); // verify that GetParseDiagnostics filters disabled warning @@ -3361,7 +3372,7 @@ public void TestRegressNegPragmaWarningDisableWithBadCode() PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.DisableKeyword, - WarnginList = new int[] { 99999 } + WarningList = new int[] { 99999 } }); } @@ -3377,7 +3388,7 @@ public void TestPragmaWarningRestore() PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.RestoreKeyword, - WarnginList = new int[] { 114 } + WarningList = new int[] { 114 } }); } @@ -3393,7 +3404,23 @@ public void TestPragmaWarningRestoreWithMultipleCodes() PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.RestoreKeyword, - WarnginList = new int[] { 114, 162, 168 } + WarningList = new int[] { 114, 162, 168 } + }); + } + + [Fact] + [Trait("Feature", "Directives")] + public void TestPragmaWarningRestoreWithMixedStringAndNumericCodes() + { + var text = @"#pragma warning restore ""CS0114"", 162, ""CS0168"" // Mixed string & numeric codes"; + var node = Parse(text); + TestRoundTripping(node, text); + VerifyDirectivePragma(node, new PragmaInfo + { + PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, + WarningOrChecksumKind = SyntaxKind.WarningKeyword, + DisableOrRestoreKind = SyntaxKind.RestoreKeyword, + WarningList = new int[] { 114, 162, 168 } }); } @@ -3404,13 +3431,13 @@ public void TestNegPragmaWarningRestoreWithBadCode() var text = @"#pragma warning restore CS1030"; var node = Parse(text); TestRoundTripping(node, text, false); - VerifyErrorSpecial(node, new DirectiveInfo { Number = (int)ErrorCode.WRN_InvalidNumber, Status = NodeStatus.IsWarning }); // CS1692 + VerifyErrorSpecial(node, new DirectiveInfo { Number = (int)ErrorCode.WRN_StringOrNumericLiteralExpected, Status = NodeStatus.IsWarning }); // CS1072 VerifyDirectivePragma(node, new PragmaInfo { PragmaKind = SyntaxKind.PragmaWarningDirectiveTrivia, WarningOrChecksumKind = SyntaxKind.WarningKeyword, DisableOrRestoreKind = SyntaxKind.RestoreKeyword, - WarnginList = new int[] { -1 } // special case - no value + WarningList = new int[] { -1 } // special case - no value }); }