001    /*
002     * Copyright 2010-2015 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.kotlin.descriptors.impl;
018    
019    import kotlin.jvm.functions.Function0;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.descriptors.*;
023    import org.jetbrains.kotlin.descriptors.annotations.Annotations;
024    import org.jetbrains.kotlin.name.Name;
025    import org.jetbrains.kotlin.resolve.DescriptorFactory;
026    import org.jetbrains.kotlin.types.DescriptorSubstitutor;
027    import org.jetbrains.kotlin.types.KotlinType;
028    import org.jetbrains.kotlin.types.TypeSubstitutor;
029    import org.jetbrains.kotlin.types.Variance;
030    import org.jetbrains.kotlin.utils.CollectionsKt;
031    import org.jetbrains.kotlin.utils.SmartSet;
032    
033    import java.util.*;
034    
035    public abstract class FunctionDescriptorImpl extends DeclarationDescriptorNonRootImpl implements FunctionDescriptor {
036        private List<TypeParameterDescriptor> typeParameters;
037        private List<ValueParameterDescriptor> unsubstitutedValueParameters;
038        private KotlinType unsubstitutedReturnType;
039        private ReceiverParameterDescriptor extensionReceiverParameter;
040        private ReceiverParameterDescriptor dispatchReceiverParameter;
041        private Modality modality;
042        private Visibility visibility = Visibilities.UNKNOWN;
043        private boolean isOperator = false;
044        private boolean isInfix = false;
045        private boolean isExternal = false;
046        private boolean isInline = false;
047        private boolean isTailrec = false;
048        private boolean isHidden = false;
049        private boolean hasStableParameterNames = true;
050        private boolean hasSynthesizedParameterNames = false;
051        private Collection<? extends FunctionDescriptor> overriddenFunctions = null;
052        private volatile Function0<Set<FunctionDescriptor>> lazyOverriddenFunctionsTask = null;
053        private final FunctionDescriptor original;
054        private final Kind kind;
055        @Nullable
056        private FunctionDescriptor initialSignatureDescriptor = null;
057    
058        protected FunctionDescriptorImpl(
059                @NotNull DeclarationDescriptor containingDeclaration,
060                @Nullable FunctionDescriptor original,
061                @NotNull Annotations annotations,
062                @NotNull Name name,
063                @NotNull Kind kind,
064                @NotNull SourceElement source
065        ) {
066            super(containingDeclaration, annotations, name, source);
067            this.original = original == null ? this : original;
068            this.kind = kind;
069        }
070    
071        @NotNull
072        public FunctionDescriptorImpl initialize(
073                @Nullable KotlinType receiverParameterType,
074                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
075                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
076                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
077                @Nullable KotlinType unsubstitutedReturnType,
078                @Nullable Modality modality,
079                @NotNull Visibility visibility
080        ) {
081            this.typeParameters = CollectionsKt.toReadOnlyList(typeParameters);
082            this.unsubstitutedValueParameters = unsubstitutedValueParameters;
083            this.unsubstitutedReturnType = unsubstitutedReturnType;
084            this.modality = modality;
085            this.visibility = visibility;
086            this.extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverParameterType);
087            this.dispatchReceiverParameter = dispatchReceiverParameter;
088    
089            for (int i = 0; i < typeParameters.size(); ++i) {
090                TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
091                if (typeParameterDescriptor.getIndex() != i) {
092                    throw new IllegalStateException(typeParameterDescriptor + " index is " + typeParameterDescriptor.getIndex() + " but position is " + i);
093                }
094            }
095    
096            for (int i = 0; i < unsubstitutedValueParameters.size(); ++i) {
097                // TODO fill me
098                int firstValueParameterOffset = 0; // receiverParameter.exists() ? 1 : 0;
099                ValueParameterDescriptor valueParameterDescriptor = unsubstitutedValueParameters.get(i);
100                if (valueParameterDescriptor.getIndex() != i + firstValueParameterOffset) {
101                    throw new IllegalStateException(valueParameterDescriptor + "index is " + valueParameterDescriptor.getIndex() + " but position is " + i);
102                }
103            }
104    
105            return this;
106        }
107    
108        public void setVisibility(@NotNull Visibility visibility) {
109            this.visibility = visibility;
110        }
111    
112        public void setOperator(boolean isOperator) {
113            this.isOperator = isOperator;
114        }
115    
116        public void setInfix(boolean isInfix) {
117            this.isInfix = isInfix;
118        }
119    
120        public void setExternal(boolean isExternal) {
121            this.isExternal = isExternal;
122        }
123    
124        public void setInline(boolean isInline) {
125            this.isInline = isInline;
126        }
127    
128        public void setTailrec(boolean isTailrec) {
129            this.isTailrec = isTailrec;
130        }
131    
132        public void setHidden(boolean hidden) {
133            isHidden = hidden;
134        }
135    
136        public void setReturnType(@NotNull KotlinType unsubstitutedReturnType) {
137            if (this.unsubstitutedReturnType != null) {
138                // TODO: uncomment and fix tests
139                //throw new IllegalStateException("returnType already set");
140            }
141            this.unsubstitutedReturnType = unsubstitutedReturnType;
142        }
143    
144        public void setHasStableParameterNames(boolean hasStableParameterNames) {
145            this.hasStableParameterNames = hasStableParameterNames;
146        }
147    
148        public void setHasSynthesizedParameterNames(boolean hasSynthesizedParameterNames) {
149            this.hasSynthesizedParameterNames = hasSynthesizedParameterNames;
150        }
151    
152        @Nullable
153        @Override
154        public ReceiverParameterDescriptor getExtensionReceiverParameter() {
155            return extensionReceiverParameter;
156        }
157    
158        @Nullable
159        @Override
160        public ReceiverParameterDescriptor getDispatchReceiverParameter() {
161            return dispatchReceiverParameter;
162        }
163    
164        @NotNull
165        @Override
166        public Collection<? extends FunctionDescriptor> getOverriddenDescriptors() {
167            performOverriddenLazyCalculationIfNeeded();
168            return overriddenFunctions != null ? overriddenFunctions : Collections.<FunctionDescriptor>emptyList();
169        }
170    
171        private void performOverriddenLazyCalculationIfNeeded() {
172            Function0<Set<FunctionDescriptor>> overriddenTask = lazyOverriddenFunctionsTask;
173            if (overriddenTask != null) {
174                overriddenFunctions = overriddenTask.invoke();
175                // Here it's important that this assignment is strictly after previous one
176                // `lazyOverriddenFunctionsTask` is volatile, so when someone will see that it's null,
177                // he can read consistent collection from `overriddenFunctions`,
178                // because it's assignment happens-before of "lazyOverriddenFunctionsTask = null"
179                lazyOverriddenFunctionsTask = null;
180            }
181        }
182    
183        @NotNull
184        @Override
185        public Modality getModality() {
186            return modality;
187        }
188    
189        @NotNull
190        @Override
191        public Visibility getVisibility() {
192            return visibility;
193        }
194    
195        @Override
196        public boolean isOperator() {
197            if (isOperator) return true;
198    
199            for (FunctionDescriptor descriptor : getOriginal().getOverriddenDescriptors()) {
200                if (descriptor.isOperator()) return true;
201            }
202    
203            return false;
204        }
205    
206        @Override
207        public boolean isInfix() {
208            if (isInfix) return true;
209    
210            for (FunctionDescriptor descriptor : getOriginal().getOverriddenDescriptors()) {
211                if (descriptor.isInfix()) return true;
212            }
213    
214            return false;
215        }
216    
217        @Override
218        public boolean isExternal() {
219            return isExternal;
220        }
221    
222        @Override
223        public boolean isInline() {
224            return isInline;
225        }
226    
227        @Override
228        public boolean isTailrec() {
229            return isTailrec;
230        }
231    
232        @Override
233        public boolean isHiddenToOvercomeSignatureClash() {
234            return isHidden;
235        }
236    
237        @Override
238        public void setOverriddenDescriptors(@NotNull Collection<? extends CallableMemberDescriptor> overriddenDescriptors) {
239            //noinspection unchecked
240            overriddenFunctions = (Collection<? extends FunctionDescriptor>) overriddenDescriptors;
241        }
242    
243        @Override
244        @NotNull
245        public List<TypeParameterDescriptor> getTypeParameters() {
246            return typeParameters;
247        }
248    
249        @Override
250        @NotNull
251        public List<ValueParameterDescriptor> getValueParameters() {
252            return unsubstitutedValueParameters;
253        }
254    
255        @Override
256        public boolean hasStableParameterNames() {
257            return hasStableParameterNames;
258        }
259    
260        @Override
261        public boolean hasSynthesizedParameterNames() {
262            return hasSynthesizedParameterNames;
263        }
264    
265        @Override
266        public KotlinType getReturnType() {
267            return unsubstitutedReturnType;
268        }
269    
270        @NotNull
271        @Override
272        public FunctionDescriptor getOriginal() {
273            return original == this ? this : original.getOriginal();
274        }
275    
276        @NotNull
277        @Override
278        public Kind getKind() {
279            return kind;
280        }
281    
282        @Override
283        public FunctionDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
284            if (originalSubstitutor.isEmpty()) {
285                return this;
286            }
287            return doSubstitute(newCopyBuilder(originalSubstitutor).setOriginal(getOriginal()));
288        }
289    
290        @Nullable
291        protected KotlinType getExtensionReceiverParameterType() {
292            if (extensionReceiverParameter == null) return null;
293            return extensionReceiverParameter.getType();
294        }
295    
296        public class CopyConfiguration {
297            protected @NotNull TypeSubstitutor originalSubstitutor;
298            protected @NotNull DeclarationDescriptor newOwner;
299            protected @NotNull Modality newModality;
300            protected @NotNull Visibility newVisibility;
301            protected @Nullable FunctionDescriptor original = null;
302            protected @NotNull Kind kind;
303            protected @NotNull List<ValueParameterDescriptor> newValueParameterDescriptors;
304            protected @Nullable KotlinType newExtensionReceiverParameterType;
305            protected @NotNull KotlinType newReturnType;
306            protected @Nullable Name name;
307            protected boolean copyOverrides = true;
308            protected boolean signatureChange = false;
309            protected boolean preserveSourceElement = false;
310            protected boolean dropOriginalInContainingParts = false;
311            private boolean isHiddenToOvercomeSignatureClash;
312            private List<TypeParameterDescriptor> newTypeParameters = null;
313    
314            public CopyConfiguration(
315                    @NotNull TypeSubstitutor originalSubstitutor,
316                    @NotNull DeclarationDescriptor newOwner,
317                    @NotNull Modality newModality,
318                    @NotNull Visibility newVisibility,
319                    @NotNull Kind kind,
320                    @NotNull List<ValueParameterDescriptor> newValueParameterDescriptors,
321                    @Nullable KotlinType newExtensionReceiverParameterType,
322                    @NotNull KotlinType newReturnType,
323                    @Nullable Name name
324            ) {
325                this.originalSubstitutor = originalSubstitutor;
326                this.newOwner = newOwner;
327                this.newModality = newModality;
328                this.newVisibility = newVisibility;
329                this.kind = kind;
330                this.newValueParameterDescriptors = newValueParameterDescriptors;
331                this.newExtensionReceiverParameterType = newExtensionReceiverParameterType;
332                this.newReturnType = newReturnType;
333                this.name = name;
334                this.isHiddenToOvercomeSignatureClash = isHiddenToOvercomeSignatureClash();
335            }
336    
337            @NotNull
338            protected CopyConfiguration setOwner(@NotNull DeclarationDescriptor owner) {
339                this.newOwner = owner;
340                return this;
341            }
342    
343            @NotNull
344            public CopyConfiguration setModality(@NotNull Modality modality) {
345                this.newModality = modality;
346                return this;
347            }
348    
349            @NotNull
350            public CopyConfiguration setVisibility(@NotNull Visibility visibility) {
351                this.newVisibility = visibility;
352                return this;
353            }
354    
355            @NotNull
356            public CopyConfiguration setKind(@NotNull Kind kind) {
357                this.kind = kind;
358                return this;
359            }
360    
361            @NotNull
362            public CopyConfiguration setCopyOverrides(boolean copyOverrides) {
363                this.copyOverrides = copyOverrides;
364                return this;
365            }
366    
367            @NotNull
368            public CopyConfiguration setName(@NotNull Name name) {
369                this.name = name;
370                return this;
371            }
372    
373            @NotNull
374            public CopyConfiguration setValueParameters(@NotNull List<ValueParameterDescriptor> parameters) {
375                this.newValueParameterDescriptors = parameters;
376                return this;
377            }
378    
379            @NotNull
380            public CopyConfiguration setTypeParameters(@NotNull List<TypeParameterDescriptor> parameters) {
381                this.newTypeParameters = parameters;
382                return this;
383            }
384    
385            public CopyConfiguration setReturnType(@NotNull KotlinType type) {
386                this.newReturnType = type;
387                return this;
388            }
389    
390            public CopyConfiguration setExtensionReceiverType(@Nullable KotlinType type) {
391                this.newExtensionReceiverParameterType = type;
392                return this;
393            }
394    
395            @NotNull
396            public CopyConfiguration setOriginal(@NotNull FunctionDescriptor original) {
397                this.original = original;
398                return this;
399            }
400    
401            @NotNull
402            public CopyConfiguration setSignatureChange() {
403                this.signatureChange = true;
404                return this;
405            }
406    
407            @NotNull
408            public CopyConfiguration setPreserveSourceElement() {
409                this.preserveSourceElement = true;
410                return this;
411            }
412    
413            @NotNull
414            public CopyConfiguration setDropOriginalInContainingParts() {
415                this.dropOriginalInContainingParts = true;
416                return this;
417            }
418    
419            @NotNull
420            public CopyConfiguration setHidden() {
421                isHiddenToOvercomeSignatureClash = true;
422                return this;
423            }
424    
425            @Nullable
426            public FunctionDescriptor build() {
427                return doSubstitute(this);
428            }
429    
430            @Nullable
431            public FunctionDescriptor getOriginal() {
432                return original;
433            }
434    
435            @NotNull
436            public TypeSubstitutor getOriginalSubstitutor() {
437                return originalSubstitutor;
438            }
439        }
440    
441        @NotNull
442        public CopyConfiguration newCopyBuilder() {
443            return newCopyBuilder(TypeSubstitutor.EMPTY);
444        }
445    
446        @NotNull
447        private CopyConfiguration newCopyBuilder(@NotNull TypeSubstitutor substitutor) {
448            return new CopyConfiguration(
449                    substitutor,
450                    getContainingDeclaration(), getModality(), getVisibility(), getKind(), getValueParameters(),
451                    getExtensionReceiverParameterType(), getReturnType(), null);
452        }
453    
454        @Nullable
455        protected FunctionDescriptor doSubstitute(@NotNull CopyConfiguration configuration) {
456            FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
457                    configuration.newOwner, configuration.original, configuration.kind, configuration.name,
458                    configuration.preserveSourceElement);
459    
460            List<TypeParameterDescriptor> substitutedTypeParameters;
461            final TypeSubstitutor substitutor;
462    
463            if (configuration.newTypeParameters == null) {
464                List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
465                substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
466                substitutor = DescriptorSubstitutor.substituteTypeParameters(
467                        originalTypeParameters, configuration.originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters
468                );
469            }
470            else {
471                // They should be already substituted
472                substitutedTypeParameters = configuration.newTypeParameters;
473                substitutor = configuration.originalSubstitutor;
474            }
475    
476            KotlinType substitutedReceiverParameterType = null;
477            if (configuration.newExtensionReceiverParameterType != null) {
478                substitutedReceiverParameterType = substitutor.substitute(configuration.newExtensionReceiverParameterType, Variance.IN_VARIANCE);
479                if (substitutedReceiverParameterType == null) {
480                    return null;
481                }
482            }
483    
484            ReceiverParameterDescriptor substitutedExpectedThis = null;
485            if (dispatchReceiverParameter != null) {
486                // When generating fake-overridden member it's dispatch receiver parameter has type of Base, and it's correct.
487                // E.g.
488                // class Base { fun foo() }
489                // class Derived : Base
490                // val x: Base
491                // if (x is Derived) {
492                //    // `x` shouldn't be marked as smart-cast
493                //    // but it would if fake-overridden `foo` had `Derived` as it's dispatch receiver parameter type
494                //    x.foo()
495                // }
496                substitutedExpectedThis = dispatchReceiverParameter.substitute(substitutor);
497                if (substitutedExpectedThis == null) {
498                    return null;
499                }
500            }
501    
502            List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(
503                    substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor, configuration.dropOriginalInContainingParts
504            );
505            if (substitutedValueParameters == null) {
506                return null;
507            }
508    
509            KotlinType substitutedReturnType = substitutor.substitute(configuration.newReturnType, Variance.OUT_VARIANCE);
510            if (substitutedReturnType == null) {
511                return null;
512            }
513    
514            substitutedDescriptor.initialize(
515                    substitutedReceiverParameterType,
516                    substitutedExpectedThis,
517                    substitutedTypeParameters,
518                    substitutedValueParameters,
519                    substitutedReturnType,
520                    configuration.newModality,
521                    configuration.newVisibility
522            );
523            substitutedDescriptor.setOperator(isOperator);
524            substitutedDescriptor.setInfix(isInfix);
525            substitutedDescriptor.setExternal(isExternal);
526            substitutedDescriptor.setInline(isInline);
527            substitutedDescriptor.setTailrec(isTailrec);
528            substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames);
529            substitutedDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames);
530            substitutedDescriptor.setHidden(configuration.isHiddenToOvercomeSignatureClash);
531    
532            if (configuration.signatureChange || getInitialSignatureDescriptor() != null) {
533                FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this);
534                FunctionDescriptor initialSignatureSubstituted = initialSignature.substitute(substitutor);
535                substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted);
536            }
537    
538            if (configuration.copyOverrides && !getOriginal().getOverriddenDescriptors().isEmpty()) {
539                if (configuration.originalSubstitutor.isEmpty()) {
540                    Function0<Set<FunctionDescriptor>> overriddenFunctionsTask = lazyOverriddenFunctionsTask;
541                    if (overriddenFunctionsTask != null) {
542                        substitutedDescriptor.lazyOverriddenFunctionsTask = overriddenFunctionsTask;
543                    }
544                    else {
545                        substitutedDescriptor.setOverriddenDescriptors(getOverriddenDescriptors());
546                    }
547                }
548                else {
549                    substitutedDescriptor.lazyOverriddenFunctionsTask = new Function0<Set<FunctionDescriptor>>() {
550                        @Override
551                        public Set<FunctionDescriptor> invoke() {
552                            SmartSet<FunctionDescriptor> result = SmartSet.create();
553                            for (FunctionDescriptor overriddenFunction : getOverriddenDescriptors()) {
554                                result.add(overriddenFunction.substitute(substitutor));
555                            }
556                            return result;
557                        }
558                    };
559                }
560            }
561    
562            return substitutedDescriptor;
563        }
564    
565        @NotNull
566        protected abstract FunctionDescriptorImpl createSubstitutedCopy(
567                @NotNull DeclarationDescriptor newOwner,
568                @Nullable FunctionDescriptor original,
569                @NotNull Kind kind,
570                @Nullable Name newName,
571                boolean preserveSource
572        );
573    
574        @NotNull
575        protected SourceElement getSourceToUseForCopy(boolean preserveSource, @Nullable FunctionDescriptor original) {
576            return preserveSource
577                   ? (original != null ? original.getSource() : getOriginal().getSource())
578                   : SourceElement.NO_SOURCE;
579        }
580    
581        @Override
582        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
583            return visitor.visitFunctionDescriptor(this, data);
584        }
585    
586        @Nullable
587        public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
588                FunctionDescriptor substitutedDescriptor,
589                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
590                @NotNull TypeSubstitutor substitutor,
591                boolean dropOriginal
592        ) {
593            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(unsubstitutedValueParameters.size());
594            for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
595                // TODO : Lazy?
596                KotlinType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
597                KotlinType varargElementType = unsubstitutedValueParameter.getVarargElementType();
598                KotlinType substituteVarargElementType =
599                        varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
600                if (substitutedType == null) return null;
601                result.add(
602                        new ValueParameterDescriptorImpl(
603                                substitutedDescriptor,
604                                dropOriginal ? null : unsubstitutedValueParameter,
605                                unsubstitutedValueParameter.getIndex(),
606                                unsubstitutedValueParameter.getAnnotations(),
607                                unsubstitutedValueParameter.getName(),
608                                substitutedType,
609                                unsubstitutedValueParameter.declaresDefaultValue(),
610                                unsubstitutedValueParameter.isCrossinline(),
611                                unsubstitutedValueParameter.isNoinline(),
612                                substituteVarargElementType,
613                                SourceElement.NO_SOURCE
614                        )
615                );
616            }
617            return result;
618        }
619    
620        @Override
621        @Nullable
622        public FunctionDescriptor getInitialSignatureDescriptor() {
623            return initialSignatureDescriptor;
624        }
625    
626        public void setInitialSignatureDescriptor(@Nullable FunctionDescriptor initialSignatureDescriptor) {
627            this.initialSignatureDescriptor = initialSignatureDescriptor;
628        }
629    }