protected FunctionDescriptor doSubstitute()

in core/descriptors/src/org/jetbrains/kotlin/descriptors/impl/FunctionDescriptorImpl.java [611:787]


    protected FunctionDescriptor doSubstitute(@NotNull CopyConfiguration configuration) {
        boolean[] wereChanges = new boolean[1];
        Annotations resultAnnotations =
                configuration.additionalAnnotations != null
                ? AnnotationsKt.composeAnnotations(getAnnotations(), configuration.additionalAnnotations)
                : getAnnotations();

        FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
                configuration.newOwner, configuration.original, configuration.kind, configuration.name, resultAnnotations,
                getSourceToUseForCopy(configuration.preserveSourceElement, configuration.original));

        List<TypeParameterDescriptor> unsubstitutedTypeParameters =
                configuration.newTypeParameters == null ? getTypeParameters() : configuration.newTypeParameters;

        wereChanges[0] |= !unsubstitutedTypeParameters.isEmpty();

        List<TypeParameterDescriptor> substitutedTypeParameters =
                new ArrayList<TypeParameterDescriptor>(unsubstitutedTypeParameters.size());
        final TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
                unsubstitutedTypeParameters, configuration.substitution, substitutedDescriptor, substitutedTypeParameters, wereChanges
        );
        if (substitutor == null) return null;

        List<ReceiverParameterDescriptor> substitutedContextReceiverParameters = new ArrayList<ReceiverParameterDescriptor>();
        if (!configuration.newContextReceiverParameters.isEmpty()) {
            int index = 0;
            for (ReceiverParameterDescriptor newContextReceiverParameter : configuration.newContextReceiverParameters) {
                KotlinType substitutedContextReceiverType =
                        substitutor.substitute(newContextReceiverParameter.getType(), Variance.IN_VARIANCE);
                if (substitutedContextReceiverType == null) {
                    return null;
                }
                ReceiverParameterDescriptor substitutedContextReceiverParameter =
                        DescriptorFactory.createContextReceiverParameterForCallable(substitutedDescriptor, substitutedContextReceiverType,
                                                                                    ((ImplicitContextReceiver)newContextReceiverParameter.getValue()).getCustomLabelName(),
                                                                                    newContextReceiverParameter.getAnnotations(),
                                                                                    index++);
                substitutedContextReceiverParameters.add(substitutedContextReceiverParameter);

                wereChanges[0] |= substitutedContextReceiverType != newContextReceiverParameter.getType();
            }
        }

        ReceiverParameterDescriptor substitutedReceiverParameter = null;
        if (configuration.newExtensionReceiverParameter != null) {
            KotlinType substitutedExtensionReceiverType =
                    substitutor.substitute(configuration.newExtensionReceiverParameter.getType(), Variance.IN_VARIANCE);
            if (substitutedExtensionReceiverType == null) {
                return null;
            }
            substitutedReceiverParameter = new ReceiverParameterDescriptorImpl(
                    substitutedDescriptor,
                    new ExtensionReceiver(
                            substitutedDescriptor, substitutedExtensionReceiverType, configuration.newExtensionReceiverParameter.getValue()
                    ),
                    configuration.newExtensionReceiverParameter.getAnnotations()
            );

            wereChanges[0] |= substitutedExtensionReceiverType != configuration.newExtensionReceiverParameter.getType();
        }

        ReceiverParameterDescriptor substitutedExpectedThis = null;
        if (configuration.dispatchReceiverParameter != null) {
            // When generating fake-overridden member it's dispatch receiver parameter has type of Base, and it's correct.
            // E.g.
            // class Base { fun foo() }
            // class Derived : Base
            // val x: Base
            // if (x is Derived) {
            //    // `x` shouldn't be marked as smart-cast
            //    // but it would if fake-overridden `foo` had `Derived` as it's dispatch receiver parameter type
            //    x.foo()
            // }
            substitutedExpectedThis = configuration.dispatchReceiverParameter.substitute(substitutor);
            if (substitutedExpectedThis == null) {
                return null;
            }

            wereChanges[0] |= substitutedExpectedThis != configuration.dispatchReceiverParameter;
        }

        List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(
                substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor, configuration.dropOriginalInContainingParts,
                configuration.preserveSourceElement, wereChanges
        );
        if (substitutedValueParameters == null) {
            return null;
        }

        KotlinType substitutedReturnType = substitutor.substitute(configuration.newReturnType, Variance.OUT_VARIANCE);
        if (substitutedReturnType == null) {
            return null;
        }

        wereChanges[0] |= substitutedReturnType != configuration.newReturnType;

        if (!wereChanges[0] && configuration.justForTypeSubstitution) {
            return this;
        }

        substitutedDescriptor.initialize(
                substitutedReceiverParameter, substitutedExpectedThis, substitutedContextReceiverParameters,
                substitutedTypeParameters,
                substitutedValueParameters,
                substitutedReturnType,
                configuration.newModality,
                configuration.newVisibility
        );
        substitutedDescriptor.setOperator(isOperator);
        substitutedDescriptor.setInfix(isInfix);
        substitutedDescriptor.setExternal(isExternal);
        substitutedDescriptor.setInline(isInline);
        substitutedDescriptor.setTailrec(isTailrec);
        substitutedDescriptor.setSuspend(isSuspend);
        substitutedDescriptor.setExpect(isExpect);
        substitutedDescriptor.setActual(isActual);
        substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames);
        substitutedDescriptor.setHiddenToOvercomeSignatureClash(configuration.isHiddenToOvercomeSignatureClash);
        substitutedDescriptor.setHiddenForResolutionEverywhereBesideSupercalls(configuration.isHiddenForResolutionEverywhereBesideSupercalls);

        substitutedDescriptor.setHasSynthesizedParameterNames(
                configuration.newHasSynthesizedParameterNames != null ? configuration.newHasSynthesizedParameterNames : hasSynthesizedParameterNames
        );

        if (!configuration.userDataMap.isEmpty() || userDataMap != null) {
            Map<UserDataKey<?>, Object> newMap = configuration.userDataMap;

            if (userDataMap != null) {
                for (Map.Entry<UserDataKey<?>, Object> entry : userDataMap.entrySet()) {
                    if (!newMap.containsKey(entry.getKey())) {
                        newMap.put(entry.getKey(), entry.getValue());
                    }
                }
            }

            if (newMap.size() == 1) {
                substitutedDescriptor.userDataMap =
                        Collections.<UserDataKey<?>, Object>singletonMap(
                                newMap.keySet().iterator().next(), newMap.values().iterator().next());
            }
            else {
                substitutedDescriptor.userDataMap = newMap;
            }
        }

        if (configuration.signatureChange || getInitialSignatureDescriptor() != null) {
            FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this);
            FunctionDescriptor initialSignatureSubstituted = initialSignature.substitute(substitutor);
            substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted);
        }

        if (configuration.copyOverrides && !getOriginal().getOverriddenDescriptors().isEmpty()) {
            if (configuration.substitution.isEmpty()) {
                Function0<Collection<FunctionDescriptor>> overriddenFunctionsTask = lazyOverriddenFunctionsTask;
                if (overriddenFunctionsTask != null) {
                    substitutedDescriptor.lazyOverriddenFunctionsTask = overriddenFunctionsTask;
                }
                else {
                    substitutedDescriptor.setOverriddenDescriptors(getOverriddenDescriptors());
                }
            }
            else {
                substitutedDescriptor.lazyOverriddenFunctionsTask = new Function0<Collection<FunctionDescriptor>>() {
                    @Override
                    public Collection<FunctionDescriptor> invoke() {
                        Collection<FunctionDescriptor> result = new SmartList<FunctionDescriptor>();
                        for (FunctionDescriptor overriddenFunction : getOverriddenDescriptors()) {
                            result.add(overriddenFunction.substitute(substitutor));
                        }
                        return result;
                    }
                };
            }
        }

        return substitutedDescriptor;
    }