未验证 提交 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,16 +187,10 @@ 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)
{
// 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))
if (promoteToAnError())
{
return ReportDiagnostic.Error;
}
}
break;
case ReportDiagnostic.Suppress:
// When doing suppress-all-warnings, don't lower severity for anything other than warning and info.
......@@ -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,66 +42,92 @@ 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)
{
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)
// 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];
if (currentDirective.IsKind(SyntaxKind.PragmaWarningDirectiveTrivia))
{
var currentPragmaDirective = (PragmaWarningDirectiveTriviaSyntax)currentDirective;
// Compute the directive state (either Disable or Restore)
var directiveState = currentDirective.DisableOrRestoreKeyword.Kind() == SyntaxKind.DisableKeyword ? ReportDiagnostic.Suppress : ReportDiagnostic.Default;
var directiveState = currentPragmaDirective.DisableOrRestoreKeyword.Kind() == SyntaxKind.DisableKeyword ? PragmaWarningState.Disabled : PragmaWarningState.Default;
// Check if this directive applies for all (e.g., #pragma warning disable)
if (currentDirective.ErrorCodes.Count == 0)
if (currentPragmaDirective.ErrorCodes.Count == 0)
{
// Update the warning state and reset the specific one
accumulatedGeneralWarningState = directiveState;
accumulatedSpecificWarningState = ImmutableDictionary.Create<string, ReportDiagnostic>();
accumulatedSpecificWarningState = ImmutableDictionary.Create<string, PragmaWarningState>();
}
else
{
// Compute warning numbers from the current directive's codes
for (int x = 0; x < currentDirective.ErrorCodes.Count; x++)
for (int x = 0; x < currentPragmaDirective.ErrorCodes.Count; x++)
{
var currentErrorCode = currentDirective.ErrorCodes[x];
var currentErrorCode = currentPragmaDirective.ErrorCodes[x];
if (currentErrorCode.IsMissing || currentErrorCode.ContainsDiagnostics)
continue;
......@@ -98,6 +149,35 @@ private static WarningStateMapEntry[] CreatePragmaWarningStateEntries(ImmutableA
}
}
}
}
else
{
var currentNullableDirective = (NullableDirectiveTriviaSyntax)currentDirective;
PragmaWarningState directiveState;
switch (currentNullableDirective.SettingToken.Kind())
{
case SyntaxKind.DisableKeyword:
directiveState = PragmaWarningState.Disabled;
break;
case SyntaxKind.EnableKeyword:
directiveState = PragmaWarningState.Enabled;
break;
default:
throw ExceptionUtilities.UnexpectedValue(currentNullableDirective.SettingToken.Kind());
}
// Update the state of this error code with the current directive state
var builder = ArrayBuilder<KeyValuePair<string, PragmaWarningState>>.GetInstance(ErrorFacts.NullableFlowAnalysisWarnings.Count);
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);
++index;
......
......@@ -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)
{
......
......@@ -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.
先完成此消息的编辑!
想要评论请 注册