/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Compilers/CSharp/Portable/Symbols/SymbolExtensions.cs
848 строк
34 KB
Cyrus Najmabadi
Add actual nullable analysis support for `with(...)` elements. (#81978)
16 янв 2026, 02:28
Не верифицирован
16 янв 2026, 02:28
48270ee
Код
Авторство
О чём код?
// 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; using System.Collections.Generic; using System.Collections.Immutable; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; using System.Linq; using Microsoft.CodeAnalysis.PooledObjects; using Roslyn.Utilities; using static System.Linq.ImmutableArrayExtensions; namespace Microsoft.CodeAnalysis.CSharp.Symbols { internal static partial class SymbolExtensions { /// <summary> /// Does the compilation this symbol belongs to output to a winmdobj? /// </summary> /// <param name="symbol"></param> /// <returns></returns> public static bool IsCompilationOutputWinMdObj(this Symbol symbol) { var comp = symbol.DeclaringCompilation; return comp != null && comp.Options.OutputKind == OutputKind.WindowsRuntimeMetadata; } /// <summary> /// Returns a constructed named type symbol if 'type' is generic, otherwise just returns 'type' /// </summary> public static NamedTypeSymbol ConstructIfGeneric(this NamedTypeSymbol type, ImmutableArray<TypeWithAnnotations> typeArguments) { Debug.Assert(type.TypeParameters.IsEmpty == (typeArguments.Length == 0)); return type.TypeParameters.IsEmpty ? type : type.Construct(typeArguments, unbound: false); } public static bool IsNestedType([NotNullWhen(true)] this Symbol? symbol) { return symbol is NamedTypeSymbol && (object?)symbol.ContainingType != null; } /// <summary> /// Returns true if the members of superType are accessible from subType due to inheritance. /// </summary> public static bool IsAccessibleViaInheritance(this NamedTypeSymbol superType, NamedTypeSymbol subType, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) { // NOTE: we don't use strict inheritance. Instead we ignore constructed generic types // and only consider the unconstructed types. Ecma-334, 4th edition contained the // following text supporting this (although, for instance members) in 10.5.3 Protected // access for instance members: // In the context of generics (25.1.6), the rules for accessing protected and // protected internal instance members are augmented by the following: // o Within a generic class G, access to an inherited protected instance member M // using a primary-expression of the form E.M is permitted if the type of E is a // class type constructed from G or a class type derived from a class type // constructed from G. // This text is missing in the current version of the spec, but we believe this is accidental. NamedTypeSymbol originalSuperType = superType.OriginalDefinition; for (NamedTypeSymbol? current = subType; (object?)current != null; current = current.BaseTypeWithDefinitionUseSiteDiagnostics(ref useSiteInfo)) { if (ReferenceEquals(current.OriginalDefinition, originalSuperType)) { return true; } } if (originalSuperType.IsInterface) { foreach (NamedTypeSymbol current in subType.AllInterfacesWithDefinitionUseSiteDiagnostics(ref useSiteInfo)) { if (ReferenceEquals(current.OriginalDefinition, originalSuperType)) { return true; } } } // The method returns true for superType == subType. // Two different submission type symbols semantically represent a single type, so we should also return true. return superType.TypeKind == TypeKind.Submission && subType.TypeKind == TypeKind.Submission; } public static bool IsNoMoreVisibleThan(this Symbol symbol, TypeSymbol type, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) { return type.IsAtLeastAsVisibleAs(symbol, ref useSiteInfo); } public static bool IsNoMoreVisibleThan(this Symbol symbol, TypeWithAnnotations type, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo) { return type.IsAtLeastAsVisibleAs(symbol, ref useSiteInfo); } internal static void AddUseSiteInfo(this Symbol? symbol, ref CompoundUseSiteInfo<AssemblySymbol> useSiteInfo, bool addDiagnostics = true) { if (symbol is null) { return; } if (!useSiteInfo.AccumulatesDiagnostics) { Debug.Assert(!useSiteInfo.AccumulatesDependencies); return; } var info = symbol.GetUseSiteInfo(); if (addDiagnostics) { useSiteInfo.AddDiagnostics(info); } useSiteInfo.AddDependencies(info); } public static LocalizableErrorArgument GetKindText(this Symbol symbol) { return symbol.Kind.Localize(); } /// <summary> /// The immediately containing namespace or named type, or null /// if the containing symbol is neither a namespace or named type. /// </summary> internal static NamespaceOrTypeSymbol? ContainingNamespaceOrType(this Symbol symbol) { var containingSymbol = symbol.ContainingSymbol; if ((object?)containingSymbol != null) { switch (containingSymbol.Kind) { case SymbolKind.Namespace: case SymbolKind.NamedType: case SymbolKind.ErrorType: return (NamespaceOrTypeSymbol)containingSymbol; } } return null; } internal static Symbol? ContainingNonLambdaMember(this Symbol? containingMember) { while (containingMember is object && containingMember.Kind == SymbolKind.Method) { var method = (MethodSymbol)containingMember; if (method.MethodKind != MethodKind.AnonymousFunction && method.MethodKind != MethodKind.LocalFunction) break; containingMember = containingMember.ContainingSymbol; } return containingMember; } internal static ParameterSymbol? EnclosingThisSymbol(this Symbol containingMember) { Symbol symbol = containingMember; while (true) { NamedTypeSymbol type; switch (symbol.Kind) { case SymbolKind.Method: MethodSymbol method = (MethodSymbol)symbol; // skip lambdas: if (method.MethodKind == MethodKind.AnonymousFunction || method.MethodKind == MethodKind.LocalFunction) { symbol = method.ContainingSymbol; continue; } return method.ThisParameter; case SymbolKind.Field: // "this" in field initializer: type = symbol.ContainingType; break; case SymbolKind.NamedType: // "this" in global statement: type = (NamedTypeSymbol)symbol; break; default: return null; } // "this" can be accessed in a lambda in a field initializer if the initializer is // a script field initializer or global statement because these are initialized // after the call to the base constructor. return type.IsScriptClass ? type.InstanceConstructors.Single().ThisParameter : null; } } public static Symbol ConstructedFrom(this Symbol symbol) { switch (symbol.Kind) { case SymbolKind.NamedType: case SymbolKind.ErrorType: return ((NamedTypeSymbol)symbol).ConstructedFrom; case SymbolKind.Method: return ((MethodSymbol)symbol).ConstructedFrom; default: return symbol; } } /// <summary> /// Returns true if all type parameter references within the given /// type belong to containingSymbol or its containing types. /// </summary> public static bool IsContainingSymbolOfAllTypeParameters(this Symbol containingSymbol, TypeSymbol type) { return type.VisitType(s_hasInvalidTypeParameterFunc, containingSymbol) is null; } /// <summary> /// Returns true if all type parameter references within the given /// types belong to containingSymbol or its containing types. /// </summary> public static bool IsContainingSymbolOfAllTypeParameters(this Symbol containingSymbol, ImmutableArray<TypeSymbol> types) { return types.All(containingSymbol.IsContainingSymbolOfAllTypeParameters); } private static readonly Func<TypeSymbol, Symbol, bool, bool> s_hasInvalidTypeParameterFunc = (type, containingSymbol, unused) => HasInvalidTypeParameter(type, containingSymbol); private static bool HasInvalidTypeParameter(TypeSymbol type, Symbol? containingSymbol) { if (type.TypeKind == TypeKind.TypeParameter) { var symbol = type.ContainingSymbol; for (; ((object?)containingSymbol != null) && (containingSymbol.Kind != SymbolKind.Namespace); containingSymbol = containingSymbol.ContainingSymbol) { if (containingSymbol == symbol) { return false; } } return true; } return false; } public static bool IsTypeOrTypeAlias(this Symbol symbol) { switch (symbol.Kind) { case SymbolKind.ArrayType: case SymbolKind.DynamicType: case SymbolKind.ErrorType: case SymbolKind.NamedType: case SymbolKind.PointerType: case SymbolKind.FunctionPointerType: case SymbolKind.TypeParameter: return true; case SymbolKind.Alias: return IsTypeOrTypeAlias(((AliasSymbol)symbol).Target); default: Debug.Assert(!(symbol is TypeSymbol)); return false; } } internal static bool CompilationAllowsUnsafe(this Symbol symbol) { return symbol.DeclaringCompilation.Options.AllowUnsafe; } internal static void CheckUnsafeModifier(this Symbol symbol, DeclarationModifiers modifiers, BindingDiagnosticBag diagnostics) { symbol.CheckUnsafeModifier(modifiers, symbol.GetFirstLocation(), diagnostics); } internal static void CheckUnsafeModifier(this Symbol symbol, DeclarationModifiers modifiers, Location errorLocation, BindingDiagnosticBag diagnostics) => CheckUnsafeModifier(symbol, modifiers, errorLocation, diagnostics.DiagnosticBag); internal static void CheckUnsafeModifier(this Symbol symbol, DeclarationModifiers modifiers, Location errorLocation, DiagnosticBag? diagnostics) { if (diagnostics != null && (modifiers & DeclarationModifiers.Unsafe) == DeclarationModifiers.Unsafe && !symbol.CompilationAllowsUnsafe()) { RoslynDebug.Assert(errorLocation != null); diagnostics.Add(ErrorCode.ERR_IllegalUnsafe, errorLocation); } } /// <summary> /// Does the top level type containing this symbol have 'Microsoft.CodeAnalysis.Embedded' attribute? /// </summary> public static bool IsHiddenByCodeAnalysisEmbeddedAttribute(this Symbol symbol) { // Only upper-level types should be checked var upperLevelType = symbol.Kind == SymbolKind.NamedType ? (NamedTypeSymbol)symbol : symbol.ContainingType; if ((object?)upperLevelType == null) { return false; } while ((object?)upperLevelType.ContainingType != null) { upperLevelType = upperLevelType.ContainingType; } return upperLevelType.HasCodeAnalysisEmbeddedAttribute; } public static bool MustCallMethodsDirectly(this Symbol symbol) { switch (symbol.Kind) { case SymbolKind.Property: return ((PropertySymbol)symbol).MustCallMethodsDirectly; case SymbolKind.Event: return ((EventSymbol)symbol).MustCallMethodsDirectly; default: return false; } } public static int GetArity(this Symbol? symbol) { if (symbol is object) { switch (symbol.Kind) { case SymbolKind.NamedType: return ((NamedTypeSymbol)symbol).Arity; case SymbolKind.Method: return ((MethodSymbol)symbol).Arity; } } return 0; } internal static CSharpSyntaxNode GetNonNullSyntaxNode(this Symbol? symbol) { if (symbol is object) { SyntaxReference? reference = symbol.DeclaringSyntaxReferences.FirstOrDefault(); if (reference == null && symbol.IsImplicitlyDeclared) { Symbol? containingSymbol = symbol.ContainingSymbol; if ((object?)containingSymbol != null) { reference = containingSymbol.DeclaringSyntaxReferences.FirstOrDefault(); } } if (reference != null) { return (CSharpSyntaxNode)reference.GetSyntax(); } } return (CSharpSyntaxNode)CSharpSyntaxTree.Dummy.GetRoot(); } [return: NotNullIfNotNull(nameof(symbol))] internal static Symbol? EnsureCSharpSymbolOrNull(this ISymbol? symbol, string paramName) { var csSymbol = symbol as PublicModel.Symbol; if (csSymbol is null) { if (symbol is object) { throw new ArgumentException(CSharpResources.NotACSharpSymbol, paramName); } return null; } return csSymbol.UnderlyingSymbol; } [return: NotNullIfNotNull(nameof(symbol))] internal static AssemblySymbol? EnsureCSharpSymbolOrNull(this IAssemblySymbol? symbol, string paramName) { return (AssemblySymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static NamespaceOrTypeSymbol? EnsureCSharpSymbolOrNull(this INamespaceOrTypeSymbol? symbol, string paramName) { return (NamespaceOrTypeSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static NamespaceSymbol? EnsureCSharpSymbolOrNull(this INamespaceSymbol? symbol, string paramName) { return (NamespaceSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static TypeSymbol? EnsureCSharpSymbolOrNull(this ITypeSymbol? symbol, string paramName) { return (TypeSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static NamedTypeSymbol? EnsureCSharpSymbolOrNull(this INamedTypeSymbol? symbol, string paramName) { return (NamedTypeSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static TypeParameterSymbol? EnsureCSharpSymbolOrNull(this ITypeParameterSymbol? symbol, string paramName) { return (TypeParameterSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } [return: NotNullIfNotNull(nameof(symbol))] internal static EventSymbol? EnsureCSharpSymbolOrNull(this IEventSymbol? symbol, string paramName) { return (EventSymbol?)EnsureCSharpSymbolOrNull((ISymbol?)symbol, paramName); } internal static TypeWithAnnotations GetTypeOrReturnType(this Symbol symbol) { TypeWithAnnotations returnType; GetTypeOrReturnType(symbol, refKind: out _, out returnType, refCustomModifiers: out _); return returnType; } internal static FlowAnalysisAnnotations GetFlowAnalysisAnnotations(this PropertySymbol property) { var annotations = property.GetOwnOrInheritedGetMethod()?.ReturnTypeFlowAnalysisAnnotations ?? FlowAnalysisAnnotations.None; if (property.GetOwnOrInheritedSetMethod()?.Parameters.Last().FlowAnalysisAnnotations is { } setterAnnotations) { annotations |= setterAnnotations; } else if (property is SourcePropertySymbolBase sourceProperty) { // When an auto-property without a setter has an AllowNull annotation, // we need to search for its flow analysis annotations in a more roundabout way // in order to properly handle assignment to the property (e.g. in a constructor). if (sourceProperty.HasAllowNull) { annotations |= FlowAnalysisAnnotations.AllowNull; } if (sourceProperty.HasDisallowNull) { annotations |= FlowAnalysisAnnotations.DisallowNull; } } return annotations; } internal static FlowAnalysisAnnotations GetFlowAnalysisAnnotations(this Symbol? symbol) { return symbol switch { MethodSymbol method => method.ReturnTypeFlowAnalysisAnnotations, PropertySymbol property => property.GetFlowAnalysisAnnotations(), ParameterSymbol parameter => parameter.FlowAnalysisAnnotations, FieldSymbol field => field.FlowAnalysisAnnotations, _ => FlowAnalysisAnnotations.None }; } internal static void GetTypeOrReturnType(this Symbol symbol, out RefKind refKind, out TypeWithAnnotations returnType, out ImmutableArray<CustomModifier> refCustomModifiers) { switch (symbol.Kind) { case SymbolKind.Field: FieldSymbol field = (FieldSymbol)symbol; refKind = RefKind.None; returnType = field.TypeWithAnnotations; refCustomModifiers = ImmutableArray<CustomModifier>.Empty; break; case SymbolKind.Method: MethodSymbol method = (MethodSymbol)symbol; refKind = method.RefKind; returnType = method.ReturnTypeWithAnnotations; refCustomModifiers = method.RefCustomModifiers; break; case SymbolKind.Property: PropertySymbol property = (PropertySymbol)symbol; refKind = property.RefKind; returnType = property.TypeWithAnnotations; refCustomModifiers = property.RefCustomModifiers; break; case SymbolKind.Event: EventSymbol @event = (EventSymbol)symbol; refKind = RefKind.None; returnType = @event.TypeWithAnnotations; refCustomModifiers = ImmutableArray<CustomModifier>.Empty; break; case SymbolKind.Local: LocalSymbol local = (LocalSymbol)symbol; refKind = local.RefKind; returnType = local.TypeWithAnnotations; refCustomModifiers = ImmutableArray<CustomModifier>.Empty; break; case SymbolKind.Parameter: ParameterSymbol parameter = (ParameterSymbol)symbol; refKind = parameter.RefKind; returnType = parameter.TypeWithAnnotations; refCustomModifiers = parameter.RefCustomModifiers; break; case SymbolKind.ErrorType: refKind = RefKind.None; returnType = TypeWithAnnotations.Create((TypeSymbol)symbol); refCustomModifiers = ImmutableArray<CustomModifier>.Empty; break; default: throw ExceptionUtilities.UnexpectedValue(symbol.Kind); } } internal static bool IsImplementableInterfaceMember(this Symbol symbol) { return !symbol.IsSealed && (symbol.IsAbstract || symbol.IsVirtual) && (symbol.ContainingType?.IsInterface ?? false); } internal static bool RequiresInstanceReceiver(this Symbol symbol) { return symbol.Kind switch { SymbolKind.Method => ((MethodSymbol)symbol).RequiresInstanceReceiver, SymbolKind.Property => ((PropertySymbol)symbol).RequiresInstanceReceiver, SymbolKind.Field => ((FieldSymbol)symbol).RequiresInstanceReceiver, SymbolKind.Event => ((EventSymbol)symbol).RequiresInstanceReceiver, _ => throw new ArgumentException("only methods, properties, fields and events can take a receiver", nameof(symbol)), }; } [return: NotNullIfNotNull(nameof(symbol))] private static TISymbol? GetPublicSymbol<TISymbol>(this Symbol? symbol) where TISymbol : class, ISymbol { return (TISymbol?)symbol?.ISymbol; } [return: NotNullIfNotNull(nameof(symbol))] internal static ISymbol? GetPublicSymbol(this Symbol? symbol) { return symbol.GetPublicSymbol<ISymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IMethodSymbol? GetPublicSymbol(this MethodSymbol? symbol) { return symbol.GetPublicSymbol<IMethodSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IPropertySymbol? GetPublicSymbol(this PropertySymbol? symbol) { return symbol.GetPublicSymbol<IPropertySymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static INamedTypeSymbol? GetPublicSymbol(this NamedTypeSymbol? symbol) { return symbol.GetPublicSymbol<INamedTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static INamespaceSymbol? GetPublicSymbol(this NamespaceSymbol? symbol) { return symbol.GetPublicSymbol<INamespaceSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static ITypeSymbol? GetPublicSymbol(this TypeSymbol? symbol) { return symbol.GetPublicSymbol<ITypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static ILocalSymbol? GetPublicSymbol(this LocalSymbol? symbol) { return symbol.GetPublicSymbol<ILocalSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IAssemblySymbol? GetPublicSymbol(this AssemblySymbol? symbol) { return symbol.GetPublicSymbol<IAssemblySymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static INamespaceOrTypeSymbol? GetPublicSymbol(this NamespaceOrTypeSymbol? symbol) { return symbol.GetPublicSymbol<INamespaceOrTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IDiscardSymbol? GetPublicSymbol(this DiscardSymbol? symbol) { return symbol.GetPublicSymbol<IDiscardSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IFieldSymbol? GetPublicSymbol(this FieldSymbol? symbol) { return symbol.GetPublicSymbol<IFieldSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IParameterSymbol? GetPublicSymbol(this ParameterSymbol? symbol) { return symbol.GetPublicSymbol<IParameterSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IRangeVariableSymbol? GetPublicSymbol(this RangeVariableSymbol? symbol) { return symbol.GetPublicSymbol<IRangeVariableSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static ILabelSymbol? GetPublicSymbol(this LabelSymbol? symbol) { return symbol.GetPublicSymbol<ILabelSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IAliasSymbol? GetPublicSymbol(this AliasSymbol? symbol) { return symbol.GetPublicSymbol<IAliasSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IModuleSymbol? GetPublicSymbol(this ModuleSymbol? symbol) { return symbol.GetPublicSymbol<IModuleSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static ITypeParameterSymbol? GetPublicSymbol(this TypeParameterSymbol? symbol) { return symbol.GetPublicSymbol<ITypeParameterSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IArrayTypeSymbol? GetPublicSymbol(this ArrayTypeSymbol? symbol) { return symbol.GetPublicSymbol<IArrayTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IPointerTypeSymbol? GetPublicSymbol(this PointerTypeSymbol? symbol) { return symbol.GetPublicSymbol<IPointerTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IFunctionPointerTypeSymbol? GetPublicSymbol(this FunctionPointerTypeSymbol? symbol) { return symbol.GetPublicSymbol<IFunctionPointerTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static IEventSymbol? GetPublicSymbol(this EventSymbol? symbol) { return symbol.GetPublicSymbol<IEventSymbol>(); } internal static IEnumerable<ISymbol?> GetPublicSymbols(this IEnumerable<Symbol?> symbols) { return symbols.Select(p => p.GetPublicSymbol<ISymbol>()); } private static ImmutableArray<TISymbol> GetPublicSymbols<TISymbol>(this ImmutableArray<Symbol> symbols) where TISymbol : class, ISymbol { if (symbols.IsDefault) { return default; } return symbols.SelectAsArray(p => p.GetPublicSymbol<TISymbol>()); } internal static ImmutableArray<ISymbol> GetPublicSymbols(this ImmutableArray<Symbol> symbols) { return GetPublicSymbols<ISymbol>(symbols); } internal static ImmutableArray<IPropertySymbol> GetPublicSymbols(this ImmutableArray<PropertySymbol> symbols) { return GetPublicSymbols<IPropertySymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<ITypeSymbol> GetPublicSymbols(this ImmutableArray<TypeSymbol> symbols) { return GetPublicSymbols<ITypeSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<INamedTypeSymbol> GetPublicSymbols(this ImmutableArray<NamedTypeSymbol> symbols) { return GetPublicSymbols<INamedTypeSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<ILocalSymbol> GetPublicSymbols(this ImmutableArray<LocalSymbol> symbols) { return GetPublicSymbols<ILocalSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<IEventSymbol> GetPublicSymbols(this ImmutableArray<EventSymbol> symbols) { return GetPublicSymbols<IEventSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<ITypeParameterSymbol> GetPublicSymbols(this ImmutableArray<TypeParameterSymbol> symbols) { return GetPublicSymbols<ITypeParameterSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<IParameterSymbol> GetPublicSymbols(this ImmutableArray<ParameterSymbol> symbols) { return GetPublicSymbols<IParameterSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<IMethodSymbol> GetPublicSymbols(this ImmutableArray<MethodSymbol> symbols) { return GetPublicSymbols<IMethodSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<IAssemblySymbol> GetPublicSymbols(this ImmutableArray<AssemblySymbol> symbols) { return GetPublicSymbols<IAssemblySymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<IFieldSymbol> GetPublicSymbols(this ImmutableArray<FieldSymbol> symbols) { return GetPublicSymbols<IFieldSymbol>(StaticCast<Symbol>.From(symbols)); } internal static ImmutableArray<INamespaceSymbol> GetPublicSymbols(this ImmutableArray<NamespaceSymbol> symbols) { return GetPublicSymbols<INamespaceSymbol>(StaticCast<Symbol>.From(symbols)); } [return: NotNullIfNotNull(nameof(symbol))] internal static TSymbol? GetSymbol<TSymbol>(this ISymbol? symbol) where TSymbol : Symbol { return (TSymbol?)((PublicModel.Symbol?)symbol)?.UnderlyingSymbol; } [return: NotNullIfNotNull(nameof(symbol))] internal static Symbol? GetSymbol(this ISymbol? symbol) { return symbol.GetSymbol<Symbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static TypeSymbol? GetSymbol(this ITypeSymbol? symbol) { return symbol.GetSymbol<TypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static NamedTypeSymbol? GetSymbol(this INamedTypeSymbol? symbol) { return symbol.GetSymbol<NamedTypeSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static AliasSymbol? GetSymbol(this IAliasSymbol? symbol) { return symbol.GetSymbol<AliasSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static LocalSymbol? GetSymbol(this ILocalSymbol? symbol) { return symbol.GetSymbol<LocalSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static AssemblySymbol? GetSymbol(this IAssemblySymbol? symbol) { return symbol.GetSymbol<AssemblySymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static MethodSymbol? GetSymbol(this IMethodSymbol? symbol) { return symbol.GetSymbol<MethodSymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static PropertySymbol? GetSymbol(this IPropertySymbol? symbol) { return symbol.GetSymbol<PropertySymbol>(); } [return: NotNullIfNotNull(nameof(symbol))] internal static FunctionPointerTypeSymbol? GetSymbol(this IFunctionPointerTypeSymbol? symbol) { return symbol.GetSymbol<FunctionPointerTypeSymbol>(); } internal static bool IsRequired(this Symbol symbol) => symbol is FieldSymbol { IsRequired: true } or PropertySymbol { IsRequired: true }; internal static bool ShouldCheckRequiredMembers(this MethodSymbol method) => method is { MethodKind: MethodKind.Constructor, HasSetsRequiredMembers: false }; internal static int GetOverloadResolutionPriority(this Symbol symbol) { Debug.Assert(symbol is MethodSymbol or PropertySymbol); return symbol is MethodSymbol method ? method.OverloadResolutionPriority : ((PropertySymbol)symbol).OverloadResolutionPriority; } internal static bool IsExtensionParameter(this ParameterSymbol parameter) { return parameter.ContainingSymbol is NamedTypeSymbol { IsExtension: true }; } internal static bool IsExtensionParameterImplementation(this ParameterSymbol parameter) { Debug.Assert(parameter.IsDefinition); return parameter.ContainingSymbol is SourceExtensionImplementationMethodSymbol implementationMethod && !implementationMethod.UnderlyingMethod.IsStatic && parameter.Ordinal == 0; } internal static ImmutableArray<TypeWithAnnotations> GetAllTypeArgumentsNoUseSiteDiagnostics(this NamedTypeSymbol symbol) { var count = 0; for (var current = symbol; current is not null; current = current.ContainingType) count += current.TypeArgumentsWithAnnotationsNoUseSiteDiagnostics.Length; var builder = ArrayBuilder<TypeWithAnnotations>.GetInstance(count); symbol.GetAllTypeArgumentsNoUseSiteDiagnostics(builder); return builder.ToImmutableAndFree(); } } }