/// <summary> /// Walks the given ResolvedType and returns all of the type parameters referenced. /// </summary> public static HashSet <TypeParameterName> Apply(ResolvedType res) { var walker = new GetTypeParameters(); walker.OnType(res); return(walker.SharedState.TypeParams); }
/// <summary> /// Reverses the dependencies of type parameters resolving to other type parameters in the given /// dictionary to create a lookup whose keys are type parameters and whose values are all the type /// parameters that can be updated by knowing the resolution of the lookup's associated key. /// </summary> private static ILookup <TypeParameterName, TypeParameterName> GetReplaceable(TypeParameterResolutions.Builder typeParamResolutions) { return(typeParamResolutions .Select(kvp => (kvp.Key, GetTypeParameters.Apply(kvp.Value))) // Get any type parameters in the resolution type. .SelectMany(tup => tup.Item2.Select(value => (tup.Key, value))) // For each type parameter found, match it to the dictionary key. .ToLookup( // Reverse the keys and resulting type parameters to make the lookup. kvp => kvp.value, kvp => kvp.Key)); }
internal PlaceholderMethodSymbol( NamedTypeSymbol container, string name, GetTypeParameters getTypeParameters, GetReturnType getReturnType, GetParameters getParameters) { _container = container; _name = name; _typeParameters = getTypeParameters(this); _returnType = getReturnType(this); _parameters = getParameters(this); }
internal PlaceholderMethodSymbol( NamedTypeSymbol container, CSharpSyntaxNode syntax, string name, GetTypeParameters getTypeParameters, GetReturnType getReturnType, GetParameters getParameters, bool returnValueIsByRef) : this(container, syntax, name) { _typeParameters = getTypeParameters(this); _returnType = getReturnType(this); _parameters = getParameters(this); _returnValueIsByRef = returnValueIsByRef; }
private static IReadOnlyList <T> GetPossibleTs <T>( SourceSymbolContext context, QualifiedName name, ImmutableArray <IType> typeArguments, TryGetT <T> tryGetT, GetLocalTs <T> getLocalTs, GetFullyQualifiedName <T> getFullyQualifiedName, GetTypeParameters <T> getTypeParameters) where T : class { List <T> possibleTs; if (name.Parent is null) { // local ts have priority over top level ts, // and an inner local t hides an outer local t // local ts can only have simple names, so we can skip this check if the name is not simple var scope = context.Scope; while (scope != null) { possibleTs = getLocalTs(scope) .Where( x => getFullyQualifiedName(x) == name && getTypeParameters(x).Length == typeArguments.Length) .ToList(); if (possibleTs.Count > 0) { return(possibleTs); } scope = scope.DeclaringMethod; } } var assemblies = context.Assembly.ReferencedAssembliesAndSelf; // types in the innermost namespace have priority over types in its parent namespace, // which have priority over types in its parent etc. var @namespace = context.NameSpace; while (@namespace != null) { var possibleName = name.Prepend(@namespace); possibleTs = LookupPossibleName(possibleName).ToList(); if (possibleTs.Count > 0) { return(possibleTs); } @namespace = @namespace?.Parent; } // Types in the global namespace have priority over types defined in imports possibleTs = LookupPossibleName(name).ToList(); if (possibleTs.Count > 0) { return(possibleTs); } // look for types in imports if (name.Parent is null) { // imports only bring the top level types into scope, so they are only relevant if the name is simple; var possibleNames = context.Imports.Select(x => x.Append(name)).ToList(); return (possibleNames .SelectMany(LookupPossibleName) .ToList()); } return(Array.Empty <T>()); IEnumerable <T> LookupPossibleName(QualifiedName possibleName) { return(assemblies.Select(x => { tryGetT(x, possibleName, out var t); return t; }).Where(x => x != null && getTypeParameters(x).Length == typeArguments.Length) !); } }