提交 3ea086b8 编写于 作者: C Charles Stoner 提交者: Andy Gocke

Use NullableAnnotation.NotAnnotated for value types (#37431)

Use NullableAnnotation.NotAnnotated always for value type annotations in the public API.

Previously, the annotation was NotAnnotated if the type reference was from source and Disabled if the type reference was from metadata.

Fixes #34412
上级 8c047836
......@@ -300,8 +300,7 @@ private void SetAnalyzedNullability(BoundExpression expr, VisitResult result, bo
}
}
#endif
_analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.NullableAnnotation.ToPublicAnnotation(),
result.RValueType.State.ToPublicFlowState()),
_analyzedNullabilityMapOpt[expr] = (new NullabilityInfo(result.LValueType.ToPublicAnnotation(), result.RValueType.State.ToPublicFlowState()),
// https://github.com/dotnet/roslyn/issues/35046 We're dropping the result if the type doesn't match up completely
// with the existing type
expr.Type?.Equals(result.RValueType.Type, TypeCompareKind.AllIgnoreOptions) == true ? result.RValueType.Type : expr.Type);
......
......@@ -195,7 +195,7 @@ public static class SymbolDisplay
bool minimal)
{
// https://github.com/dotnet/roslyn/issues/35035: Refactor this. We need to be able to handle non-TypeSymbol inputs
var annotation = (CodeAnalysis.NullableAnnotation?)TypeWithState.Create((TypeSymbol)symbol, nullableFlowState.ToInternalFlowState()).ToTypeWithAnnotations().NullableAnnotation.ToPublicAnnotation();
var annotation = (CodeAnalysis.NullableAnnotation?)TypeWithState.Create((TypeSymbol)symbol, nullableFlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToPublicAnnotation();
return ToDisplayParts(symbol, annotation, semanticModelOpt, positionOpt, format, minimal);
}
......
......@@ -477,7 +477,7 @@ ITypeSymbol IArrayTypeSymbol.ElementType
CodeAnalysis.NullableAnnotation IArrayTypeSymbol.ElementNullableAnnotation
{
get => ElementTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
get => ElementTypeWithAnnotations.ToPublicAnnotation();
}
ImmutableArray<CustomModifier> IArrayTypeSymbol.CustomModifiers
......
......@@ -351,7 +351,7 @@ ITypeSymbol IEventSymbol.Type
}
}
CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IEventSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
IMethodSymbol IEventSymbol.AddMethod
{
......
......@@ -467,7 +467,7 @@ ITypeSymbol IFieldSymbol.Type
}
}
CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IFieldSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IFieldSymbol.CustomModifiers
{
......
......@@ -372,7 +372,7 @@ ITypeSymbol ILocalSymbol.Type
}
}
CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation ILocalSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
bool ILocalSymbol.IsFunctionValue
{
......
......@@ -1038,7 +1038,7 @@ ITypeSymbol IMethodSymbol.ReturnType
}
}
CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IMethodSymbol.ReturnNullableAnnotation => ReturnTypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments
{
......@@ -1048,7 +1048,8 @@ ImmutableArray<ITypeSymbol> IMethodSymbol.TypeArguments
}
}
ImmutableArray<CodeAnalysis.NullableAnnotation> IMethodSymbol.TypeArgumentNullableAnnotations => TypeArgumentsWithAnnotations.SelectAsArray(arg => arg.NullableAnnotation.ToPublicAnnotation());
ImmutableArray<CodeAnalysis.NullableAnnotation> IMethodSymbol.TypeArgumentNullableAnnotations =>
TypeArgumentsWithAnnotations.SelectAsArray(arg => arg.ToPublicAnnotation());
ImmutableArray<ITypeParameterSymbol> IMethodSymbol.TypeParameters
{
......
......@@ -1582,10 +1582,8 @@ ImmutableArray<ITypeSymbol> INamedTypeSymbol.TypeArguments
}
}
ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations
{
get => this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.NullableAnnotation.ToPublicAnnotation());
}
ImmutableArray<CodeAnalysis.NullableAnnotation> INamedTypeSymbol.TypeArgumentNullableAnnotations =>
this.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.SelectAsArray(a => a.ToPublicAnnotation());
ImmutableArray<CustomModifier> INamedTypeSymbol.GetTypeArgumentCustomModifiers(int ordinal)
{
......
......@@ -81,15 +81,21 @@ internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnno
internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type)
{
var flowState = TypeWithAnnotations.Create(type, annotation).ToTypeWithState().State;
return new NullabilityInfo(annotation.ToPublicAnnotation(), flowState.ToPublicFlowState());
return new NullabilityInfo(ToPublicAnnotation(type, annotation), flowState.ToPublicFlowState());
}
internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this CSharp.NullableAnnotation annotation) =>
internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this TypeWithAnnotations type) =>
ToPublicAnnotation(type.Type, type.NullableAnnotation);
private static CodeAnalysis.NullableAnnotation ToPublicAnnotation(TypeSymbol type, NullableAnnotation annotation) =>
annotation switch
{
CSharp.NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated,
CSharp.NullableAnnotation.NotAnnotated => CodeAnalysis.NullableAnnotation.NotAnnotated,
CSharp.NullableAnnotation.Oblivious => CodeAnalysis.NullableAnnotation.Disabled,
// A value type may be oblivious or not annotated depending on whether the type reference
// is from source or metadata. (Binding using the #nullable context only when setting the annotation
// to avoid checking IsValueType early.) The annotation is normalized here in the public API.
CSharp.NullableAnnotation.Oblivious => type.IsValueType ? CodeAnalysis.NullableAnnotation.NotAnnotated : CodeAnalysis.NullableAnnotation.Disabled,
_ => throw ExceptionUtilities.UnexpectedValue(annotation)
};
......
......@@ -412,7 +412,7 @@ ITypeSymbol IParameterSymbol.Type
get { return this.Type; }
}
CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IParameterSymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<CustomModifier> IParameterSymbol.CustomModifiers
{
......
......@@ -433,7 +433,7 @@ ITypeSymbol IPropertySymbol.Type
get { return this.Type; }
}
CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
CodeAnalysis.NullableAnnotation IPropertySymbol.NullableAnnotation => TypeWithAnnotations.ToPublicAnnotation();
ImmutableArray<IParameterSymbol> IPropertySymbol.Parameters
{
......
......@@ -183,7 +183,7 @@ public override TypeSymbol ReceiverType
}
protected override CodeAnalysis.NullableAnnotation ReceiverNullableAnnotation =>
_reducedFrom.Parameters[0].TypeWithAnnotations.NullableAnnotation.ToPublicAnnotation();
_reducedFrom.Parameters[0].TypeWithAnnotations.ToPublicAnnotation();
public override TypeSymbol GetTypeInferredDuringReduction(TypeParameterSymbol reducedFromTypeParameter)
{
......
......@@ -716,10 +716,8 @@ ImmutableArray<ITypeSymbol> ITypeParameterSymbol.ConstraintTypes
}
}
ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations
{
get => this.ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.NullableAnnotation.ToPublicAnnotation());
}
ImmutableArray<CodeAnalysis.NullableAnnotation> ITypeParameterSymbol.ConstraintNullableAnnotations =>
ConstraintTypesNoUseSiteDiagnostics.SelectAsArray(c => c.ToPublicAnnotation());
ITypeParameterSymbol ITypeParameterSymbol.OriginalDefinition
{
......
......@@ -43,7 +43,7 @@ internal Boxed(TypeWithAnnotations value)
private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableAnnotation, Extensions extensions)
{
Debug.Assert(defaultType?.IsNullableType() != true || (nullableAnnotation != NullableAnnotation.Oblivious && nullableAnnotation != NullableAnnotation.NotAnnotated));
Debug.Assert(defaultType?.IsNullableType() != true || nullableAnnotation == NullableAnnotation.Annotated);
Debug.Assert(extensions != null);
DefaultType = defaultType;
......@@ -53,7 +53,7 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
public override string ToString() => Type.ToString();
internal static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat(
private static readonly SymbolDisplayFormat DebuggerDisplayFormat = new SymbolDisplayFormat(
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier);
......@@ -64,15 +64,14 @@ private TypeWithAnnotations(TypeSymbol defaultType, NullableAnnotation nullableA
miscellaneousOptions: SymbolDisplayMiscellaneousOptions.UseSpecialTypes | SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier,
compilerInternalOptions: SymbolDisplayCompilerInternalOptions.IncludeNonNullableTypeModifier);
internal static TypeWithAnnotations Create(bool isNullableEnabled, TypeSymbol typeSymbol, bool isAnnotated = false, ImmutableArray<CustomModifier> customModifiers = default)
internal static TypeWithAnnotations Create(bool isNullableEnabled, TypeSymbol typeSymbol, bool isAnnotated = false)
{
if (typeSymbol is null)
{
return default;
}
return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious,
customModifiers.NullToEmpty());
return Create(typeSymbol, nullableAnnotation: isAnnotated ? NullableAnnotation.Annotated : isNullableEnabled ? NullableAnnotation.NotAnnotated : NullableAnnotation.Oblivious);
}
internal static TypeWithAnnotations Create(TypeSymbol typeSymbol, NullableAnnotation nullableAnnotation = NullableAnnotation.Oblivious, ImmutableArray<CustomModifier> customModifiers = default)
......@@ -580,7 +579,7 @@ public bool NeedsNullableAttribute()
/// If the type is a non-generic value type or Nullable&lt;&gt;, and
/// is not a type parameter, the nullability is not included in the byte[].
/// </summary>
private static bool SkipNullableTransform(TypeSymbol type)
private static bool IsNonGenericValueType(TypeSymbol type)
{
var namedType = type as NamedTypeSymbol;
if (namedType is null)
......@@ -605,7 +604,7 @@ private static void AddNullableTransforms(TypeWithAnnotations typeWithAnnotation
{
var type = typeWithAnnotations.Type;
if (!SkipNullableTransform(type))
if (!IsNonGenericValueType(type))
{
var annotation = typeWithAnnotations.NullableAnnotation;
byte flag;
......@@ -642,9 +641,9 @@ public bool ApplyNullableTransforms(byte defaultTransformFlag, ImmutableArray<by
TypeSymbol oldTypeSymbol = Type;
byte transformFlag;
// Check SkipNullableTransform first to avoid
// Check IsNonGenericValueType first to avoid
// applying transforms to simple value types.
if (SkipNullableTransform(oldTypeSymbol))
if (IsNonGenericValueType(oldTypeSymbol))
{
transformFlag = NullableAnnotationExtensions.ObliviousAttributeValue;
}
......
......@@ -933,6 +933,40 @@ public class C : IC<
AssertNullableAttributes(comp, expected);
}
[Fact]
public void EmitAttribute_TypeParameters()
{
var source =
@"#nullable enable
public interface I<T, U, V>
where U : class
where V : struct
{
T F1();
U F2();
U? F3();
V F4();
V? F5();
#nullable disable
T F6();
U F7();
U? F8();
V F9();
V? F10();
}";
var comp = CreateCompilation(source);
var expected =
@"I<T, U, V> where U : class! where V : struct
[Nullable(2)] T
[Nullable(1)] U
[NullableContext(1)] T F1()
[NullableContext(1)] U! F2()
[NullableContext(2)] U? F3()
[NullableContext(2)] U? F8()
";
AssertNullableAttributes(comp, expected);
}
[Fact]
public void EmitAttribute_Constraint_Nullable()
{
......
......@@ -3,7 +3,6 @@
using System;
using System.Collections.Immutable;
using System.Linq;
using System.Reflection;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CSharp.Test.Utilities;
......@@ -87,7 +86,8 @@ void M1(C? c)
Assert.Equal(PublicNullableAnnotation.NotAnnotated, expressionTypes[2].TypeArgumentNullableAnnotations.Single());
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/34412")]
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void FieldDeclarations()
{
var source = @"
......@@ -143,11 +143,12 @@ public class C
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/34412")]
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void PropertyDeclarations()
{
var source = @"
......@@ -204,11 +205,12 @@ public class C
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/34412")]
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void MethodReturnDeclarations()
{
var source = @"
......@@ -272,12 +274,12 @@ public class C
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact(Skip = "https://github.com/dotnet/roslyn/issues/34412")]
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void ParameterDeclarations()
{
var source = @"
......@@ -355,7 +357,7 @@ public class C
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Annotated);
}
......@@ -375,52 +377,56 @@ public class C
public static void M3() {}
public void M4() {}
}
public static class CExt
public static class Ext
{
#nullable enable
public static void M5(this C c) {}
public static void M6(this C? c) {}
public static void M7(this int i) {}
public static void M8(this int? i) {}
#nullable disable
public static void M7(this C c) {}
public static void M8(this C? c) {}
public static void M9(this C c) {}
public static void M10(this C? c) {}
public static void M11(this int i) {}
public static void M12(this int? i) {}
}
";
var comp1 = CreateCompilation(source, options: WithNonNullTypesTrue());
comp1.VerifyDiagnostics(
// (20,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// public static void M8(this C? c) {}
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 33));
// (22,34): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// public static void M10(this C? c) {}
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(22, 34));
verifyCompilation(comp1);
var comp2 = CreateCompilation(source, options: WithNonNullTypesFalse());
comp2.VerifyDiagnostics(
// (20,33): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' context.
// public static void M8(this C? c) {}
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(20, 33));
// (22,34): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// public static void M10(this C? c) {}
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(22, 34));
verifyCompilation(comp2);
var comp3 = CreateCompilation(source, parseOptions: TestOptions.Regular7_3, skipUsesIsNullable: true);
comp3.VerifyDiagnostics(
// (4,2): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (4,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(4, 2),
// (8,2): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (8,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(8, 2),
// (14,2): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (14,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(14, 2),
// (16,33): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (16,33): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// public static void M6(this C? c) {}
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(16, 33),
// (18,2): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// (20,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(18, 2),
// (20,33): error CS8652: The feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// public static void M8(this C? c) {}
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(20, 33));
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(20, 2),
// (22,34): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// public static void M10(this C? c) {}
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(22, 34));
verifyCompilation(comp3);
var comp1Emit = comp1.EmitToImageReference();
......@@ -441,22 +447,28 @@ void verifyCompilation(CSharpCompilation compilation)
{
var c = compilation.GetTypeByMetadataName("C");
var members = c.GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("M")).ToArray();
assertNullability(members,
PublicNullableAnnotation.NotApplicable,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.NotApplicable,
PublicNullableAnnotation.NotAnnotated);
assertNullability(PublicNullableAnnotation.NotApplicable, 0);
assertNullability(PublicNullableAnnotation.NotAnnotated, 1);
assertNullability(PublicNullableAnnotation.NotApplicable, 2);
assertNullability(PublicNullableAnnotation.NotAnnotated, 3);
var cExt = compilation.GetTypeByMetadataName("CExt");
members = cExt.GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("M")).Select(m => m.ReduceExtensionMethod(c)).ToArray();
assertNullability(PublicNullableAnnotation.NotAnnotated, 0);
assertNullability(PublicNullableAnnotation.Annotated, 1);
assertNullability(PublicNullableAnnotation.Disabled, 2);
assertNullability(PublicNullableAnnotation.Annotated, 3);
var e = compilation.GetTypeByMetadataName("Ext");
members = e.GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("M")).Select(m => m.ReduceExtensionMethod(m.Parameters[0].Type)).ToArray();
assertNullability(members,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
void assertNullability(PublicNullableAnnotation nullability, int index)
static void assertNullability(IMethodSymbol[] methods, params PublicNullableAnnotation[] expectedAnnotations)
{
Assert.Equal(nullability, members[index].ReceiverNullableAnnotation);
var actualAnnotations = methods.Select(m => m.ReceiverNullableAnnotation);
AssertEx.Equal(expectedAnnotations, actualAnnotations);
}
}
}
......@@ -534,7 +546,7 @@ void M1()
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
......@@ -592,6 +604,345 @@ public class C
PublicNullableAnnotation.Annotated);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void ArrayElements()
{
var source =
@"public interface I
{
#nullable enable
object[] F1();
object?[] F2();
int[] F3();
int?[] F4();
#nullable disable
object[] F5();
object?[] F6();
int[] F7();
int?[] F8();
}";
VerifyAcrossCompilations(
source,
new[]
{
// (10,11): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// object?[] F6();
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(10, 11)
},
new[]
{
// (3,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(3, 2),
// (5,11): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// object?[] F2();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(5, 11),
// (8,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(8, 2),
// (10,11): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// object?[] F6();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(10, 11)
},
comp => ((NamedTypeSymbol)comp.GetMember("I")).GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("F")).ToArray(),
method => ((IArrayTypeSymbol)method.ReturnType).ElementNullableAnnotation,
testMetadata: true,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void TypeParameters()
{
var source =
@"#nullable enable
public interface I<T, U, V>
where U : class
where V : struct
{
T F1();
U F2();
U? F3();
V F4();
V? F5();
#nullable disable
T F6();
U F7();
U? F8();
V F9();
V? F10();
}";
VerifyAcrossCompilations(
source,
new[]
{
// (14,6): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// U? F8();
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 6)
},
new[]
{
// (1,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(1, 2),
// (8,6): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// U? F3();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(8, 6),
// (11,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(11, 2),
// (14,6): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// U? F8();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(14, 6)
},
comp => ((NamedTypeSymbol)comp.GetMember("I")).GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("F")).ToArray(),
method => method.ReturnNullableAnnotation,
testMetadata: true,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void Constraints()
{
var source =
@"public class A<T>
{
public class B<U> where U : T { }
}
public interface I
{
#nullable enable
A<string> F1();
A<string?> F2();
A<int> F3();
A<int?> F4();
#nullable disable
A<string> F5();
A<string?> F6();
A<int> F7();
A<int?> F8();
}";
VerifyAcrossCompilations(
source,
new[]
{
// (14,13): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// A<object?> F6();
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(14, 13)
},
new[]
{
// (7,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(7, 2),
// (9,13): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// A<string?> F2();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(9, 13),
// (12,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(12, 2),
// (14,13): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// A<string?> F6();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(14, 13)
},
comp => ((NamedTypeSymbol)comp.GetMember("I")).GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("F")).ToArray(),
method => ((INamedTypeSymbol)((INamedTypeSymbol)method.ReturnType).GetMembers("B").Single()).TypeParameters.Single().ConstraintNullableAnnotations.Single(),
testMetadata: true,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void TypeArguments_01()
{
var source =
@"public interface IA<T>
{
}
#nullable enable
public interface IB<T, U, V>
where U : class
where V : struct
{
IA<T> F1();
IA<U> F2();
IA<U?> F3();
IA<V> F4();
IA<V?> F5();
#nullable disable
IA<T> F6();
IA<U> F7();
IA<U?> F8();
IA<V> F9();
IA<V?> F10();
}";
VerifyAcrossCompilations(
source,
new[]
{
// (17,9): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// IA<U?> F8();
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 9)
},
new[]
{
// (4,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable enable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(4, 2),
// (11,9): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// IA<U?> F3();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(11, 9),
// (14,2): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// #nullable disable
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "nullable").WithArguments("nullable reference types", "8.0").WithLocation(14, 2),
// (17,9): error CS8370: Feature 'nullable reference types' is not available in C# 7.3. Please use language version 8.0 or greater.
// IA<U?> F8();
Diagnostic(ErrorCode.ERR_FeatureNotAvailableInVersion7_3, "?").WithArguments("nullable reference types", "8.0").WithLocation(17, 9)
},
comp => ((NamedTypeSymbol)comp.GetMember("IB")).GetMembers().OfType<IMethodSymbol>().Where(m => m.Name.StartsWith("F")).ToArray(),
method => ((INamedTypeSymbol)method.ReturnType).TypeArgumentNullableAnnotations.Single(),
testMetadata: true,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void TypeArguments_02()
{
var source =
@"class C
{
static void F<T>()
{
}
#nullable enable
static void M<T, U, V>()
where U : class
where V : struct
{
F<T>();
F<U>();
F<U?>();
F<V>();
F<V?>();
#nullable disable
F<T>();
F<U>();
F<U?>();
F<V>();
F<V?>();
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (19,12): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// F<U?>();
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(19, 12));
var syntaxTree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(syntaxTree);
var invocations = syntaxTree.GetRoot().DescendantNodes().OfType<InvocationExpressionSyntax>();
var actualAnnotations = invocations.Select(inv => ((IMethodSymbol)model.GetSymbolInfo(inv).Symbol).TypeArgumentNullableAnnotations.Single()).ToArray();
var expectedAnnotations = new[]
{
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated
};
AssertEx.Equal(expectedAnnotations, actualAnnotations);
}
[Fact]
[WorkItem(34412, "https://github.com/dotnet/roslyn/issues/34412")]
public void Locals()
{
var source =
@"#pragma warning disable 168
class C
{
#nullable enable
static void M<T, U, V>()
where U : class
where V : struct
{
T x1;
U x2;
U? x3;
V x4;
V? x5;
#nullable disable
T x6;
U x7;
U? x8;
V x9;
V? x10;
}
}";
var comp = CreateCompilation(source);
comp.VerifyDiagnostics(
// (17,10): warning CS8632: The annotation for nullable reference types should only be used in code within a '#nullable' annotations context.
// U? x8;
Diagnostic(ErrorCode.WRN_MissingNonNullTypesContextForAnnotation, "?").WithLocation(17, 10));
var syntaxTree = comp.SyntaxTrees[0];
var model = comp.GetSemanticModel(syntaxTree);
var variables = syntaxTree.GetRoot().DescendantNodes().OfType<VariableDeclaratorSyntax>();
var actualAnnotations = variables.Select(v => ((ILocalSymbol)model.GetDeclaredSymbol(v)).NullableAnnotation).ToArray();
var expectedAnnotations = new[]
{
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Disabled,
PublicNullableAnnotation.Annotated,
PublicNullableAnnotation.NotAnnotated,
PublicNullableAnnotation.Annotated
};
AssertEx.Equal(expectedAnnotations, actualAnnotations);
}
private static void VerifyAcrossCompilations<T>(string source,
DiagnosticDescription[] nullableEnabledErrors,
DiagnosticDescription[] nullableDisabledErrors,
......@@ -600,7 +951,6 @@ public class C
bool testMetadata,
params PublicNullableAnnotation[] expectedNullabilities)
{
var comp1 = CreateCompilation(source, options: WithNonNullTypesTrue());
comp1.VerifyDiagnostics(nullableEnabledErrors);
verifyCompilation(comp1);
......
......@@ -319,14 +319,10 @@ internal static void VerifyTypes(this CSharpCompilation compilation, SyntaxTree
Assert.NotEqual(CodeAnalysis.NullableAnnotation.NotApplicable, typeInfo.Nullability.Annotation);
Assert.NotEqual(CodeAnalysis.NullableFlowState.NotApplicable, typeInfo.Nullability.FlowState);
// https://github.com/dotnet/roslyn/issues/35035: After refactoring symboldisplay, we should be able to just call something like typeInfo.Type.ToDisplayString(typeInfo.Nullability.FlowState, TypeWithState.TestDisplayFormat)
if (annotation.IsConverted)
{
return TypeWithState.Create((TypeSymbol)typeInfo.ConvertedType, typeInfo.ConvertedNullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
}
else
{
return TypeWithState.Create((TypeSymbol)typeInfo.Type, typeInfo.Nullability.FlowState.ToInternalFlowState()).ToTypeWithAnnotations().ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
}
var type = TypeWithState.Create(
(TypeSymbol)(annotation.IsConverted ? typeInfo.ConvertedType : typeInfo.Type),
(annotation.IsConverted ? typeInfo.ConvertedNullability : typeInfo.Nullability).FlowState.ToInternalFlowState()).ToTypeWithAnnotations();
return type.ToDisplayString(TypeWithAnnotations.TestDisplayFormat);
});
// Consider reporting the correct source with annotations on mismatch.
AssertEx.Equal(expectedTypes, actualTypes, message: method.ToTestDisplayString());
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册