未验证 提交 75ceb398 编写于 作者: C Charles Stoner 提交者: GitHub

Use #nonnull directive to determine NonNullTypes context (#30499)

上级 695db84a
......@@ -84,8 +84,12 @@ private BoundExpression BindAnonymousObjectCreation(AnonymousObjectCreationExpre
// build anonymous type field descriptor
fieldSyntaxNodes[i] = (nameToken.Kind() == SyntaxKind.IdentifierToken) ? (CSharpSyntaxNode)nameToken.Parent : fieldInitializer;
fields[i] = new AnonymousTypeField(fieldName == null ? "$" + i.ToString() : fieldName, fieldSyntaxNodes[i].Location,
TypeSymbolWithAnnotations.Create(fieldType, isNullableIfReferenceType: node.IsFeatureStaticNullCheckingEnabled()));
// https://github.com/dotnet/roslyn/issues/24018: Initial binding should set IsNullable = null.
bool? isNullableIfReferenceType = ((CSharpParseOptions)node.SyntaxTree?.Options)?.IsFeatureEnabled(MessageID.IDS_FeatureStaticNullChecking) == true;
fields[i] = new AnonymousTypeField(
fieldName == null ? "$" + i.ToString() : fieldName,
fieldSyntaxNodes[i].Location,
TypeSymbolWithAnnotations.Create(fieldType, isNullableIfReferenceType));
// NOTE: ERR_InvalidAnonymousTypeMemberDeclarator (CS0746) would be generated by parser if needed
}
......
......@@ -7261,6 +7261,15 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Expected disable or restore.
/// </summary>
internal static string ERR_NonNullDirectiveQualifierExpected {
get {
return ResourceManager.GetString("ERR_NonNullDirectiveQualifierExpected", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to A void or int returning entry point cannot be async.
/// </summary>
......@@ -14990,24 +14999,6 @@ internal class CSharpResources {
}
}
/// <summary>
/// Looks up a localized string similar to Non-null reference types are off..
/// </summary>
internal static string WRN_PragmaNonNullTypes {
get {
return ResourceManager.GetString("WRN_PragmaNonNullTypes", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to Non-null reference types are off..
/// </summary>
internal static string WRN_PragmaNonNullTypes_Title {
get {
return ResourceManager.GetString("WRN_PragmaNonNullTypes_Title", resourceCulture);
}
}
/// <summary>
/// Looks up a localized string similar to &apos;{0}&apos;: new protected member declared in sealed class.
/// </summary>
......
......@@ -5580,12 +5580,6 @@ To remove the warning, you can use /reference instead (set the Embed Interop Typ
<data name="ERR_ExplicitNonNullTypesAttribute" xml:space="preserve">
<value>Explicit application of 'System.Runtime.CompilerServices.NonNullTypesAttribute' is not allowed.</value>
</data>
<data name="WRN_PragmaNonNullTypes" xml:space="preserve">
<value>Non-null reference types are off.</value>
</data>
<data name="WRN_PragmaNonNullTypes_Title" xml:space="preserve">
<value>Non-null reference types are off.</value>
</data>
<data name="ERR_NonNullDirectiveQualifierExpected" xml:space="preserve">
<value>Expected disable or restore</value>
</data>
......
......@@ -1620,9 +1620,8 @@ internal enum ErrorCode
WRN_MissingNonNullTypesContextForAnnotation = 8632,
WRN_NullabilityMismatchInConstraintsOnImplicitImplementation = 8633,
WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint = 8634,
ERR_ExplicitNonNullTypesAttribute = 8635,
WRN_PragmaNonNullTypes = 8636, // PROTOTYPE(NullableReferenceTypes): Remove this fake warning once we have full support for new directive.
//ERR_TripleDotNotAllowed = 8635,
ERR_ExplicitNonNullTypesAttribute = 8636,
ERR_NonNullDirectiveQualifierExpected = 8637,
#endregion diagnostics introduced for C# 8.0
......
......@@ -353,7 +353,6 @@ internal static int GetWarningLevel(ErrorCode code)
case ErrorCode.WRN_MissingNonNullTypesContextForAnnotation:
case ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation:
case ErrorCode.WRN_SuppressionOperatorNotReferenceType:
case ErrorCode.WRN_PragmaNonNullTypes:
return 1;
default:
return 0;
......
......@@ -209,7 +209,6 @@ public static bool IsWarning(ErrorCode code)
case ErrorCode.WRN_MissingNonNullTypesContextForAnnotation:
case ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation:
case ErrorCode.WRN_NullabilityMismatchInTypeParameterReferenceTypeConstraint:
case ErrorCode.WRN_PragmaNonNullTypes:
return true;
default:
return false;
......
......@@ -101,7 +101,7 @@ Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax.WithEndQuoteToken(Micros
Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax.WithEqualsToken(Microsoft.CodeAnalysis.SyntaxToken equalsToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax.WithName(Microsoft.CodeAnalysis.CSharp.Syntax.XmlNameSyntax name) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax
Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax.WithStartQuoteToken(Microsoft.CodeAnalysis.SyntaxToken startQuoteToken) -> Microsoft.CodeAnalysis.CSharp.Syntax.XmlAttributeSyntax
Microsoft.CodeAnalysis.CSharp.SyntaxKind.NonNullDirectiveTrivia = 9056 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.NonNullDirectiveTrivia = 9055 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.NonNullKeyword = 8486 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
Microsoft.CodeAnalysis.CSharp.SyntaxKind.SuppressNullableWarningExpression = 9054 -> Microsoft.CodeAnalysis.CSharp.SyntaxKind
override Microsoft.CodeAnalysis.CSharp.CSharpCompilation.ClassifyCommonConversion(Microsoft.CodeAnalysis.ITypeSymbol source, Microsoft.CodeAnalysis.ITypeSymbol destination) -> Microsoft.CodeAnalysis.Operations.CommonConversion
......
......@@ -867,29 +867,24 @@ public virtual bool HasUnsupportedMetadata
internal bool? GetNonNullTypesFromSyntax()
{
bool? result = null;
string id = "CS" + ((int)ErrorCode.WRN_PragmaNonNullTypes).ToString("0000");
foreach (Location location in Locations)
{
SyntaxTree tree = location.SourceTree;
if (tree != null)
if (tree == null)
{
ReportDiagnostic? state = ((CSharpSyntaxTree)tree).GetPragmaDirectiveSpecificWarningState(id, location.SourceSpan.Start);
if (state.HasValue)
{
if (state.GetValueOrDefault() == ReportDiagnostic.Suppress)
{
result = false;
}
else
{
return true;
}
}
continue;
}
bool? state = ((CSharpSyntaxTree)tree).GetNonNullDirectiveState(location.SourceSpan.Start);
if (state == null)
{
continue;
}
if (state == true)
{
return true;
}
result = false;
}
return result;
}
......
......@@ -593,20 +593,24 @@ internal ReportDiagnostic GetPragmaDirectiveWarningState(string id, int position
return _lazyPragmaWarningStateMap.GetWarningState(id, position);
}
internal ReportDiagnostic? GetPragmaDirectiveSpecificWarningState(string id, int position)
/// <summary>
/// Returns true if the `#nonnull` directive preceding the position is
/// `restore`, false if `disable`, and null if no preceding directive.
/// </summary>
internal bool? GetNonNullDirectiveState(int position)
{
if (_lazyPragmaWarningStateMap == null)
if (_lazyNonNullDirectiveMap == null)
{
// Create the warning state map on demand.
Interlocked.CompareExchange(ref _lazyPragmaWarningStateMap, new CSharpPragmaWarningStateMap(this), null);
// Create the #nonnull directive map on demand.
Interlocked.CompareExchange(ref _lazyNonNullDirectiveMap, NonNullDirectiveMap.Create(this), null);
}
return _lazyPragmaWarningStateMap.GetSpecificWarningState(id, position);
return _lazyNonNullDirectiveMap.GetDirectiveState(position);
}
private CSharpLineDirectiveMap _lazyLineDirectiveMap;
private CSharpPragmaWarningStateMap _lazyPragmaWarningStateMap;
private NonNullDirectiveMap _lazyNonNullDirectiveMap;
private LinePosition GetLinePosition(int position)
{
......
// 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;
namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
internal sealed class NonNullDirectiveMap
{
private static readonly NonNullDirectiveMap Empty = new NonNullDirectiveMap(ImmutableArray<(int Position, bool State)>.Empty);
private readonly ImmutableArray<(int Position, bool State)> _directives;
internal static NonNullDirectiveMap Create(SyntaxTree tree)
{
var directives = GetDirectives(tree);
return directives.IsEmpty ? Empty : new NonNullDirectiveMap(directives);
}
private NonNullDirectiveMap(ImmutableArray<(int Position, bool State)> directives)
{
#if DEBUG
for (int i = 1; i < directives.Length; i++)
{
Debug.Assert(directives[i - 1].Position < directives[i].Position);
}
#endif
_directives = directives;
}
/// <summary>
/// Returns true if the `#nonnull` directive preceding the position is
/// `restore`, false if `disable`, and null if no preceding directive.
/// </summary>
internal bool? GetDirectiveState(int position)
{
int index = _directives.BinarySearch((position, false), PositionComparer.Instance);
if (index < 0)
{
// If no exact match, BinarySearch returns the complement
// of the index of the next higher value.
index = ~index - 1;
}
if (index < 0)
{
return null;
}
Debug.Assert(_directives[index].Position <= position);
Debug.Assert(index == _directives.Length - 1 || position < _directives[index + 1].Position);
return _directives[index].State;
}
private static ImmutableArray<(int Position, bool State)> GetDirectives(SyntaxTree tree)
{
var builder = ArrayBuilder<(int Position, bool State)>.GetInstance();
foreach (var d in tree.GetRoot().GetDirectives())
{
if (d.Kind() != SyntaxKind.NonNullDirectiveTrivia)
{
continue;
}
var nn = (NonNullDirectiveTriviaSyntax)d;
if (nn.DisableOrRestoreKeyword.IsMissing || !nn.IsActive)
{
continue;
}
builder.Add((nn.Location.SourceSpan.End, nn.DisableOrRestoreKeyword.Kind() == SyntaxKind.RestoreKeyword));
}
return builder.ToImmutableAndFree();
}
private sealed class PositionComparer : IComparer<(int Position, bool State)>
{
internal static readonly PositionComparer Instance = new PositionComparer();
public int Compare((int Position, bool State) x, (int Position, bool State) y)
{
return x.Position.CompareTo(y.Position);
}
}
}
}
......@@ -387,10 +387,5 @@ internal static bool IsOutVarDeclaration(this DeclarationExpressionSyntax p)
{
return p.Designation.Kind() == SyntaxKind.SingleVariableDesignation && p.IsOutDeclaration();
}
internal static bool IsFeatureStaticNullCheckingEnabled(this CSharpSyntaxNode node)
{
return ((CSharpParseOptions)node.SyntaxTree?.Options)?.IsFeatureEnabled(MessageID.IDS_FeatureStaticNullChecking) == true;
}
}
}
......@@ -570,6 +570,6 @@ public enum SyntaxKind : ushort
ThrowExpression = 9052,
ImplicitStackAllocArrayCreationExpression = 9053,
SuppressNullableWarningExpression = 9054,
NonNullDirectiveTrivia = 9056,
NonNullDirectiveTrivia = 9055,
}
}
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -507,16 +507,6 @@
<target state="new">The type cannot be used as type parameter in the generic type or method. Nullability of type argument doesn't match 'class' constraint.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_PragmaNonNullTypes_Title">
<source>Non-null reference types are off.</source>
<target state="new">Non-null reference types are off.</target>
<note />
</trans-unit>
<trans-unit id="WRN_SuppressionOperatorNotReferenceType">
<source>The suppression operator (!) can only be applied to reference types.</source>
<target state="new">The suppression operator (!) can only be applied to reference types.</target>
......
......@@ -286,7 +286,6 @@ public void WarningLevel_2()
case ErrorCode.WRN_MissingNonNullTypesContextForAnnotation:
case ErrorCode.WRN_NullabilityMismatchInConstraintsOnImplicitImplementation:
case ErrorCode.WRN_SuppressionOperatorNotReferenceType:
case ErrorCode.WRN_PragmaNonNullTypes:
Assert.Equal(1, ErrorFacts.GetWarningLevel(errorCode));
break;
case ErrorCode.WRN_InvalidVersionFormat:
......
......@@ -44,19 +44,6 @@ public ReportDiagnostic GetWarningState(string id, int position)
return entry.GeneralWarningOption;
}
public ReportDiagnostic? GetSpecificWarningState(string id, int position)
{
var entry = GetEntryAtOrBeforePosition(position);
ReportDiagnostic state;
if (entry.SpecificWarningOption.TryGetValue(id, out state))
{
return state;
}
return null;
}
/// <summary>
/// Gets the entry with the largest position less than or equal to supplied position.
/// </summary>
......
......@@ -122,12 +122,12 @@ protected static CSharpCompilationOptions WithNonNullTypesFalse(CSharpCompilatio
protected static string NonNullTypesOff()
{
return $"#pragma warning disable {(int)ErrorCode.WRN_PragmaNonNullTypes}";
return "#nonnull disable";
}
internal static string NonNullTypesOn()
{
return $"#pragma warning restore {(int)ErrorCode.WRN_PragmaNonNullTypes}";
return "#nonnull restore";
}
internal CompilationVerifier CompileAndVerifyWithMscorlib40(
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册