未验证 提交 5010ecae 编写于 作者: R Rikki Gibson 提交者: GitHub

Let #nullable directive enable/disable all nullable-related warnings (#37242)

* Add all nullable-related warnings to ErrorFacts

* Fix test failures and add a bit more coverage
上级 fb93d210
......@@ -1919,7 +1919,7 @@ private static IEnumerable<string> ParseWarnings(string value)
{
if (string.Equals(id, "nullable", StringComparison.OrdinalIgnoreCase))
{
foreach (var errorCode in ErrorFacts.NullableFlowAnalysisWarnings)
foreach (var errorCode in ErrorFacts.NullableWarnings)
{
yield return errorCode;
}
......
......@@ -123,7 +123,7 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, NullableCo
var tree = location?.SourceTree as CSharpSyntaxTree;
var position = location.SourceSpan.Start;
bool isNullableFlowAnalysisWarning = ErrorFacts.NullableFlowAnalysisWarnings.Contains(id);
bool isNullableFlowAnalysisWarning = ErrorFacts.NullableWarnings.Contains(id);
if (isNullableFlowAnalysisWarning)
{
var nullableWarningsGloballyEnabled = nullableOption == NullableContextOptions.Enable || nullableOption == NullableContextOptions.Warnings;
......
......@@ -15,11 +15,12 @@ internal static partial class ErrorFacts
private const string s_descriptionSuffix = "_Description";
private static readonly Lazy<ImmutableDictionary<ErrorCode, string>> s_helpLinksMap = new Lazy<ImmutableDictionary<ErrorCode, string>>(CreateHelpLinks);
private static readonly Lazy<ImmutableDictionary<ErrorCode, string>> s_categoriesMap = new Lazy<ImmutableDictionary<ErrorCode, string>>(CreateCategoriesMap);
public static readonly ImmutableHashSet<string> NullableFlowAnalysisWarnings;
public static readonly ImmutableHashSet<string> NullableWarnings;
static ErrorFacts()
{
ImmutableHashSet<string>.Builder builder = ImmutableHashSet.CreateBuilder<string>();
builder.Add(getId(ErrorCode.WRN_NullReferenceAssignment));
builder.Add(getId(ErrorCode.WRN_NullReferenceReceiver));
builder.Add(getId(ErrorCode.WRN_NullReferenceReturn));
......@@ -47,7 +48,23 @@ static ErrorFacts()
builder.Add(getId(ErrorCode.WRN_ConvertingNullableToNonNullable));
builder.Add(getId(ErrorCode.WRN_DisallowNullAttributeForbidsMaybeNullAssignment));
NullableFlowAnalysisWarnings = builder.ToImmutable();
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeOnOverride));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnOverride));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnOverride));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnPartial));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeOnImplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeOnExplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnExplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnExplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInExplicitlyImplementedInterface));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInInterfaceImplementedByBase));
builder.Add(getId(ErrorCode.WRN_DuplicateInterfaceWithNullabilityMismatchInBaseList));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInConstraintsOnPartialImplementation));
NullableWarnings = builder.ToImmutable();
string getId(ErrorCode errorCode)
{
......
......@@ -1123,7 +1123,7 @@ private void ReportDiagnostic(ErrorCode errorCode, SyntaxNode syntaxNode, params
private void ReportDiagnostic(ErrorCode errorCode, Location location, params object[] arguments)
{
Debug.Assert(ErrorFacts.NullableFlowAnalysisWarnings.Contains(MessageProvider.Instance.GetIdForErrorCode((int)errorCode)));
Debug.Assert(ErrorFacts.NullableWarnings.Contains(MessageProvider.Instance.GetIdForErrorCode((int)errorCode)));
if (IsReachable() && !_disableDiagnostics)
{
Diagnostics.Add(errorCode, location, arguments);
......
......@@ -3134,9 +3134,9 @@ public void NoWarn_Nullable()
Assert.Empty(errors);
Assert.Equal(expected: ReportDiagnostic.Default, actual: arguments.CompilationOptions.GeneralDiagnosticOption);
Assert.Equal(expected: ErrorFacts.NullableFlowAnalysisWarnings.Count, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
Assert.Equal(expected: ErrorFacts.NullableWarnings.Count, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
foreach (string warning in ErrorFacts.NullableFlowAnalysisWarnings)
foreach (string warning in ErrorFacts.NullableWarnings)
{
Assert.Equal(expected: ReportDiagnostic.Suppress, actual: arguments.CompilationOptions.SpecificDiagnosticOptions[warning]);
}
......@@ -3162,9 +3162,9 @@ public void NoWarn_Nullable_Capitalization()
Assert.Empty(errors);
Assert.Equal(expected: ReportDiagnostic.Default, actual: arguments.CompilationOptions.GeneralDiagnosticOption);
Assert.Equal(expected: ErrorFacts.NullableFlowAnalysisWarnings.Count, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
Assert.Equal(expected: ErrorFacts.NullableWarnings.Count, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
foreach (string warning in ErrorFacts.NullableFlowAnalysisWarnings)
foreach (string warning in ErrorFacts.NullableWarnings)
{
Assert.Equal(expected: ReportDiagnostic.Suppress, actual: arguments.CompilationOptions.SpecificDiagnosticOptions[warning]);
}
......@@ -3190,9 +3190,9 @@ public void NoWarn_Nullable_MultipleArguments()
Assert.Empty(errors);
Assert.Equal(expected: ReportDiagnostic.Default, actual: arguments.CompilationOptions.GeneralDiagnosticOption);
Assert.Equal(expected: ErrorFacts.NullableFlowAnalysisWarnings.Count + 1, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
Assert.Equal(expected: ErrorFacts.NullableWarnings.Count + 1, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
foreach (string warning in ErrorFacts.NullableFlowAnalysisWarnings)
foreach (string warning in ErrorFacts.NullableWarnings)
{
Assert.Equal(expected: ReportDiagnostic.Suppress, actual: arguments.CompilationOptions.SpecificDiagnosticOptions[warning]);
}
......@@ -3220,9 +3220,9 @@ public void WarnAsError_Nullable()
Assert.Empty(errors);
Assert.Equal(expected: ReportDiagnostic.Default, actual: arguments.CompilationOptions.GeneralDiagnosticOption);
Assert.Equal(expected: 25, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
Assert.Equal(expected: ErrorFacts.NullableWarnings.Count, actual: arguments.CompilationOptions.SpecificDiagnosticOptions.Count);
foreach (string warning in ErrorFacts.NullableFlowAnalysisWarnings)
foreach (string warning in ErrorFacts.NullableWarnings)
{
Assert.Equal(expected: ReportDiagnostic.Error, actual: arguments.CompilationOptions.SpecificDiagnosticOptions[warning]);
}
......
......@@ -5588,6 +5588,103 @@ public partial class C
partial void M(string? s);
}
public partial class C
{
partial void M(string s) { }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_02()
{
var source = @"
using System.Collections.Generic;
#nullable enable annotations
class Base
{
internal virtual void M(List<string> list) { }
}
class Derived : Base
{
internal override void M(List<string?> list) { }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_03()
{
var source = @"
using System.Collections.Generic;
class Base
{
internal virtual void M(List<string> list) { }
}
#nullable enable annotations
class Derived : Base
{
internal override void M(List<string?> list) { }
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_04()
{
var source = @"
#nullable enable annotations
public interface I
{
void M(string? s);
}
public class C : I
{
public void M(string s) => throw null!;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_05()
{
var source = @"
#nullable enable annotations
public interface I
{
string M();
}
public class C : I
{
public string? M() => throw null!;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Enable_NonFlowAnalysisWarning_01()
{
var source = @"
#nullable enable
public partial class C
{
partial void M(string? s);
}
public partial class C
{
partial void M(string s) { }
......@@ -5601,11 +5698,11 @@ public partial class C
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_02()
public void Directive_Enable_NonFlowAnalysisWarning_02()
{
var source = @"
using System.Collections.Generic;
#nullable enable annotations
#nullable enable
class Base
{
internal virtual void M(List<string> list) { }
......@@ -5624,7 +5721,7 @@ class Derived : Base
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Annotations_NonFlowAnalysisWarning_03()
public void Directive_Enable_NonFlowAnalysisWarning_03()
{
var source = @"
using System.Collections.Generic;
......@@ -5633,7 +5730,7 @@ class Base
internal virtual void M(List<string> list) { }
}
#nullable enable annotations
#nullable enable
class Derived : Base
{
// No warning because the base method's parameter type is oblivious
......@@ -5644,6 +5741,52 @@ class Derived : Base
comp.VerifyDiagnostics();
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Enable_NonFlowAnalysisWarning_04()
{
var source = @"
#nullable enable
public interface I
{
void M(string? s);
}
public class C : I
{
public void M(string s) => throw null!;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,17): warning CS8614: Nullability of reference types in type of parameter 's' of 'void C.M(string s)' doesn't match implicitly implemented member 'void I.M(string? s)'.
// public void M(string s) => throw null!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInParameterTypeOnImplicitImplementation, "M").WithArguments("s", "void C.M(string s)", "void I.M(string? s)").WithLocation(10, 17)
);
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Enable_NonFlowAnalysisWarning_05()
{
var source = @"
#nullable enable
public interface I
{
string M();
}
public class C : I
{
public string? M() => throw null!;
}
";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (10,20): warning CS8613: Nullability of reference types in return type of 'string? C.M()' doesn't match implicitly implemented member 'string I.M()'.
// public string? M() => throw null!;
Diagnostic(ErrorCode.WRN_NullabilityMismatchInReturnTypeOnImplicitImplementation, "M").WithArguments("string? C.M()", "string I.M()").WithLocation(10, 20)
);
}
[Fact, WorkItem(35748, "https://github.com/dotnet/roslyn/issues/35748")]
public void Directive_Warnings_Enable_01()
{
......@@ -11880,17 +12023,17 @@ abstract class A
class B1 : A
{
#nullable disable
#nullable disable annotations
public override event System.Action<string?> E1 {add {} remove{}} // 1
#nullable disable
#nullable disable annotations
public override event System.Action<string> E2 {add {} remove{}}
}
#nullable enable
class B2 : A
{
#nullable disable
#nullable disable annotations
public override event System.Action<string?> E1; // 3
#nullable disable
#nullable disable annotations
public override event System.Action<string> E2;
#nullable enable
void Dummy()
......@@ -12530,13 +12673,13 @@ abstract class A
class B : A
{
#nullable disable
#nullable disable annotations
public override string?[] M1()
{
return new string?[] {};
}
#nullable disable
#nullable disable annotations
public override S?[] M2<S>()
{
return new S?[] {};
......@@ -12732,13 +12875,13 @@ interface IA
class B : IA
{
#nullable disable
#nullable disable annotations
string?[] IA.M1()
{
return new string?[] {};
}
#nullable disable
#nullable disable annotations
S?[] IA.M2<S>()
{
return new S?[] {};
......@@ -12791,13 +12934,13 @@ interface IA
class B : IA
{
#nullable disable
#nullable disable annotations
string?[] IA.M1()
{
return new string?[] {};
}
#nullable disable
#nullable disable annotations
S?[] IA.M2<S>() where S : class
{
return new S?[] {};
......@@ -13348,13 +13491,13 @@ abstract class A
class B : A
{
#nullable disable
#nullable disable annotations
public override string?[] M1()
{
return new string?[] {};
}
#nullable disable
#nullable disable annotations
public override S?[] M2<S>() where S : class
{
return new S?[] {};
......@@ -69528,7 +69671,7 @@ void symbolValidator(ModuleSymbol m)
comp2.VerifyDiagnostics(
);
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() });
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }, options: WithNonNullTypes(NullableContextOptions.Warnings));
comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(
// (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2<T22>()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2<T2>()'. Consider using an explicit interface implementation instead.
// public void F2<T22>() where T22 : class?
......@@ -70216,7 +70359,7 @@ void symbolValidator(ModuleSymbol m)
comp2.VerifyDiagnostics(
);
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() });
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }, options: WithNonNullTypes(NullableContextOptions.Warnings));
comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(
// (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2<T22>()' doesn't match the constraints for type parameter 'T2' of interface method 'IA<string>.F2<T2>()'. Consider using an explicit interface implementation instead.
// public void F2<T22>() where T22 : class?
......@@ -70993,7 +71136,7 @@ void symbolValidator1(ModuleSymbol m)
comp2.VerifyDiagnostics(
);
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() });
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }, options: WithNonNullTypes(NullableContextOptions.Warnings));
comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(
// (8,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2<T22>()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2<T2>()'. Consider using an explicit interface implementation instead.
// public void F2<T22>() where T22 : class?, IB?
......@@ -71112,7 +71255,7 @@ void symbolValidator1(ModuleSymbol m)
comp2.VerifyDiagnostics(
);
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() });
var comp3 = CreateCompilation(new[] { source2 }, references: new[] { comp2.ToMetadataReference() }, options: WithNonNullTypes(NullableContextOptions.Warnings));
comp3.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_MissingNonNullTypesContextForAnnotation).Verify(
// (4,17): warning CS8633: Nullability in constraints for type parameter 'T22' of method 'B.F2<T22>()' doesn't match the constraints for type parameter 'T2' of interface method 'IA.F2<T2>()'. Consider using an explicit interface implementation instead.
// public void F2<T22>() where T22 : class?, IB?
......@@ -30565,7 +30565,7 @@ public interface I3 : I1<string?>
";
var source2 =
@"
@"#nullable enable warnings
class Test1 : I2, I3
{
}
......@@ -30631,7 +30631,6 @@ public void MethodImplementationInDerived_16()
var source1 =
@"
#nullable enable
public interface I1<T>
{
void M1();
......@@ -30653,7 +30652,7 @@ public interface I3 : I1<string?>
";
var source2 =
@"
@"#nullable enable warnings
class Test1 : I2, I3, I1<string>
{
}
......@@ -323,6 +323,38 @@ public void WarningLevel_2()
}
}
[Fact]
public void NullableWarnings()
{
foreach (ErrorCode error in Enum.GetValues(typeof(ErrorCode)))
{
if ((int)error < 8600 || (int)error >= 9000)
{
continue;
}
if (!error.ToString().StartsWith("WRN"))
{
// Only interested in warnings
continue;
}
if (ErrorFacts.NullableWarnings.Contains(MessageProvider.Instance.GetIdForErrorCode((int)error)))
{
continue;
}
// Nullable-unrelated warnings in the C# 8 range should be added to this array.
var nullableUnrelatedWarnings = new[]
{
ErrorCode.WRN_MissingNonNullTypesContextForAnnotation,
ErrorCode.WRN_ImplicitCopyInReadOnlyMember,
};
Assert.Contains(error, nullableUnrelatedWarnings);
}
}
[Fact]
public void Warning_1()
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册