<commit_before>﻿// 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.

#nullable disable

using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Roslyn.Utilities;

// https://github.com/dotnet/roslyn/issues/34962 IDE005 "Fix formatting" does a poor job with a switch expression as the body of an expression-bodied method
#pragma warning disable IDE0055

namespace Microsoft.CodeAnalysis.CSharp
{
    internal static class NullableAnnotationExtensions
    {
        public static bool IsAnnotated(this NullableAnnotation annotation) => annotation == NullableAnnotation.Annotated;

        public static bool IsNotAnnotated(this NullableAnnotation annotation) => annotation == NullableAnnotation.NotAnnotated;

        public static bool IsOblivious(this NullableAnnotation annotation) => annotation == NullableAnnotation.Oblivious;

        /// <summary>
        /// Join nullable annotations from the set of lower bounds for fixing a type parameter.
        /// This uses the covariant merging rules. (Annotated wins over Oblivious which wins over NotAnnotated)
        /// </summary>
        public static NullableAnnotation Join(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a < b) ? b : a;
        }

        /// <summary>
        /// Meet two nullable annotations for computing the nullable annotation of a type parameter from upper bounds.
        /// This uses the contravariant merging rules. (NotAnnotated wins over Oblivious which wins over Annotated)
        /// </summary>
        public static NullableAnnotation Meet(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a < b) ? a : b;
        }

        /// <summary>
        /// Return the nullable annotation to use when two annotations are expected to be "compatible", which means
        /// they could be the same. These are the "invariant" merging rules. (NotAnnotated wins over Annotated which wins over Oblivious)
        /// </summary>
        public static NullableAnnotation EnsureCompatible(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a, b) switch
            {
                (NullableAnnotation.Oblivious, _) => b,
                (_, NullableAnnotation.Oblivious) => a,
                _ => a < b ? a : b,
            };
        }

        /// <summary>
        /// Merges nullability.
        /// </summary>
        public static NullableAnnotation MergeNullableAnnotation(this NullableAnnotation a, NullableAnnotation b, VarianceKind variance)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return variance switch
            {
                VarianceKind.In => a.Meet(b),
                VarianceKind.Out => a.Join(b),
                VarianceKind.None => a.EnsureCompatible(b),
                _ => throw ExceptionUtilities.UnexpectedValue(variance)
            };
        }

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.NotAnnotated"/>.
        /// </summary>
        public const byte NotAnnotatedAttributeValue = 1;

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.Annotated"/>.
        /// </summary>
        public const byte AnnotatedAttributeValue = 2;

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.Oblivious"/>.
        /// </summary>
        public const byte ObliviousAttributeValue = 0;

        internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnnotation annotation, TypeSymbol type)
        {
            if (annotation == CodeAnalysis.NullableAnnotation.None)
            {
                return default;
            }

            CSharp.NullableAnnotation internalAnnotation = annotation.ToInternalAnnotation();
            return internalAnnotation.ToNullabilityInfo(type);
        }

        internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type)
        {
            var flowState = TypeWithAnnotations.Create(type, annotation).ToTypeWithState().State;
            return new NullabilityInfo(ToPublicAnnotation(type, annotation), flowState.ToPublicFlowState());
        }

        internal static ITypeSymbol GetPublicSymbol(this TypeWithAnnotations type)
        {
            return type.Type?.GetITypeSymbol(type.ToPublicAnnotation());
        }

        internal static ImmutableArray<ITypeSymbol> GetPublicSymbols(this ImmutableArray<TypeWithAnnotations> types)
        {
            return types.SelectAsArray(t => t.GetPublicSymbol());
        }

        internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this TypeWithAnnotations type) =>
            ToPublicAnnotation(type.Type, type.NullableAnnotation);

        internal static ImmutableArray<CodeAnalysis.NullableAnnotation> ToPublicAnnotations(this ImmutableArray<TypeWithAnnotations> types) =>
            types.SelectAsArray(t => t.ToPublicAnnotation());

#nullable enable

        internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(TypeSymbol? type, NullableAnnotation annotation)
        {
            Debug.Assert(annotation != NullableAnnotation.Ignored);
            return annotation switch
            {
                NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated,
                NullableAnnotation.NotAnnotated => CodeAnalysis.NullableAnnotation.NotAnnotated,

                // 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.
                NullableAnnotation.Oblivious when type?.IsValueType == true => CodeAnalysis.NullableAnnotation.NotAnnotated,
                NullableAnnotation.Oblivious => CodeAnalysis.NullableAnnotation.None,

                NullableAnnotation.Ignored => CodeAnalysis.NullableAnnotation.None,

                _ => throw ExceptionUtilities.UnexpectedValue(annotation)
            };
        }

#nullable disable

        internal static CSharp.NullableAnnotation ToInternalAnnotation(this CodeAnalysis.NullableAnnotation annotation) =>
            annotation switch
            {
                CodeAnalysis.NullableAnnotation.None => CSharp.NullableAnnotation.Oblivious,
                CodeAnalysis.NullableAnnotation.NotAnnotated => CSharp.NullableAnnotation.NotAnnotated,
                CodeAnalysis.NullableAnnotation.Annotated => CSharp.NullableAnnotation.Annotated,
                _ => throw ExceptionUtilities.UnexpectedValue(annotation)
            };
    }
}
<commit_msg>Remove unneeded `#pragma warning disable` (#64535)<commit_after>﻿// 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.

#nullable disable

using System.Collections.Immutable;
using System.Diagnostics;
using Microsoft.CodeAnalysis.CSharp.Symbols;
using Roslyn.Utilities;

namespace Microsoft.CodeAnalysis.CSharp
{
    internal static class NullableAnnotationExtensions
    {
        public static bool IsAnnotated(this NullableAnnotation annotation) => annotation == NullableAnnotation.Annotated;

        public static bool IsNotAnnotated(this NullableAnnotation annotation) => annotation == NullableAnnotation.NotAnnotated;

        public static bool IsOblivious(this NullableAnnotation annotation) => annotation == NullableAnnotation.Oblivious;

        /// <summary>
        /// Join nullable annotations from the set of lower bounds for fixing a type parameter.
        /// This uses the covariant merging rules. (Annotated wins over Oblivious which wins over NotAnnotated)
        /// </summary>
        public static NullableAnnotation Join(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a < b) ? b : a;
        }

        /// <summary>
        /// Meet two nullable annotations for computing the nullable annotation of a type parameter from upper bounds.
        /// This uses the contravariant merging rules. (NotAnnotated wins over Oblivious which wins over Annotated)
        /// </summary>
        public static NullableAnnotation Meet(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a < b) ? a : b;
        }

        /// <summary>
        /// Return the nullable annotation to use when two annotations are expected to be "compatible", which means
        /// they could be the same. These are the "invariant" merging rules. (NotAnnotated wins over Annotated which wins over Oblivious)
        /// </summary>
        public static NullableAnnotation EnsureCompatible(this NullableAnnotation a, NullableAnnotation b)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return (a, b) switch
            {
                (NullableAnnotation.Oblivious, _) => b,
                (_, NullableAnnotation.Oblivious) => a,
                _ => a < b ? a : b,
            };
        }

        /// <summary>
        /// Merges nullability.
        /// </summary>
        public static NullableAnnotation MergeNullableAnnotation(this NullableAnnotation a, NullableAnnotation b, VarianceKind variance)
        {
            Debug.Assert(a != NullableAnnotation.Ignored);
            Debug.Assert(b != NullableAnnotation.Ignored);
            return variance switch
            {
                VarianceKind.In => a.Meet(b),
                VarianceKind.Out => a.Join(b),
                VarianceKind.None => a.EnsureCompatible(b),
                _ => throw ExceptionUtilities.UnexpectedValue(variance)
            };
        }

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.NotAnnotated"/>.
        /// </summary>
        public const byte NotAnnotatedAttributeValue = 1;

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.Annotated"/>.
        /// </summary>
        public const byte AnnotatedAttributeValue = 2;

        /// <summary>
        /// The attribute (metadata) representation of <see cref="NullableAnnotation.Oblivious"/>.
        /// </summary>
        public const byte ObliviousAttributeValue = 0;

        internal static NullabilityInfo ToNullabilityInfo(this CodeAnalysis.NullableAnnotation annotation, TypeSymbol type)
        {
            if (annotation == CodeAnalysis.NullableAnnotation.None)
            {
                return default;
            }

            CSharp.NullableAnnotation internalAnnotation = annotation.ToInternalAnnotation();
            return internalAnnotation.ToNullabilityInfo(type);
        }

        internal static NullabilityInfo ToNullabilityInfo(this NullableAnnotation annotation, TypeSymbol type)
        {
            var flowState = TypeWithAnnotations.Create(type, annotation).ToTypeWithState().State;
            return new NullabilityInfo(ToPublicAnnotation(type, annotation), flowState.ToPublicFlowState());
        }

        internal static ITypeSymbol GetPublicSymbol(this TypeWithAnnotations type)
        {
            return type.Type?.GetITypeSymbol(type.ToPublicAnnotation());
        }

        internal static ImmutableArray<ITypeSymbol> GetPublicSymbols(this ImmutableArray<TypeWithAnnotations> types)
        {
            return types.SelectAsArray(t => t.GetPublicSymbol());
        }

        internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(this TypeWithAnnotations type) =>
            ToPublicAnnotation(type.Type, type.NullableAnnotation);

        internal static ImmutableArray<CodeAnalysis.NullableAnnotation> ToPublicAnnotations(this ImmutableArray<TypeWithAnnotations> types) =>
            types.SelectAsArray(t => t.ToPublicAnnotation());

#nullable enable

        internal static CodeAnalysis.NullableAnnotation ToPublicAnnotation(TypeSymbol? type, NullableAnnotation annotation)
        {
            Debug.Assert(annotation != NullableAnnotation.Ignored);
            return annotation switch
            {
                NullableAnnotation.Annotated => CodeAnalysis.NullableAnnotation.Annotated,
                NullableAnnotation.NotAnnotated => CodeAnalysis.NullableAnnotation.NotAnnotated,

                // 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.
                NullableAnnotation.Oblivious when type?.IsValueType == true => CodeAnalysis.NullableAnnotation.NotAnnotated,
                NullableAnnotation.Oblivious => CodeAnalysis.NullableAnnotation.None,

                NullableAnnotation.Ignored => CodeAnalysis.NullableAnnotation.None,

                _ => throw ExceptionUtilities.UnexpectedValue(annotation)
            };
        }

#nullable disable

        internal static CSharp.NullableAnnotation ToInternalAnnotation(this CodeAnalysis.NullableAnnotation annotation) =>
            annotation switch
            {
                CodeAnalysis.NullableAnnotation.None => CSharp.NullableAnnotation.Oblivious,
                CodeAnalysis.NullableAnnotation.NotAnnotated => CSharp.NullableAnnotation.NotAnnotated,
                CodeAnalysis.NullableAnnotation.Annotated => CSharp.NullableAnnotation.Annotated,
                _ => throw ExceptionUtilities.UnexpectedValue(annotation)
            };
    }
}

{'fraction_non_alphanumeric': 0.07968994356428911, 'fraction_numerical': 0.0015638811450329774, 'mean_word_length': 2.5500844798455224, 'pattern_counts': {'":': 0, '<': 51, '<?xml version=': 0, '>': 95, 'https://': 1, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2016123', 'n_tokens_mistral': 3554, 'n_tokens_neox': 3379, 'n_words': 950}