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); }