| File: Symbols\TypeWithState.cs | Web Access |
| Project: src\roslyn\src\Compilers\CSharp\Portable\Microsoft.CodeAnalysis.CSharp.csproj (Microsoft.CodeAnalysis.CSharp) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Diagnostics; using System.Diagnostics.CodeAnalysis; namespace Microsoft.CodeAnalysis.CSharp.Symbols { /// <summary> /// A type and its corresponding flow state resulting from evaluating an rvalue expression. /// </summary> [DebuggerDisplay("{GetDebuggerDisplay(), nq}")] internal readonly struct TypeWithState { public readonly TypeSymbol? Type; public readonly NullableFlowState State; [MemberNotNullWhen(false, nameof(Type))] public bool HasNullType => Type is null; public bool MayBeNull => State == NullableFlowState.MaybeNull; public bool IsNotNull => State == NullableFlowState.NotNull; public static TypeWithState ForType(TypeSymbol? type) { return Create(type, NullableFlowState.MaybeDefault); } public static TypeWithState Create(TypeSymbol? type, NullableFlowState defaultState) { if (defaultState == NullableFlowState.MaybeDefault && (type is null || type.IsTypeParameterDisallowingAnnotationInCSharp8())) { Debug.Assert(type?.IsNullableTypeOrTypeParameter() != true); return new TypeWithState(type, defaultState); } var state = defaultState != NullableFlowState.NotNull && type?.CanContainNull() != false ? NullableFlowState.MaybeNull : NullableFlowState.NotNull; return new TypeWithState(type, state); } public static TypeWithState Create(TypeWithAnnotations typeWithAnnotations, FlowAnalysisAnnotations annotations = FlowAnalysisAnnotations.None) { var type = typeWithAnnotations.Type; Debug.Assert((object)type != null); NullableFlowState state; if (type.CanContainNull()) { if ((annotations & FlowAnalysisAnnotations.MaybeNull) == FlowAnalysisAnnotations.MaybeNull) { state = NullableFlowState.MaybeDefault; } else if ((annotations & FlowAnalysisAnnotations.NotNull) == FlowAnalysisAnnotations.NotNull) { state = NullableFlowState.NotNull; } else { return typeWithAnnotations.ToTypeWithState(); } } else { state = NullableFlowState.NotNull; } return Create(type, state); } private TypeWithState(TypeSymbol? type, NullableFlowState state) { Debug.Assert(state == NullableFlowState.NotNull || type?.CanContainNull() != false); Debug.Assert(state != NullableFlowState.MaybeDefault || type is null || type.IsTypeParameterDisallowingAnnotationInCSharp8()); Type = type; State = state; } public string GetDebuggerDisplay() => $"{{Type:{Type?.GetDebuggerDisplay()}, State:{State}{"}"}"; public override string ToString() => GetDebuggerDisplay(); public TypeWithState WithNotNullState() => new TypeWithState(Type, NullableFlowState.NotNull); public TypeWithState WithSuppression(bool suppress) => suppress ? new TypeWithState(Type, NullableFlowState.NotNull) : this; public TypeWithAnnotations ToTypeWithAnnotations(CSharpCompilation compilation, bool asAnnotatedType = false) { if (Type?.IsTypeParameterDisallowingAnnotationInCSharp8() == true) { var type = TypeWithAnnotations.Create(Type, NullableAnnotation.NotAnnotated); return (State == NullableFlowState.MaybeDefault || asAnnotatedType) ? type.SetIsAnnotated(compilation) : type; } NullableAnnotation annotation = asAnnotatedType ? (Type?.IsValueType == true ? NullableAnnotation.NotAnnotated : NullableAnnotation.Annotated) : (State.IsNotNull() || Type?.CanContainNull() == false ? NullableAnnotation.NotAnnotated : NullableAnnotation.Annotated); return TypeWithAnnotations.Create(this.Type, annotation); } public TypeWithAnnotations ToAnnotatedTypeWithAnnotations(CSharpCompilation compilation) => ToTypeWithAnnotations(compilation, asAnnotatedType: true); } }