未验证 提交 5badf86b 编写于 作者: A AlekseyTs 提交者: GitHub

NullableAnnotation on a type symbol returned by TypeInfo should match...

NullableAnnotation on a type symbol returned by TypeInfo should match corresponding FlowState. (#40338)

Fixes #40051.
上级 e8a539c4
......@@ -48,7 +48,8 @@ internal CSharpTypeInfo(TypeSymbol type, TypeSymbol convertedType, NullabilityIn
public static implicit operator TypeInfo(CSharpTypeInfo info)
{
return new TypeInfo(info.Type.GetPublicSymbol(), info.ConvertedType.GetPublicSymbol(), info.Nullability, info.ConvertedNullability);
return new TypeInfo(info.Type?.GetITypeSymbol(info.Nullability.FlowState.ToAnnotation()), info.ConvertedType?.GetITypeSymbol(info.ConvertedNullability.FlowState.ToAnnotation()),
info.Nullability, info.ConvertedNullability);
}
public override bool Equals(object obj)
......
......@@ -194,20 +194,7 @@ public static class SymbolDisplay
SymbolDisplayFormat format,
bool minimal)
{
return ToDisplayParts(symbol.WithNullableAnnotation(StateToAnnotation(nullableFlowState)), semanticModelOpt, positionOpt, format, minimal);
}
private static CodeAnalysis.NullableAnnotation StateToAnnotation(CodeAnalysis.NullableFlowState nullableFlowState)
{
switch (nullableFlowState)
{
case CodeAnalysis.NullableFlowState.MaybeNull:
return CodeAnalysis.NullableAnnotation.Annotated;
case CodeAnalysis.NullableFlowState.NotNull:
return CodeAnalysis.NullableAnnotation.NotAnnotated;
default:
return CodeAnalysis.NullableAnnotation.None;
}
return ToDisplayParts(symbol.WithNullableAnnotation(nullableFlowState.ToAnnotation()), semanticModelOpt, positionOpt, format, minimal);
}
private static ImmutableArray<SymbolDisplayPart> ToDisplayParts(
......
......@@ -12923,7 +12923,7 @@ static void Main()
var t = typeofNodes[i];
var typeInfo = model.GetTypeInfo(t.Type);
var symbolInfo = model.GetSymbolInfo(t.Type);
Assert.Same(typeInfo.Type, symbolInfo.Symbol);
Assert.Equal(typeInfo.Type, symbolInfo.Symbol);
switch (i)
{
......@@ -23076,7 +23076,7 @@ static void Main()
var typeInfo = model.GetTypeInfo(type);
Assert.Equal("(System.Int32 elem1, System.Int32 elem2)", typeInfo.Type.ToTestDisplayString());
Assert.Same(symbolInfo.Symbol, typeInfo.Type);
Assert.Equal(symbolInfo.Symbol, typeInfo.Type);
Assert.Equal("System.Int32 (System.Int32 elem1, System.Int32 elem2).elem1", model.GetDeclaredSymbol(type.Elements.First()).ToTestDisplayString());
Assert.Equal("System.Int32 (System.Int32 elem1, System.Int32 elem2).elem2", model.GetDeclaredSymbol(type.Elements.Last()).ToTestDisplayString());
......@@ -46582,12 +46582,12 @@ void M2()
var discard1 = arguments.First().Expression;
Assert.Equal("var _", discard1.ToString());
Assert.Equal("System.String", model.GetTypeInfo(discard1).Type.ToTestDisplayString());
Assert.Equal("System.String?", model.GetTypeInfo(discard1).Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, model.GetTypeInfo(discard1).Nullability.Annotation);
var discard2 = arguments.Skip(1).First().Expression;
Assert.Equal("_", discard2.ToString());
Assert.Equal("System.Object", model.GetTypeInfo(discard2).Type.ToTestDisplayString());
Assert.Equal("System.Object?", model.GetTypeInfo(discard2).Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableAnnotation.Annotated, model.GetTypeInfo(discard2).Nullability.Annotation);
var discard3 = arguments.Skip(2).First().Expression;
......@@ -87016,7 +87016,7 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String!>!");
}
private static void AssertTryGetSpeculativeSemanticModel(string source, NullableContextOptions nullableContextOptions, TypeSyntax type, string expected)
......@@ -87055,7 +87055,7 @@ void Tests()
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String>!");
}
[Fact]
......@@ -87080,7 +87080,7 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String>!");
}
[Fact]
......@@ -87106,7 +87106,7 @@ void Tests()
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String!>!");
}
[Fact]
......@@ -87133,7 +87133,7 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String>!");
}
[Fact]
......@@ -87160,8 +87160,8 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String!>!");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String!>!");
}
[Fact]
......@@ -87189,7 +87189,7 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String!>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Enable, type, "A<System.String!>!");
}
[Fact]
......@@ -87217,8 +87217,8 @@ void Tests()
"
);
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String>");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Disable, type, "A<System.String>!");
AssertTryGetSpeculativeSemanticModel(source, NullableContextOptions.Warnings, type, "A<System.String>!");
}
[Fact]
......@@ -4163,7 +4163,7 @@ void M()
var type = typeInfo.Type;
var conv = model.GetConversion(syntax);
Assert.NotNull(type);
Assert.Same(type, typeInfo.ConvertedType);
Assert.Equal(type, typeInfo.ConvertedType);
Assert.Equal(Conversion.Identity, conv);
Assert.Equal(TypeKind.Pointer, type.TypeKind);
Assert.Equal(SpecialType.System_Int32, ((IPointerTypeSymbol)type).PointedAtType.SpecialType);
......@@ -4230,7 +4230,7 @@ void M()
var type = typeInfo.Type;
var conv = model.GetConversion(syntax);
Assert.NotNull(type);
Assert.Same(type, typeInfo.ConvertedType);
Assert.Equal(type, typeInfo.ConvertedType);
Assert.Equal(Conversion.Identity, conv);
Assert.Equal("?*", typeInfo.Type.ToTestDisplayString());
......@@ -4268,7 +4268,7 @@ void M()
var type = typeInfo.Type;
var conv = model.GetConversion(syntax);
Assert.NotNull(type);
Assert.Same(type, typeInfo.ConvertedType);
Assert.Equal(type, typeInfo.ConvertedType);
Assert.Equal(Conversion.Identity, conv);
Assert.Equal("?*", typeInfo.Type.ToTestDisplayString());
......@@ -4305,7 +4305,7 @@ void M()
var type = typeInfo.Type;
var conv = model.GetConversion(syntax);
Assert.NotNull(type);
Assert.Same(type, typeInfo.ConvertedType);
Assert.Equal(type, typeInfo.ConvertedType);
Assert.Equal(Conversion.Identity, conv);
Assert.Equal("?*", typeInfo.Type.ToTestDisplayString());
......@@ -4441,7 +4441,7 @@ void M()
var type = typeInfo.Type;
var conv = model.GetConversion(syntax);
Assert.NotNull(type);
Assert.Same(type, typeInfo.ConvertedType);
Assert.Equal(type, typeInfo.ConvertedType);
Assert.Equal(Conversion.Identity, conv);
Assert.Equal(SpecialType.System_Int32, type.SpecialType);
}
......
......@@ -8482,7 +8482,8 @@ public static int Main(string[] args)
Assert.Equal(true, semanticInfo.ConstantValue);
}
[Fact]
[ConditionalFact(typeof(IsDebug))]
[WorkItem(40352, "https://github.com/dotnet/roslyn/issues/40352")]
public void SwitchExpression_Constant02()
{
string sourceCode = @"
......@@ -8509,9 +8510,11 @@ public static int Main(string[] args)
";
var semanticInfo = GetSemanticInfoForTest<IdentifierNameSyntax>(sourceCode);
Assert.Equal("System.String", semanticInfo.Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, semanticInfo.Nullability.FlowState);
Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, semanticInfo.ConvertedNullability.FlowState);
Assert.Equal("System.String?", semanticInfo.Type.ToTestDisplayString());
Assert.Equal(TypeKind.Class, semanticInfo.Type.TypeKind);
Assert.Equal("System.String", semanticInfo.ConvertedType.ToTestDisplayString());
Assert.Equal("System.String?", semanticInfo.ConvertedType.ToTestDisplayString());
Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind);
Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind);
......@@ -8525,7 +8528,8 @@ public static int Main(string[] args)
Assert.Null(semanticInfo.ConstantValue.Value);
}
[Fact]
[ConditionalFact(typeof(IsDebug))]
[WorkItem(40352, "https://github.com/dotnet/roslyn/issues/40352")]
public void SwitchExpression_NotConstant()
{
string sourceCode = @"
......@@ -8551,9 +8555,11 @@ public static int Main(string[] args)
";
var semanticInfo = GetSemanticInfoForTest<IdentifierNameSyntax>(sourceCode);
Assert.Equal("System.String", semanticInfo.Type.ToTestDisplayString());
Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, semanticInfo.Nullability.FlowState);
Assert.Equal(CodeAnalysis.NullableFlowState.MaybeNull, semanticInfo.ConvertedNullability.FlowState);
Assert.Equal("System.String?", semanticInfo.Type.ToTestDisplayString());
Assert.Equal(TypeKind.Class, semanticInfo.Type.TypeKind);
Assert.Equal("System.String", semanticInfo.ConvertedType.ToTestDisplayString());
Assert.Equal("System.String?", semanticInfo.ConvertedType.ToTestDisplayString());
Assert.Equal(TypeKind.Class, semanticInfo.ConvertedType.TypeKind);
Assert.Equal(ConversionKind.Identity, semanticInfo.ImplicitConversion.Kind);
......
......@@ -20,28 +20,28 @@ public void Equality()
EqualityTesting.AssertEqual(default(TypeInfo), default(TypeInfo));
EqualityTesting.AssertEqual(new TypeInfo(obj, int32, nullable, notNullable),
new TypeInfo(obj, int32, nullable, notNullable));
EqualityTesting.AssertEqual(new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32, nullable, notNullable),
new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32, nullable, notNullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj, obj, nullable, nullable),
new TypeInfo(obj, int32, nullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable),
new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(int32, obj, nullable, nullable),
new TypeInfo(obj, obj, nullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable),
new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj, int32, nullable, nullable),
new TypeInfo(obj, int32, notNullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable),
new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.NotAnnotated), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), notNullable, nullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj, int32, nullable, nullable),
new TypeInfo(obj, int32, nullable, notNullable));
EqualityTesting.AssertNotEqual(new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), nullable, nullable),
new TypeInfo(obj.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.Annotated), int32, nullable, notNullable));
EqualityTesting.AssertEqual(new TypeInfo(int32, int32, default, default),
new TypeInfo(int32, int32, default, default));
EqualityTesting.AssertEqual(new TypeInfo(int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), default, default),
new TypeInfo(int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), default, default));
var intEnum1 = c.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T).GetPublicSymbol().Construct(int32);
var intEnum2 = c.GetSpecialType(SpecialType.System_Collections_Generic_IEnumerable_T).GetPublicSymbol().Construct(int32);
EqualityTesting.AssertEqual(new TypeInfo(intEnum1, int32, default, default),
new TypeInfo(intEnum2, int32, default, default));
EqualityTesting.AssertEqual(new TypeInfo(intEnum1.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), default, default),
new TypeInfo(intEnum2.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), int32.WithNullableAnnotation(CodeAnalysis.NullableAnnotation.None), default, default));
}
}
}
......@@ -3,6 +3,7 @@
#nullable enable
using System;
using System.Diagnostics;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis
......@@ -39,6 +40,8 @@ namespace Microsoft.CodeAnalysis
internal TypeInfo(ITypeSymbol? type, ITypeSymbol? convertedType, NullabilityInfo nullability, NullabilityInfo convertedNullability)
: this()
{
Debug.Assert(type is null || type.NullableAnnotation == nullability.FlowState.ToAnnotation());
Debug.Assert(convertedType is null || convertedType.NullableAnnotation == convertedNullability.FlowState.ToAnnotation());
this.Type = type;
this.Nullability = nullability;
this.ConvertedType = convertedType;
......
......@@ -23,4 +23,26 @@ public enum NullableFlowState : byte
/// </summary>
MaybeNull
}
internal static class NullableFlowStateExtensions
{
/// <summary>
/// This method directly converts a <see cref="NullableFlowState"/> to a <see cref="NullableAnnotation"/>,
/// ignoring the <see cref="ITypeSymbol"/> to which it is attached. It should only be used when converting
/// an RValue flow state to an RValue annotation for returning via the public API. For general use, please
/// use Microsoft.CodeAnalysis.CSharp.Symbols.TypeWithState.ToTypeWithAnnotations.
/// </summary>
public static NullableAnnotation ToAnnotation(this NullableFlowState nullableFlowState)
{
switch (nullableFlowState)
{
case CodeAnalysis.NullableFlowState.MaybeNull:
return CodeAnalysis.NullableAnnotation.Annotated;
case CodeAnalysis.NullableFlowState.NotNull:
return CodeAnalysis.NullableAnnotation.NotAnnotated;
default:
return CodeAnalysis.NullableAnnotation.None;
}
}
}
}
......@@ -203,7 +203,9 @@ public class SemanticInfoSummary
public CandidateReason CandidateReason;
public ImmutableArray<ISymbol> CandidateSymbols = ImmutableArray.Create<ISymbol>();
public ITypeSymbol Type;
public NullabilityInfo Nullability;
public ITypeSymbol ConvertedType;
public NullabilityInfo ConvertedNullability;
public Conversion ImplicitConversion = default(Conversion);
public IAliasSymbol Alias;
public Optional<object> ConstantValue = default(Optional<object>);
......@@ -230,6 +232,8 @@ public static SemanticInfoSummary GetSemanticInfoSummary(this SemanticModel sema
var typeInfo = semanticModel.GetTypeInfo(expr);
summary.Type = typeInfo.Type;
summary.ConvertedType = typeInfo.ConvertedType;
summary.Nullability = typeInfo.Nullability;
summary.ConvertedNullability = typeInfo.ConvertedNullability;
summary.ImplicitConversion = semanticModel.GetConversion(expr);
summary.MemberGroup = semanticModel.GetMemberGroup(expr);
}
......@@ -291,6 +295,8 @@ public static SemanticInfoSummary GetSpeculativeSemanticInfoSummary(this Semanti
var typeInfo = semanticModel.GetSpeculativeTypeInfo(position, expr, bindingOption);
summary.Type = typeInfo.Type;
summary.ConvertedType = typeInfo.ConvertedType;
summary.Nullability = typeInfo.Nullability;
summary.ConvertedNullability = typeInfo.ConvertedNullability;
summary.ImplicitConversion = semanticModel.GetSpeculativeConversion(position, expr, bindingOption);
//summary.MethodGroup = semanticModel.GetSpeculativeMethodGroup(expr);
}
......
......@@ -233,6 +233,17 @@ public class IsRelease : ExecutionCondition
public override string SkipReason => "Test not supported in DEBUG";
}
public class IsDebug : ExecutionCondition
{
#if DEBUG
public override bool ShouldSkip => false;
#else
public override bool ShouldSkip => true;
#endif
public override string SkipReason => "Test not supported in RELEASE";
}
public class WindowsOnly : ExecutionCondition
{
public override bool ShouldSkip => !ExecutionConditionUtil.IsWindows;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册