提交 5408538f 编写于 作者: E elijah6 提交者: Neal Gafter

Misleading constant diagnostics (#18933)

* Separating warning messages for constant filter expression
* Deal with try-catch with finally block and add test
上级 b63240f7
......@@ -2646,13 +2646,21 @@ private BoundExpression BindCatchFilter(CatchFilterClauseSyntax filter, Diagnost
BoundExpression boundFilter = this.BindBooleanExpression(filter.FilterExpression, diagnostics);
if (boundFilter.ConstantValue != ConstantValue.NotAvailable)
{
Error(diagnostics, ErrorCode.WRN_FilterIsConstant, filter.FilterExpression);
// Depending on whether the filter constant is true or false, and whether there are other catch clauses,
// we suggest different actions
var errorCode = boundFilter.ConstantValue.BooleanValue
? ErrorCode.WRN_FilterIsConstantTrue
: (filter.Parent.Parent is TryStatementSyntax s && s.Catches.Count == 1 && s.Finally == null)
? ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch
: ErrorCode.WRN_FilterIsConstantFalse;
// Since the expression is a constant, the name can be retrieved from the first token
Error(diagnostics, errorCode, filter.FilterExpression);
}
return boundFilter;
}
// Report an extra error on the return if we are in a lambda conversion.
private void ReportCantConvertLambdaReturn(SyntaxNode syntax, DiagnosticBag diagnostics)
{
......
......@@ -13104,20 +13104,56 @@ internal class CSharpResources {
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant, consider removing the filter.
/// Looks up a localized string similar to Filter expression is a constant &apos;false&apos;, consider removing the catch clause.
/// </summary>
internal static string WRN_FilterIsConstant {
internal static string WRN_FilterIsConstantFalse {
get {
return ResourceManager.GetString("WRN_FilterIsConstant", resourceCulture);
return ResourceManager.GetString("WRN_FilterIsConstantFalse", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant.
/// Looks up a localized string similar to Filter expression is a constant &apos;false&apos;.
/// </summary>
internal static string WRN_FilterIsConstant_Title {
internal static string WRN_FilterIsConstantFalse_Title {
get {
return ResourceManager.GetString("WRN_FilterIsConstant_Title", resourceCulture);
return ResourceManager.GetString("WRN_FilterIsConstantFalse_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant &apos;false&apos;, consider removing the try-catch block.
/// </summary>
internal static string WRN_FilterIsConstantFalseRedundantTryCatch {
get {
return ResourceManager.GetString("WRN_FilterIsConstantFalseRedundantTryCatch", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant &apos;false&apos;. .
/// </summary>
internal static string WRN_FilterIsConstantFalseRedundantTryCatch_Title {
get {
return ResourceManager.GetString("WRN_FilterIsConstantFalseRedundantTryCatch_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant &apos;true&apos;, consider removing the filter.
/// </summary>
internal static string WRN_FilterIsConstantTrue {
get {
return ResourceManager.GetString("WRN_FilterIsConstantTrue", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Filter expression is a constant &apos;true&apos;.
/// </summary>
internal static string WRN_FilterIsConstantTrue_Title {
get {
return ResourceManager.GetString("WRN_FilterIsConstantTrue_Title", resourceCulture);
}
}
......
......@@ -759,11 +759,11 @@
<data name="ERR_UnreachableCatch" xml:space="preserve">
<value>A previous catch clause already catches all exceptions of this or of a super type ('{0}')</value>
</data>
<data name="WRN_FilterIsConstant" xml:space="preserve">
<value>Filter expression is a constant, consider removing the filter</value>
<data name="WRN_FilterIsConstantTrue" xml:space="preserve">
<value>Filter expression is a constant 'true', consider removing the filter</value>
</data>
<data name="WRN_FilterIsConstant_Title" xml:space="preserve">
<value>Filter expression is a constant</value>
<data name="WRN_FilterIsConstantTrue_Title" xml:space="preserve">
<value>Filter expression is a constant 'true'</value>
</data>
<data name="ERR_ReturnExpected" xml:space="preserve">
<value>'{0}': not all code paths return a value</value>
......@@ -5223,4 +5223,16 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ICompoundAssignmentOperationIsNotCSharpCompoundAssignment" xml:space="preserve">
<value>{0} is not a valid C# compound assignment operation</value>
</data>
<data name="WRN_FilterIsConstantFalse" xml:space="preserve">
<value>Filter expression is a constant 'false', consider removing the catch clause</value>
</data>
<data name="WRN_FilterIsConstantFalse_Title" xml:space="preserve">
<value>Filter expression is a constant 'false'</value>
</data>
<data name="WRN_FilterIsConstantFalseRedundantTryCatch" xml:space="preserve">
<value>Filter expression is a constant 'false', consider removing the try-catch block</value>
</data>
<data name="WRN_FilterIsConstantFalseRedundantTryCatch_Title" xml:space="preserve">
<value>Filter expression is a constant 'false'. </value>
</data>
</root>
......@@ -1232,7 +1232,7 @@ internal enum ErrorCode
ERR_FixedBufferTooManyDimensions = 7092,
ERR_CantReadConfigFile = 7093,
ERR_BadAwaitInCatchFilter = 7094,
WRN_FilterIsConstant = 7095,
WRN_FilterIsConstantTrue = 7095,
ERR_EncNoPIAReference = 7096,
//ERR_EncNoDynamicOperation = 7097, // dynamic operations are now allowed
ERR_LinkedNetmoduleMetadataMustProvideFullPEImage = 7098,
......@@ -1543,5 +1543,10 @@ internal enum ErrorCode
ERR_InvalidVersionFormatDeterministic = 8357,
ERR_AttributeCtorInParameter = 8358,
#region diagnostics for FilterIsConstant warning message fix
WRN_FilterIsConstantFalse = 8359,
WRN_FilterIsConstantFalseRedundantTryCatch = 8360,
#endregion diagnostics for FilterIsConstant warning message fix
}
}
......@@ -312,7 +312,9 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_BadUILang:
case ErrorCode.WRN_RefCultureMismatch:
case ErrorCode.WRN_ConflictingMachineAssembly:
case ErrorCode.WRN_FilterIsConstant:
case ErrorCode.WRN_FilterIsConstantTrue:
case ErrorCode.WRN_FilterIsConstantFalse:
case ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch:
case ErrorCode.WRN_IdentifierOrNumericLiteralExpected:
case ErrorCode.WRN_ReferencedAssemblyDoesNotHaveStrongName:
case ErrorCode.WRN_AlignmentMagnitude:
......
......@@ -158,7 +158,7 @@ public static bool IsWarning(ErrorCode code)
case ErrorCode.WRN_CallerLineNumberPreferredOverCallerMemberName:
case ErrorCode.WRN_CallerLineNumberPreferredOverCallerFilePath:
case ErrorCode.WRN_AssemblyAttributeFromModuleIsOverridden:
case ErrorCode.WRN_FilterIsConstant:
case ErrorCode.WRN_FilterIsConstantTrue:
case ErrorCode.WRN_UnimplementedCommandLineSwitch:
case ErrorCode.WRN_ReferencedAssemblyDoesNotHaveStrongName:
case ErrorCode.WRN_RefCultureMismatch:
......@@ -176,6 +176,8 @@ public static bool IsWarning(ErrorCode code)
case ErrorCode.WRN_Experimental:
case ErrorCode.WRN_DefaultInSwitch:
case ErrorCode.WRN_UnreferencedLocalFunction:
case ErrorCode.WRN_FilterIsConstantFalse:
case ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch:
return true;
default:
return false;
......
......@@ -5280,7 +5280,165 @@ static void M()
}
[Fact]
public void CS7095WRN_FilterIsConstant1()
public void CS8359WRN_FilterIsConstantFalse_NonBoolean()
{
// Non-boolean constant filters are not considered for WRN_FilterIsConstant warnings.
var text = @"
using System;
class A : Exception { }
class B : A { }
class Program
{
static void M()
{
try { }
catch (A) when (1) { }
catch (B) when (0) { }
catch (B) when (""false"") { }
catch (B) when (false) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): error CS0029: Cannot implicitly convert type 'int' to 'bool'
// catch (A) when (1) { }
Diagnostic(ErrorCode.ERR_NoImplicitConv, "1").WithArguments("int", "bool").WithLocation(11, 25),
// (12,25): error CS0029: Cannot implicitly convert type 'int' to 'bool'
// catch (B) when (0) { }
Diagnostic(ErrorCode.ERR_NoImplicitConv, "0").WithArguments("int", "bool").WithLocation(12, 25),
// (13,25): error CS0029: Cannot implicitly convert type 'string' to 'bool'
// catch (B) when ("false") { }
Diagnostic(ErrorCode.ERR_NoImplicitConv, @"""false""").WithArguments("string", "bool").WithLocation(13, 25),
// (14,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (B) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(14, 25));
}
[Fact]
public void CS8359WRN_FilterIsConstantFalse1()
{
var text = @"
using System;
class A : Exception { }
class B : A { }
class Program
{
static void M()
{
try { }
catch (A) when (false) { }
catch (B) when (false) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (A) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(11, 25),
// (12,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (B) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(12, 25));
}
[Fact]
public void CS8359WRN_FilterIsConstantFalse2()
{
var text = @"
using System;
class A : Exception { }
class B : A { }
class Program
{
static void M()
{
try { }
catch (A) when ((1+1)!=2) { }
catch (B) when (false) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (A) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "(1+1)!=2").WithLocation(11, 25),
// (12,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (B) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(12, 25));
}
[Fact]
public void CS8359WRN_FilterIsConstantFalse3()
{
var text = @"
using System;
class A : Exception { }
class Program
{
static void M()
{
try { }
catch (A) when (false) { }
finally { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (A) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(10, 25));
}
[Fact]
public void CS8360WRN_FilterIsConstantRedundantTryCatch1()
{
var text = @"
using System;
class A : Exception { }
class Program
{
static void M()
{
try { }
catch (A) when (false) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block
// catch (A) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(10, 25));
}
[Fact]
public void CS8360WRN_FilterIsConstantRedundantTryCatch2()
{
var text = @"
using System;
class A : Exception { }
class Program
{
static void M()
{
try { }
catch (A) when ((1+1)!=2) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block
// catch (A) when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "(1+1)!=2").WithLocation(10, 25));
}
[Fact]
public void CS7095WRN_FilterIsConstantTrue1()
{
var text = @"
using System;
......@@ -5298,13 +5456,13 @@ static void M()
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,23): warning CS7095: Filter expression is a constant, consider removing the filter
// (11,25): warning CS7095: Filter expression is a constant 'true', consider removing the filter
// catch (A) when (true) { }
Diagnostic(ErrorCode.WRN_FilterIsConstant, "true").WithLocation(11, 25));
Diagnostic(ErrorCode.WRN_FilterIsConstantTrue, "true").WithLocation(11, 25));
}
[Fact]
public void CS7095WRN_FilterIsConstant2()
public void CS7095WRN_FilterIsConstantTrue2()
{
var text = @"
using System;
......@@ -5322,12 +5480,34 @@ static void M()
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (10,19): warning CS7095: Filter expression is a constant, consider removing the filter
// (10,19): warning CS7095: Filter expression is a constant 'true', consider removing the filter
// catch when (true) { }
Diagnostic(ErrorCode.WRN_FilterIsConstant, "true").WithLocation(10, 21),
// (12,19): warning CS7095: Filter expression is a constant, consider removing the filter
Diagnostic(ErrorCode.WRN_FilterIsConstantTrue, "true").WithLocation(10, 21),
// (12,19): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch when (false) { }
Diagnostic(ErrorCode.WRN_FilterIsConstant, "false").WithLocation(12, 21));
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(12, 21));
}
[Fact]
public void CS7095WRN_FilterIsConstantTrue3()
{
var text = @"
using System;
class A : Exception { }
class Program
{
static void M()
{
try { }
catch when ((1+1)==2) { }
}
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (10,19): warning CS7095: Filter expression is a constant 'true', consider removing the filter
// catch when (true) { }
Diagnostic(ErrorCode.WRN_FilterIsConstantTrue, "(1+1)==2").WithLocation(10, 21));
}
[Fact]
......@@ -5352,9 +5532,9 @@ static void M()
}
";
CreateStandardCompilation(text).VerifyDiagnostics(
// (11,25): warning CS7095: Filter expression is a constant, consider removing the filter
// (11,25): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch (A) when (false)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "false").WithLocation(11, 25),
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(11, 25),
// (13,13): warning CS0162: Unreachable code detected
// Console.WriteLine(1);
Diagnostic(ErrorCode.WRN_UnreachableCode, "Console").WithLocation(13, 13)
......@@ -5385,9 +5565,9 @@ static void M()
// is to make conditional compilation easier. Such scenario doesn't apply to filters.
CreateStandardCompilation(text).VerifyDiagnostics(
// (10,33): warning CS7095: Filter expression is a constant, consider removing the filter
// (10,33): warning CS7105: Filter expression is a constant 'false', consider removing the try-catch block
// catch (Exception) when (false)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "false").WithLocation(10, 33),
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "false").WithLocation(10, 33),
// (12,13): warning CS0162: Unreachable code detected
// Console.WriteLine(x);
Diagnostic(ErrorCode.WRN_UnreachableCode, "Console").WithLocation(12, 13)
......@@ -5418,9 +5598,9 @@ static void M()
// is to make conditional compilation easier. Such scenario doesn't apply to filters.
CreateStandardCompilation(text).VerifyDiagnostics(
// (10,33): warning CS7095: Filter expression is a constant, consider removing the filter
// (10,33): warning CS7095: Filter expression is a constant 'true', consider removing the filter
// catch (Exception) when (true)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "true").WithLocation(10, 33),
Diagnostic(ErrorCode.WRN_FilterIsConstantTrue, "true").WithLocation(10, 33),
// (12,31): error CS0165: Use of unassigned local variable 'x'
// Console.WriteLine(x);
Diagnostic(ErrorCode.ERR_UseDefViolation, "x").WithArguments("x").WithLocation(12, 31)
......
......@@ -1232,9 +1232,9 @@ static void Main()
// (12,37): error CS8310: Operator '|' cannot be applied to operand 'default'
// System.Console.Write($"{true | default} {i} {b}");
Diagnostic(ErrorCode.ERR_BadOpOnNullOrDefault, "true | default").WithArguments("|", "default").WithLocation(12, 37),
// (15,40): warning CS7095: Filter expression is a constant, consider removing the filter
// (15,40): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block
// catch (System.Exception) when (default)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "default").WithLocation(15, 40),
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "default").WithLocation(15, 40),
// (17,13): warning CS0162: Unreachable code detected
// System.Console.Write("catch");
Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(17, 13)
......@@ -1262,9 +1262,9 @@ static void Main()
";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics(
// (10,40): warning CS7095: Filter expression is a constant, consider removing the filter
// (10,40): warning CS8360: Filter expression is a constant 'false', consider removing the try-catch block
// catch (System.Exception) when (false)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "default").WithLocation(10, 40),
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "default").WithLocation(10, 40),
// (12,13): warning CS0162: Unreachable code detected
// System.Console.Write("catch");
Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(12, 13)
......@@ -1308,9 +1308,9 @@ private static void SomeAction()
}";
var comp = CreateStandardCompilation(source, parseOptions: TestOptions.Regular7_1, options: TestOptions.DebugExe);
comp.VerifyDiagnostics(
// (26,40): warning CS7095: Filter expression is a constant, consider removing the filter
// catch (System.Exception) when (false)
Diagnostic(ErrorCode.WRN_FilterIsConstant, "default").WithLocation(26, 40),
// (26,40): warning CS8360: Filter expression is a constant, consider removing the filter
// catch (System.Exception) when (default)
Diagnostic(ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch, "default").WithLocation(26, 40),
// (28,13): warning CS0162: Unreachable code detected
// System.Console.Write("catch");
Diagnostic(ErrorCode.WRN_UnreachableCode, "System").WithLocation(28, 13)
......
......@@ -241,7 +241,9 @@ public void WarningLevel_2()
case ErrorCode.WRN_AssemblyAttributeFromModuleIsOverridden:
case ErrorCode.WRN_RefCultureMismatch:
case ErrorCode.WRN_ConflictingMachineAssembly:
case ErrorCode.WRN_FilterIsConstant:
case ErrorCode.WRN_FilterIsConstantFalse:
case ErrorCode.WRN_FilterIsConstantTrue:
case ErrorCode.WRN_FilterIsConstantFalseRedundantTryCatch:
case ErrorCode.WRN_AnalyzerCannotBeCreated:
case ErrorCode.WRN_NoAnalyzerInAssembly:
case ErrorCode.WRN_UnableToLoadAnalyzer:
......
......@@ -2020,9 +2020,9 @@ public static int Main()
// (18,9): error CS1017: Catch clauses cannot follow the general catch clause of a try statement
// catch when (false) {}
Diagnostic(ErrorCode.ERR_TooManyCatches, "catch").WithLocation(18, 9),
// (18,21): warning CS7095: Filter expression is a constant, consider removing the filter
// (18,21): warning CS8359: Filter expression is a constant 'false', consider removing the catch clause
// catch when (false) {}
Diagnostic(ErrorCode.WRN_FilterIsConstant, "false").WithLocation(18, 21));
Diagnostic(ErrorCode.WRN_FilterIsConstantFalse, "false").WithLocation(18, 21));
}
[Fact]
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册