未验证 提交 e33692c5 编写于 作者: J Jared Parsons 提交者: GitHub

Merge pull request #31457 from AlekseyTs/NullableContext_02

Split nullable context for types and for warnings.
......@@ -739,7 +739,7 @@ public override int GetHashCode()
internal override Diagnostic FilterDiagnostic(Diagnostic diagnostic)
{
return CSharpDiagnosticFilter.Filter(diagnostic, WarningLevel, GeneralDiagnosticOption, SpecificDiagnosticOptions);
return CSharpDiagnosticFilter.Filter(diagnostic, WarningLevel, Nullable, GeneralDiagnosticOption, SpecificDiagnosticOptions);
}
protected override CompilationOptions CommonWithModuleName(string moduleName)
......
......@@ -370,7 +370,7 @@ internal static bool IsPreprocessorSymbolDefined(this SyntaxTree tree, string sy
}
// Given the error code and the source location, get the warning state based on pragma warning directives.
internal static ReportDiagnostic GetPragmaDirectiveWarningState(this SyntaxTree tree, string id, int position)
internal static PragmaWarningState GetPragmaDirectiveWarningState(this SyntaxTree tree, string id, int position)
{
return ((CSharpSyntaxTree)tree).GetPragmaDirectiveWarningState(id, position);
}
......
......@@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Linq;
using Roslyn.Utilities;
......@@ -24,9 +25,10 @@ internal static class CSharpDiagnosticFilter
/// <param name="d">The input diagnostic</param>
/// <param name="warningLevelOption">The maximum warning level to allow. Diagnostics with a higher warning level will be filtered out.</param>
/// <param name="generalDiagnosticOption">How warning diagnostics should be reported</param>
/// <param name="nullableOption">Whether Nullable Reference Types feature is enabled globally</param>
/// <param name="specificDiagnosticOptions">How specific diagnostics should be reported</param>
/// <returns>A diagnostic updated to reflect the options, or null if it has been filtered out</returns>
public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiagnostic generalDiagnosticOption, IDictionary<string, ReportDiagnostic> specificDiagnosticOptions)
public static Diagnostic Filter(Diagnostic d, int warningLevelOption, bool nullableOption, ReportDiagnostic generalDiagnosticOption, IDictionary<string, ReportDiagnostic> specificDiagnosticOptions)
{
if (d == null)
{
......@@ -70,6 +72,7 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
d.Location as Location,
d.Category,
warningLevelOption,
nullableOption,
generalDiagnosticOption,
specificDiagnosticOptions,
out hasPragmaSuppression);
......@@ -77,7 +80,7 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
else
{
reportAction = GetDiagnosticReport(d.Severity, d.IsEnabledByDefault, d.Id, d.WarningLevel, d.Location as Location,
d.Category, warningLevelOption, generalDiagnosticOption, specificDiagnosticOptions, out hasPragmaSuppression);
d.Category, warningLevelOption, nullableOption, generalDiagnosticOption, specificDiagnosticOptions, out hasPragmaSuppression);
}
if (hasPragmaSuppression)
......@@ -98,6 +101,7 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
Location location,
string category,
int warningLevelOption,
bool nullableOption,
ReportDiagnostic generalDiagnosticOption,
IDictionary<string, ReportDiagnostic> specificDiagnosticOptions,
out bool hasPragmaSuppression)
......@@ -113,20 +117,69 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
}
// Compute if the reporting should be suppressed.
if (diagnosticWarningLevel > warningLevelOption // honor the warning level
|| report == ReportDiagnostic.Suppress) // check options (/nowarn)
if (diagnosticWarningLevel > warningLevelOption) // honor the warning level
{
return ReportDiagnostic.Suppress;
}
bool isNullableFlowAnalysisWarning = ErrorFacts.NullableFlowAnalysisWarnings.Contains(id);
if (report == ReportDiagnostic.Suppress && // check options (/nowarn)
!isNullableFlowAnalysisWarning)
{
return ReportDiagnostic.Suppress;
}
var pragmaWarningState = Syntax.PragmaWarningState.Default;
// If location is available, check out pragmas
if (location != null &&
location.SourceTree != null &&
((SyntaxTree)location.SourceTree).GetPragmaDirectiveWarningState(id, location.SourceSpan.Start) == ReportDiagnostic.Suppress)
(pragmaWarningState = location.SourceTree.GetPragmaDirectiveWarningState(id, location.SourceSpan.Start)) == Syntax.PragmaWarningState.Disabled)
{
hasPragmaSuppression = true;
}
if (pragmaWarningState == Syntax.PragmaWarningState.Enabled)
{
switch (report)
{
case ReportDiagnostic.Error:
case ReportDiagnostic.Hidden:
case ReportDiagnostic.Info:
case ReportDiagnostic.Warn:
// No need to adjust the current report state, it already means "enabled"
return report;
case ReportDiagnostic.Suppress:
// Enable the warning
return ReportDiagnostic.Default;
case ReportDiagnostic.Default:
if (generalDiagnosticOption == ReportDiagnostic.Error && promoteToAnError())
{
return ReportDiagnostic.Error;
}
return ReportDiagnostic.Default;
default:
throw ExceptionUtilities.UnexpectedValue(report);
}
}
else if (report == ReportDiagnostic.Suppress) // check options (/nowarn)
{
return ReportDiagnostic.Suppress;
}
// Nullable flow analysis warnings cannot be turned on by specific diagnostic options.
// They can be turned on by nullable options and specific diagnostic options
// can either turn them off, or adjust the way they are reported.
if (isNullableFlowAnalysisWarning && !nullableOption)
{
return ReportDiagnostic.Suppress;
}
// Unless specific warning options are defined (/warnaserror[+|-]:<n> or /nowarn:<n>,
// follow the global option (/warnaserror[+|-] or /nowarn).
if (report == ReportDiagnostic.Default)
......@@ -134,15 +187,9 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
switch (generalDiagnosticOption)
{
case ReportDiagnostic.Error:
// If we've been asked to do warn-as-error then don't raise severity for anything below warning (info or hidden).
if (severity == DiagnosticSeverity.Warning)
if (promoteToAnError())
{
// In the case where /warnaserror+ is followed by /warnaserror-:<n> on the command line,
// do not promote the warning specified in <n> to an error.
if (!isSpecified && (report == ReportDiagnostic.Default))
{
return ReportDiagnostic.Error;
}
return ReportDiagnostic.Error;
}
break;
case ReportDiagnostic.Suppress:
......@@ -160,6 +207,19 @@ public static Diagnostic Filter(Diagnostic d, int warningLevelOption, ReportDiag
}
return report;
bool promoteToAnError()
{
Debug.Assert(report == ReportDiagnostic.Default);
Debug.Assert(generalDiagnosticOption == ReportDiagnostic.Error);
// If we've been asked to do warn-as-error then don't raise severity for anything below warning (info or hidden).
return severity == DiagnosticSeverity.Warning &&
// In the case where /warnaserror+ is followed by /warnaserror-:<n> on the command line,
// do not promote the warning specified in <n> to an error.
!isSpecified;
}
}
}
}
......@@ -15,6 +15,38 @@ 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;
static ErrorFacts()
{
ImmutableHashSet<string>.Builder builder = ImmutableHashSet.CreateBuilder<string>();
builder.Add(getId(ErrorCode.WRN_ConvertingNullableToNonNullable));
builder.Add(getId(ErrorCode.WRN_NullReferenceAssignment));
builder.Add(getId(ErrorCode.WRN_NullReferenceReceiver));
builder.Add(getId(ErrorCode.WRN_NullReferenceReturn));
builder.Add(getId(ErrorCode.WRN_NullReferenceArgument));
builder.Add(getId(ErrorCode.WRN_UninitializedNonNullableField));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInAssignment));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInArgument));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInReturnTypeOfTargetDelegate));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInParameterTypeOfTargetDelegate));
builder.Add(getId(ErrorCode.WRN_NullAsNonNullable));
builder.Add(getId(ErrorCode.WRN_NoBestNullabilityConditionalExpression));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint));
builder.Add(getId(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint));
builder.Add(getId(ErrorCode.WRN_CantInferNullabilityOfMethodTypeArgs));
builder.Add(getId(ErrorCode.WRN_NoBestNullabilityArrayElements));
builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysFalse));
builder.Add(getId(ErrorCode.HDN_NullCheckIsProbablyAlwaysTrue));
builder.Add(getId(ErrorCode.HDN_ExpressionIsProbablyNeverNull));
NullableFlowAnalysisWarnings = builder.ToImmutable();
string getId(ErrorCode errorCode)
{
return MessageProvider.Instance.GetIdForErrorCode((int)errorCode);
}
}
private static ImmutableDictionary<ErrorCode, string> CreateHelpLinks()
{
......
......@@ -123,6 +123,7 @@ public override ReportDiagnostic GetDiagnosticReport(DiagnosticInfo diagnosticIn
Location.None,
diagnosticInfo.Category,
options.WarningLevel,
((CSharpCompilationOptions)options).Nullable,
options.GeneralDiagnosticOption,
options.SpecificDiagnosticOptions,
out hasPragmaSuppression);
......
......@@ -369,8 +369,7 @@ public static void Analyze(CSharpCompilation compilation, MethodSymbol member, B
walker.Free();
}
if (member.NonNullTypes == true &&
compilation.LanguageVersion >= MessageID.IDS_FeatureNullableReferenceTypes.RequiredVersion())
if (compilation.LanguageVersion >= MessageID.IDS_FeatureNullableReferenceTypes.RequiredVersion())
{
NullableWalker.Analyze(compilation, member, node, diagnostics);
}
......
......@@ -3502,7 +3502,7 @@ private bool HasTopLevelNullabilityConversion(TypeSymbolWithAnnotations source,
var resultType = TypeSymbolWithAnnotations.Create(targetType, resultAnnotation);
if (operandType.TypeSymbol?.IsErrorType() != true)
if (operandType.TypeSymbol?.IsErrorType() != true && !targetType.IsErrorType())
{
// Need to report all warnings that apply since the warnings can be suppressed individually.
if (reportTopLevelWarnings)
......
......@@ -28,7 +28,7 @@ internal static void Analyze(CSharpCompilation compilation, MethodSymbol method,
{
Debug.Assert(method.MethodKind == MethodKind.Constructor);
if (method.NonNullTypes != true)
if (compilation.LanguageVersion < MessageID.IDS_FeatureNullableReferenceTypes.RequiredVersion())
{
return;
}
......
// 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.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CodeAnalysis.Syntax;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
internal class CSharpPragmaWarningStateMap : AbstractWarningStateMap
/// <summary>
/// Describes how to report a warning diagnostic.
/// </summary>
internal enum PragmaWarningState : byte
{
/// <summary>
/// Report a diagnostic by default.
/// Either there is no corresponding #pragma, or the action is "restore".
/// </summary>
Default = 0,
/// <summary>
/// Diagnostic is enabled.
/// </summary>
Enabled = 1,
/// <summary>
/// Diagnostic is disabled.
/// </summary>
Disabled = 2,
}
internal class CSharpPragmaWarningStateMap : AbstractWarningStateMap<PragmaWarningState>
{
public CSharpPragmaWarningStateMap(SyntaxTree syntaxTree) :
base(syntaxTree)
......@@ -17,86 +42,141 @@ internal class CSharpPragmaWarningStateMap : AbstractWarningStateMap
protected override WarningStateMapEntry[] CreateWarningStateMapEntries(SyntaxTree syntaxTree)
{
// Accumulate all the pragma warning directives, in source code order
var directives = ArrayBuilder<PragmaWarningDirectiveTriviaSyntax>.GetInstance();
var directives = ArrayBuilder<DirectiveTriviaSyntax>.GetInstance();
GetAllPragmaWarningDirectives(syntaxTree, directives);
// Create the pragma warning map.
return CreatePragmaWarningStateEntries(directives.ToImmutableAndFree());
WarningStateMapEntry[] result = CreatePragmaWarningStateEntries(directives);
directives.Free();
return result;
}
// Add all active #pragma warn directives under trivia into the list, in source code order.
private static void GetAllPragmaWarningDirectives(SyntaxTree syntaxTree, ArrayBuilder<PragmaWarningDirectiveTriviaSyntax> directiveList)
// Add all active #pragma warn and #nullable directives under trivia into the list, in source code order.
private static void GetAllPragmaWarningDirectives(SyntaxTree syntaxTree, ArrayBuilder<DirectiveTriviaSyntax> directiveList)
{
foreach (var d in syntaxTree.GetRoot().GetDirectives())
{
if (d.Kind() == SyntaxKind.PragmaWarningDirectiveTrivia)
// Ignore directives inside disabled code (by #if and #endif)
if (!d.IsActive)
{
var w = (PragmaWarningDirectiveTriviaSyntax)d;
continue;
}
switch (d.Kind())
{
case SyntaxKind.PragmaWarningDirectiveTrivia:
var w = (PragmaWarningDirectiveTriviaSyntax)d;
// Ignore directives with errors (i.e., Unrecognized #pragma directive) and
// directives inside disabled code (by #if and #endif)
if (!w.DisableOrRestoreKeyword.IsMissing && !w.WarningKeyword.IsMissing && w.IsActive)
directiveList.Add(w);
// Ignore directives with errors (i.e., Unrecognized #pragma directive)
if (!w.DisableOrRestoreKeyword.IsMissing && !w.WarningKeyword.IsMissing)
{
directiveList.Add(w);
}
break;
case SyntaxKind.NullableDirectiveTrivia:
var nullableDirective = (NullableDirectiveTriviaSyntax)d;
// Ignore directives with errors (i.e., Unrecognized #nullable directive)
if (!nullableDirective.SettingToken.IsMissing)
{
directiveList.Add(nullableDirective);
}
break;
}
}
}
// Given the ordered list of all pragma warning directives in the syntax tree, return a list of mapping entries,
// Given the ordered list of all pragma warning and nullable directives in the syntax tree, return a list of mapping entries,
// containing the cumulative set of warnings that are disabled for that point in the source.
// This mapping also contains a global warning option, accumulated of all #pragma up to the current line position.
private static WarningStateMapEntry[] CreatePragmaWarningStateEntries(ImmutableArray<PragmaWarningDirectiveTriviaSyntax> directiveList)
private static WarningStateMapEntry[] CreatePragmaWarningStateEntries(ArrayBuilder<DirectiveTriviaSyntax> directiveList)
{
var entries = new WarningStateMapEntry[directiveList.Length + 1];
var current = new WarningStateMapEntry(0, ReportDiagnostic.Default, null);
var entries = new WarningStateMapEntry[directiveList.Count + 1];
var current = new WarningStateMapEntry(0, PragmaWarningState.Default, null);
var index = 0;
entries[index] = current;
// Captures the general reporting option, accumulated of all #pragma up to the current directive.
var accumulatedGeneralWarningState = ReportDiagnostic.Default;
var accumulatedGeneralWarningState = PragmaWarningState.Default;
// Captures the mapping of a warning number to the reporting option, accumulated of all #pragma up to the current directive.
var accumulatedSpecificWarningState = ImmutableDictionary.Create<string, ReportDiagnostic>();
var accumulatedSpecificWarningState = ImmutableDictionary.Create<string, PragmaWarningState>();
while (index < directiveList.Length)
while (index < directiveList.Count)
{
var currentDirective = directiveList[index];
// Compute the directive state (either Disable or Restore)
var directiveState = currentDirective.DisableOrRestoreKeyword.Kind() == SyntaxKind.DisableKeyword ? ReportDiagnostic.Suppress : ReportDiagnostic.Default;
// Check if this directive applies for all (e.g., #pragma warning disable)
if (currentDirective.ErrorCodes.Count == 0)
if (currentDirective.IsKind(SyntaxKind.PragmaWarningDirectiveTrivia))
{
// Update the warning state and reset the specific one
accumulatedGeneralWarningState = directiveState;
accumulatedSpecificWarningState = ImmutableDictionary.Create<string, ReportDiagnostic>();
var currentPragmaDirective = (PragmaWarningDirectiveTriviaSyntax)currentDirective;
// Compute the directive state (either Disable or Restore)
var directiveState = currentPragmaDirective.DisableOrRestoreKeyword.Kind() == SyntaxKind.DisableKeyword ? PragmaWarningState.Disabled : PragmaWarningState.Default;
// Check if this directive applies for all (e.g., #pragma warning disable)
if (currentPragmaDirective.ErrorCodes.Count == 0)
{
// Update the warning state and reset the specific one
accumulatedGeneralWarningState = directiveState;
accumulatedSpecificWarningState = ImmutableDictionary.Create<string, PragmaWarningState>();
}
else
{
// Compute warning numbers from the current directive's codes
for (int x = 0; x < currentPragmaDirective.ErrorCodes.Count; x++)
{
var currentErrorCode = currentPragmaDirective.ErrorCodes[x];
if (currentErrorCode.IsMissing || currentErrorCode.ContainsDiagnostics)
continue;
var errorId = string.Empty;
if (currentErrorCode.Kind() == SyntaxKind.NumericLiteralExpression)
{
var token = ((LiteralExpressionSyntax)currentErrorCode).Token;
errorId = MessageProvider.Instance.GetIdForErrorCode((int)token.Value);
}
else if (currentErrorCode.Kind() == SyntaxKind.IdentifierName)
{
errorId = ((IdentifierNameSyntax)currentErrorCode).Identifier.ValueText;
}
if (!string.IsNullOrWhiteSpace(errorId))
{
// Update the state of this error code with the current directive state
accumulatedSpecificWarningState = accumulatedSpecificWarningState.SetItem(errorId, directiveState);
}
}
}
}
else
{
// Compute warning numbers from the current directive's codes
for (int x = 0; x < currentDirective.ErrorCodes.Count; x++)
var currentNullableDirective = (NullableDirectiveTriviaSyntax)currentDirective;
PragmaWarningState directiveState;
switch (currentNullableDirective.SettingToken.Kind())
{
var currentErrorCode = currentDirective.ErrorCodes[x];
if (currentErrorCode.IsMissing || currentErrorCode.ContainsDiagnostics)
continue;
case SyntaxKind.DisableKeyword:
directiveState = PragmaWarningState.Disabled;
break;
case SyntaxKind.EnableKeyword:
directiveState = PragmaWarningState.Enabled;
break;
default:
throw ExceptionUtilities.UnexpectedValue(currentNullableDirective.SettingToken.Kind());
}
var errorId = string.Empty;
if (currentErrorCode.Kind() == SyntaxKind.NumericLiteralExpression)
{
var token = ((LiteralExpressionSyntax)currentErrorCode).Token;
errorId = MessageProvider.Instance.GetIdForErrorCode((int)token.Value);
}
else if (currentErrorCode.Kind() == SyntaxKind.IdentifierName)
{
errorId = ((IdentifierNameSyntax)currentErrorCode).Identifier.ValueText;
}
// Update the state of this error code with the current directive state
var builder = ArrayBuilder<KeyValuePair<string, PragmaWarningState>>.GetInstance(ErrorFacts.NullableFlowAnalysisWarnings.Count);
if (!string.IsNullOrWhiteSpace(errorId))
{
// Update the state of this error code with the current directive state
accumulatedSpecificWarningState = accumulatedSpecificWarningState.SetItem(errorId, directiveState);
}
foreach (string id in ErrorFacts.NullableFlowAnalysisWarnings)
{
builder.Add(new KeyValuePair<string, PragmaWarningState>(id, directiveState));
}
accumulatedSpecificWarningState = accumulatedSpecificWarningState.SetItems(builder);
builder.Free();
}
current = new WarningStateMapEntry(currentDirective.Location.SourceSpan.End, accumulatedGeneralWarningState, accumulatedSpecificWarningState);
......
......@@ -582,7 +582,7 @@ public override bool HasHiddenRegions()
/// </summary>
/// <param name="id">Error code.</param>
/// <param name="position">Source location.</param>
internal ReportDiagnostic GetPragmaDirectiveWarningState(string id, int position)
internal PragmaWarningState GetPragmaDirectiveWarningState(string id, int position)
{
if (_lazyPragmaWarningStateMap == null)
{
......
......@@ -49478,7 +49478,7 @@ public class B0<T> where T : A { }";
var source =
@"#pragma warning disable 0169
#pragma warning disable 8618
class B1<T> where T : A? { }
class B2<T> where T : A { }
......@@ -49515,13 +49515,10 @@ class D
B4<A> G10;
}";
var comp = CreateCompilation(new[] { source }, references: new[] { ref0 });
comp.VerifyDiagnostics(
comp.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_UninitializedNonNullableField).Verify(
// (4,24): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// class B1<T> where T : A? { }
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 24),
// (21,8): warning CS8631: The type 'A?' cannot be used as type parameter 'T' in the generic type or method 'B4<T>'. Nullability of type argument 'A?' doesn't match constraint type 'A'.
// B4<A?> F9; // 5 and 6
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A?").WithArguments("B4<T>", "A", "T", "A?").WithLocation(21, 8),
// (15,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// B1<A?> F3; // 2
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(15, 9),
......@@ -49555,7 +49552,7 @@ public class B0<T> where T : A<object> { }";
var source =
@"#pragma warning disable 0169
#pragma warning disable 8618
class B1<T> where T : A<object?> { }
class B2<T> where T : A<object> { }
......@@ -49592,7 +49589,7 @@ class D
B4<A<object>> G10;
}";
var comp = CreateCompilation(new[] { source }, references: new[] { ref0 });
comp.VerifyDiagnostics(
comp.GetDiagnostics().Where(d => d.Code != (int)ErrorCode.WRN_UninitializedNonNullableField).Verify(
// (4,31): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// class B1<T> where T : A<object?> { }
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(4, 31),
......@@ -49619,10 +49616,7 @@ class D
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object>").WithArguments("B3<T>", "A<object?>", "T", "A<object>").WithLocation(34, 8),
// (35,8): warning CS8631: The type 'A<object?>' cannot be used as type parameter 'T' in the generic type or method 'B4<T>'. Nullability of type argument 'A<object?>' doesn't match constraint type 'A<object>'.
// B4<A<object?>> G9; // 9
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object?>").WithArguments("B4<T>", "A<object>", "T", "A<object?>").WithLocation(35, 8),
// (21,8): warning CS8631: The type 'A<object?>' cannot be used as type parameter 'T' in the generic type or method 'B4<T>'. Nullability of type argument 'A<object?>' doesn't match constraint type 'A<object>'.
// B4<A<object?>> F9; // 5 and 6
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object?>").WithArguments("B4<T>", "A<object>", "T", "A<object?>").WithLocation(21, 8)
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "A<object?>").WithArguments("B4<T>", "A<object>", "T", "A<object?>").WithLocation(35, 8)
);
}
......@@ -50017,18 +50011,28 @@ static void Main()
// [NullNullTypes(true)]
comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue());
ref0 = comp0.EmitToImageReference();
comp = CreateCompilation(source, references: new[] { ref0 });
comp = CreateCompilation(source, references: new[] { ref0 });
comp.VerifyDiagnostics(
// (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// new A0<string?>(); // 1
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22),
// (9,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// new A5<string?>(); // 4
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 22)
);
verifyTypeParameterConstraint("A0", "System.IEquatable<T>");
verifyTypeParameterConstraint("A1", "System.IEquatable<T>");
verifyTypeParameterConstraint("A3", "System.IEquatable<T>");
verifyTypeParameterConstraint("A4", "System.IEquatable<T?>");
verifyTypeParameterConstraint("A5", "System.IEquatable<System.String?>");
verifyTypeParameterConstraint("A6", "System.IEquatable<System.Int32?>");
comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics(
// (5,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A0<T>'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable<string?>'.
// new A0<string?>(); // 1
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A0<T>", "System.IEquatable<string?>", "T", "string?").WithLocation(5, 16),
// (9,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// new A5<string?>(); // 4
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(9, 22),
// (9,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A5<T>'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable<string?>'.
// new A5<string?>(); // 4
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A5<T>", "System.IEquatable<string?>", "T", "string?").WithLocation(9, 16)
......@@ -50111,18 +50115,24 @@ static void Main()
// [NullNullTypes(true)]
comp0 = CreateCompilation(new[] { source0 }, options: WithNonNullTypesTrue());
ref0 = comp0.EmitToImageReference();
comp = CreateCompilation(source, references: new[] { ref0 });
// https://github.com/dotnet/roslyn/issues/30003: Should report a nullability mismatch warning for A2<string>().
comp.VerifyDiagnostics(
// (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// new A2<string?>(); // 2
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22)
);
verifyTypeParameterConstraint("A2", "System.IEquatable<T?>");
comp = CreateCompilation(source, references: new[] { ref0 }, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics(
// (5,16): warning CS8634: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. Nullability of type argument 'string?' doesn't match 'class' constraint.
// new A2<string?>(); // 2
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint, "string?").WithArguments("A2<T>", "T", "string?").WithLocation(5, 16),
// (5,16): warning CS8631: The type 'string?' cannot be used as type parameter 'T' in the generic type or method 'A2<T>'. Nullability of type argument 'string?' doesn't match constraint type 'System.IEquatable<string?>'.
// new A2<string?>(); // 2
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A2<T>", "System.IEquatable<string?>", "T", "string?").WithLocation(5, 16),
// (5,22): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// new A2<string?>(); // 2
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(5, 22)
Diagnostic(ErrorCode.WRN_NullabilityMismatchInTypeParameterConstraint, "string?").WithArguments("A2<T>", "System.IEquatable<string?>", "T", "string?").WithLocation(5, 16)
);
verifyTypeParameterConstraint("A2", "System.IEquatable<T?>");
......@@ -59696,6 +59706,750 @@ static void F(object o)
comp.VerifyTypes();
}
[Fact]
public void DiagnosticOptions_01()
{
var source =
@"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
private static void AssertDiagnosticOptions_01(string source)
{
string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable);
var source2 =
@"
partial class Program
{
#nullable enable
static void F(object o)
{
}
}";
var comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
foreach (ReportDiagnostic option in Enum.GetValues(typeof(ReportDiagnostic)))
{
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithSpecificDiagnosticOptions(id, option));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithGeneralDiagnosticOption(option));
comp.VerifyDiagnostics();
}
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue());
var diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithGeneralDiagnosticOption(ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error).
WithGeneralDiagnosticOption(ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Suppress));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
}
[Fact]
public void DiagnosticOptions_02()
{
var source =
@"
#pragma warning disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
private static void AssertDiagnosticOptions_02(string source)
{
string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable);
var source2 =
@"
partial class Program
{
#nullable enable
static void F(object o)
{
}
}";
var comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse());
comp.VerifyDiagnostics();
foreach (ReportDiagnostic option in Enum.GetValues(typeof(ReportDiagnostic)))
{
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithSpecificDiagnosticOptions(id, option));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesFalse().WithGeneralDiagnosticOption(option));
comp.VerifyDiagnostics();
}
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue());
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithGeneralDiagnosticOption(ReportDiagnostic.Default));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error).
WithGeneralDiagnosticOption(ReportDiagnostic.Default));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Suppress));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
comp.VerifyDiagnostics();
comp = CreateCompilation(new[] { source, source2 }, options: WithNonNullTypesTrue().
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
comp.VerifyDiagnostics();
}
[Fact]
public void DiagnosticOptions_03()
{
var source =
@"
#pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_04()
{
var source =
@"
#pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
[Fact]
public void DiagnosticOptions_05()
{
var source =
@"
#nullable disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_06()
{
var source =
@"
#nullable enable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_06(source);
}
private static void AssertDiagnosticOptions_06(string source)
{
var source2 =
@"
partial class Program
{
#nullable enable
static void F(object o)
{
}
}";
assertDiagnosticOptions(WithNonNullTypesTrue());
assertDiagnosticOptions(WithNonNullTypesFalse());
void assertDiagnosticOptions(CSharpCompilationOptions options)
{
string id = MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable);
var comp = CreateCompilation(new[] { source, source2 }, options: options);
var diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.WithGeneralDiagnosticOption(ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Error).
WithGeneralDiagnosticOption(ReportDiagnostic.Default));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): error CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null").WithWarningAsError(true)
);
Assert.Equal(DiagnosticSeverity.Error, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Suppress).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithGeneralDiagnosticOption(ReportDiagnostic.Suppress));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Hidden).
WithGeneralDiagnosticOption(ReportDiagnostic.Error));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): hidden CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Hidden, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
comp = CreateCompilation(new[] { source, source2 }, options: options.
WithSpecificDiagnosticOptions(id, ReportDiagnostic.Default).
WithGeneralDiagnosticOption(ReportDiagnostic.Hidden));
diagnostics = comp.GetDiagnostics();
diagnostics.Verify(
// (6,11): warning CS8625: Cannot convert null literal to non-nullable reference or unconstrained type parameter.
// F(null);
Diagnostic(ErrorCode.WRN_NullAsNonNullable, "null")
);
Assert.Equal(DiagnosticSeverity.Warning, diagnostics.Single().Severity);
}
}
[Fact]
public void DiagnosticOptions_07()
{
var source =
@"
#pragma warning disable
#nullable disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_08()
{
var source =
@"
#pragma warning disable
#nullable enable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_06(source);
}
[Fact]
public void DiagnosticOptions_09()
{
var source =
@"
#pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
#nullable disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_10()
{
var source =
@"
#pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
#nullable enable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_06(source);
}
[Fact]
public void DiagnosticOptions_11()
{
var source =
@"
#nullable disable
#pragma warning disable " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_12()
{
var source =
@"
#nullable disable
#pragma warning disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_13()
{
var source =
@"
#pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
#nullable disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_14()
{
var source =
@"
#pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
#nullable enable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_06(source);
}
[Fact]
public void DiagnosticOptions_15()
{
var source =
@"
#nullable disable
#pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
[Fact]
public void DiagnosticOptions_16()
{
var source =
@"
#pragma warning restore
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
[Fact]
public void DiagnosticOptions_17()
{
var source =
@"
#nullable disable
#pragma warning restore
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
[Fact]
public void DiagnosticOptions_18()
{
var source =
@"
#pragma warning restore
#nullable disable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_02(source);
}
[Fact]
public void DiagnosticOptions_19()
{
var source =
@"
#nullable enable
#pragma warning restore
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
[Fact]
public void DiagnosticOptions_20()
{
var source =
@"
#pragma warning restore
#nullable enable
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_06(source);
}
[Fact]
public void DiagnosticOptions_21()
{
var source =
@"
#nullable enable
#pragma warning restore " + MessageProvider.Instance.GetIdForErrorCode((int)ErrorCode.WRN_NullAsNonNullable) + @"
partial class Program
{
static void Test()
{
F(null);
}
}";
AssertDiagnosticOptions_01(source);
}
private readonly static NullableAnnotation[] s_AllNullableAnnotations = (NullableAnnotation[])Enum.GetValues(typeof(NullableAnnotation));
[Fact]
......@@ -5,6 +5,7 @@
using System.Globalization;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.Test.Utilities;
......@@ -2035,15 +2036,15 @@ public static void Main()
}
}";
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(text, path: "goo.cs");
Assert.Equal(ReportDiagnostic.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "public class").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "public static").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "public static").Start));
Assert.Equal(ReportDiagnostic.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int x").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int x").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int y").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int y").Start));
Assert.Equal(ReportDiagnostic.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int z").Start));
Assert.Equal(ReportDiagnostic.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int z").Start));
Assert.Equal(PragmaWarningState.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "public class").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "public static").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "public static").Start));
Assert.Equal(PragmaWarningState.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int x").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int x").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int y").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int y").Start));
Assert.Equal(PragmaWarningState.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "int z").Start));
Assert.Equal(PragmaWarningState.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "int z").Start));
}
[Fact]
......@@ -2064,9 +2065,9 @@ static void Main(string[] args)
}
}";
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(text, path: "goo.cs");
Assert.Equal(ReportDiagnostic.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "static void").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "var x").Start));
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "var y").Start));
Assert.Equal(PragmaWarningState.Default, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "static void").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "var x").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(219), GetSpanIn(syntaxTree, "var y").Start));
}
[WorkItem(545407, "http://vstfdevdiv:8080/DevDiv2/DevDiv/_workitems/edit/545407")]
......@@ -2082,7 +2083,7 @@ static void Main(string[] args)
}
}";
SyntaxTree syntaxTree = SyntaxFactory.ParseSyntaxTree(text, path: "goo.cs");
Assert.Equal(ReportDiagnostic.Suppress, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "static void").Start));
Assert.Equal(PragmaWarningState.Disabled, syntaxTree.GetPragmaDirectiveWarningState(MessageProvider.Instance.GetIdForErrorCode(168), GetSpanIn(syntaxTree, "static void").Start));
}
private TextSpan GetSpanIn(SyntaxTree syntaxTree, string textToFind)
......
......@@ -6,7 +6,7 @@
namespace Microsoft.CodeAnalysis.Syntax
{
internal abstract class AbstractWarningStateMap
internal abstract class AbstractWarningStateMap<WarningState>
{
/// <summary>
/// List of entries sorted in source order, each of which captures a
......@@ -31,11 +31,11 @@ protected AbstractWarningStateMap(SyntaxTree syntaxTree)
/// Returns the reporting state for the supplied diagnostic id at the supplied position
/// in the associated syntax tree.
/// </summary>
public ReportDiagnostic GetWarningState(string id, int position)
public WarningState GetWarningState(string id, int position)
{
var entry = GetEntryAtOrBeforePosition(position);
ReportDiagnostic state;
WarningState state;
if (entry.SpecificWarningOption.TryGetValue(id, out state))
{
return state;
......@@ -63,23 +63,23 @@ protected struct WarningStateMapEntry : IComparable<WarningStateMapEntry>
public readonly int Position;
// the general option applicable to all warnings, accumulated of all #pragma up to the current Line.
public readonly ReportDiagnostic GeneralWarningOption;
public readonly WarningState GeneralWarningOption;
// the mapping of the specific warning to the option, accumulated of all #pragma up to the current Line.
public readonly ImmutableDictionary<string, ReportDiagnostic> SpecificWarningOption;
public readonly ImmutableDictionary<string, WarningState> SpecificWarningOption;
public WarningStateMapEntry(int position)
{
this.Position = position;
this.GeneralWarningOption = ReportDiagnostic.Default;
this.SpecificWarningOption = ImmutableDictionary.Create<string, ReportDiagnostic>();
this.GeneralWarningOption = default;
this.SpecificWarningOption = ImmutableDictionary.Create<string, WarningState>();
}
public WarningStateMapEntry(int position, ReportDiagnostic general, ImmutableDictionary<string, ReportDiagnostic> specific)
public WarningStateMapEntry(int position, WarningState general, ImmutableDictionary<string, WarningState> specific)
{
this.Position = position;
this.GeneralWarningOption = general;
this.SpecificWarningOption = specific ?? ImmutableDictionary.Create<string, ReportDiagnostic>();
this.SpecificWarningOption = specific ?? ImmutableDictionary.Create<string, WarningState>();
}
public int CompareTo(WarningStateMapEntry other)
......
......@@ -2,6 +2,7 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis.Emit;
......@@ -109,6 +110,11 @@ internal static CSharpParseOptions WithExperimental(this CSharpParseOptions opti
return options.WithFeatures(options.Features.Concat(list));
}
public static CSharpCompilationOptions WithSpecificDiagnosticOptions(this CSharpCompilationOptions options, string key, ReportDiagnostic value)
{
return options.WithSpecificDiagnosticOptions(ImmutableDictionary<string, ReportDiagnostic>.Empty.Add(key, value));
}
}
}
......@@ -6,7 +6,7 @@ Imports Microsoft.CodeAnalysis.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.Syntax
Friend Class VisualBasicWarningStateMap
Inherits AbstractWarningStateMap
Inherits AbstractWarningStateMap(Of ReportDiagnostic)
Public Sub New(tree As SyntaxTree)
MyBase.New(tree)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册