Пример #1
0
        protected static ImmutableArray <ITypeParameterSymbol> GetTypeParameters(
            State state,
            SemanticModel semanticModel,
            IEnumerable <SyntaxNode> typeArguments,
            CancellationToken cancellationToken)
        {
            var arguments = typeArguments.ToList();
            var arity     = arguments.Count;

            using var _ = ArrayBuilder <ITypeParameterSymbol> .GetInstance(out var typeParameters);

            // For anything that was a type parameter, just use the name (if we haven't already
            // used it).  Otherwise, synthesize new names for the parameters.
            using var namesDisposer = ArrayBuilder <string> .GetInstance(arity, out var names);

            using var isFixedDisposer = ArrayBuilder <bool> .GetInstance(arity, out var isFixed);

            for (var i = 0; i < arity; i++)
            {
                var argument = i < arguments.Count ? arguments[i] : null;
                var type     = argument == null ? null : semanticModel.GetTypeInfo(argument, cancellationToken).Type;
                if (type is ITypeParameterSymbol typeParameter)
                {
                    var name = type.Name;

                    // If we haven't seen this type parameter already, then we can use this name
                    // and 'fix' it so that it doesn't change. Otherwise, use it, but allow it
                    // to be changed if it collides with anything else.
                    isFixed.Add(!names.Contains(name));
                    names.Add(name);
                    typeParameters.Add(typeParameter);
                }
                else
                {
                    isFixed.Add(false);
                    names.Add("T");
                    typeParameters.Add(null);
                }
            }

            // We can use a type parameter as long as it hasn't been used in an outer type.
            var canUse = state.TypeToGenerateInOpt == null
                ? (Func <string, bool>)null
                : s => state.TypeToGenerateInOpt.GetAllTypeParameters().All(t => t.Name != s);

            NameGenerator.EnsureUniquenessInPlace(names, isFixed, canUse);
            for (var i = 0; i < names.Count; i++)
            {
                if (typeParameters[i] == null || typeParameters[i].Name != names[i])
                {
                    typeParameters[i] = CodeGenerationSymbolFactory.CreateTypeParameterSymbol(names[i]);
                }
            }

            return(typeParameters.ToImmutable());
        }