コード例 #1
0
            private bool InitializeDelegatedConstructor(int argumentCount, INamedTypeSymbol namedType, CancellationToken cancellationToken)
            {
                // We can't resolve overloads across language.
                if (_document.Project.Language != namedType.Language)
                {
                    return(false);
                }

                // Look for constructors in this specified type that are:
                // 1. Non-implicit.  We don't want to add `: base()` as that's just redundant for subclasses and `:
                //    this()` won't even work as we won't have an implicit constructor once we add this new constructor.
                // 2. Accessible.  We obviously need our constructor to be able to call that other constructor.
                // 3. Won't cause a cycle.  i.e. if we're generating a new constructor from an existing constructor,
                //    then we don't want it calling back into us.
                // 4. Are compatible with the parameters we're generating for this constructor.  Compatible means there
                //    exists an implicit conversion from the new constructor's parameter types to the existing
                //    constructor's parameter types.
                var parameterTypesToMatch = ParameterTypes.Take(argumentCount).ToList();
                var delegatedConstructor  = namedType.InstanceConstructors
                                            .Where(c => IsSymbolAccessible(c, _document))
                                            .Where(c => !c.IsImplicitlyDeclared)
                                            .Where(c => c.Parameters.Length == parameterTypesToMatch.Count)
                                            .Where(c => _service.CanDelegateThisConstructor(this, _document, c, cancellationToken))
                                            .Where(c => IsCompatible(c, parameterTypesToMatch))
                                            .FirstOrDefault();

                if (delegatedConstructor == null)
                {
                    return(false);
                }

                // Map the first N parameters to the other constructor in this type.  Then
                // try to map any further parameters to existing fields.  Finally, generate
                // new fields if no such parameters exist.

                // Find the names of the parameters that will follow the parameters we're
                // delegating.
                var remainingArguments      = _arguments.Skip(argumentCount).ToImmutableArray();
                var remainingParameterNames = _service.GenerateParameterNames(
                    _document, remainingArguments,
                    delegatedConstructor.Parameters.Select(p => p.Name).ToList(),
                    _parameterNamingRule,
                    cancellationToken);

                // Can't generate the constructor if the parameter names we're copying over forcibly
                // conflict with any names we generated.
                if (delegatedConstructor.Parameters.Select(p => p.Name).Intersect(remainingParameterNames.Select(n => n.BestNameForParameter)).Any())
                {
                    return(false);
                }

                var remainingParameterTypes = ParameterTypes.Skip(argumentCount).ToImmutableArray();

                _delegatedConstructor = delegatedConstructor;
                GetParameters(remainingArguments, remainingParameterTypes, remainingParameterNames, cancellationToken);
                return(true);
            }