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 newCopyBuilder(originalSubstitutor).setOriginal(getOriginal()).build();
288        }
289    
290        @Nullable
291        protected KotlinType getExtensionReceiverParameterType() {
292            if (extensionReceiverParameter == null) return null;
293            return extensionReceiverParameter.getType();
294        }
295    
296        public class CopyConfiguration implements SimpleFunctionDescriptor.CopyBuilder<FunctionDescriptor> {
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            @Override
338            @NotNull
339            public CopyConfiguration setOwner(@NotNull DeclarationDescriptor owner) {
340                this.newOwner = owner;
341                return this;
342            }
343    
344            @Override
345            @NotNull
346            public CopyConfiguration setModality(@NotNull Modality modality) {
347                this.newModality = modality;
348                return this;
349            }
350    
351            @Override
352            @NotNull
353            public CopyConfiguration setVisibility(@NotNull Visibility visibility) {
354                this.newVisibility = visibility;
355                return this;
356            }
357    
358            @Override
359            @NotNull
360            public CopyConfiguration setKind(@NotNull Kind kind) {
361                this.kind = kind;
362                return this;
363            }
364    
365            @Override
366            @NotNull
367            public CopyConfiguration setCopyOverrides(boolean copyOverrides) {
368                this.copyOverrides = copyOverrides;
369                return this;
370            }
371    
372            @Override
373            @NotNull
374            public CopyConfiguration setName(@NotNull Name name) {
375                this.name = name;
376                return this;
377            }
378    
379            @Override
380            @NotNull
381            public CopyConfiguration setValueParameters(@NotNull List<ValueParameterDescriptor> parameters) {
382                this.newValueParameterDescriptors = parameters;
383                return this;
384            }
385    
386            @Override
387            @NotNull
388            public CopyConfiguration setTypeParameters(@NotNull List<TypeParameterDescriptor> parameters) {
389                this.newTypeParameters = parameters;
390                return this;
391            }
392    
393            @NotNull
394            @Override
395            public CopyConfiguration setReturnType(@NotNull KotlinType type) {
396                this.newReturnType = type;
397                return this;
398            }
399    
400            @NotNull
401            @Override
402            public CopyConfiguration setExtensionReceiverType(@Nullable KotlinType type) {
403                this.newExtensionReceiverParameterType = type;
404                return this;
405            }
406    
407            @Override
408            @NotNull
409            public CopyConfiguration setOriginal(@NotNull FunctionDescriptor original) {
410                this.original = original;
411                return this;
412            }
413    
414            @Override
415            @NotNull
416            public CopyConfiguration setSignatureChange() {
417                this.signatureChange = true;
418                return this;
419            }
420    
421            @Override
422            @NotNull
423            public CopyConfiguration setPreserveSourceElement() {
424                this.preserveSourceElement = true;
425                return this;
426            }
427    
428            @Override
429            @NotNull
430            public CopyConfiguration setDropOriginalInContainingParts() {
431                this.dropOriginalInContainingParts = true;
432                return this;
433            }
434    
435            @Override
436            @NotNull
437            public CopyConfiguration setHiddenToOvercomeSignatureClash() {
438                isHiddenToOvercomeSignatureClash = true;
439                return this;
440            }
441    
442            @Override
443            @Nullable
444            public FunctionDescriptor build() {
445                return doSubstitute(this);
446            }
447    
448            @Nullable
449            public FunctionDescriptor getOriginal() {
450                return original;
451            }
452    
453            @NotNull
454            public TypeSubstitutor getOriginalSubstitutor() {
455                return originalSubstitutor;
456            }
457        }
458    
459        @Override
460        @NotNull
461        public CopyBuilder<? extends FunctionDescriptor> newCopyBuilder() {
462            return newCopyBuilder(TypeSubstitutor.EMPTY);
463        }
464    
465        @NotNull
466        private CopyConfiguration newCopyBuilder(@NotNull TypeSubstitutor substitutor) {
467            return new CopyConfiguration(
468                    substitutor,
469                    getContainingDeclaration(), getModality(), getVisibility(), getKind(), getValueParameters(),
470                    getExtensionReceiverParameterType(), getReturnType(), null);
471        }
472    
473        @Nullable
474        protected FunctionDescriptor doSubstitute(@NotNull CopyConfiguration configuration) {
475            FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(
476                    configuration.newOwner, configuration.original, configuration.kind, configuration.name,
477                    configuration.preserveSourceElement);
478    
479            List<TypeParameterDescriptor> unsubstitutedTypeParameters =
480                    configuration.newTypeParameters == null ? getTypeParameters() : configuration.newTypeParameters;
481    
482            List<TypeParameterDescriptor> substitutedTypeParameters =
483                    new ArrayList<TypeParameterDescriptor>(unsubstitutedTypeParameters.size());
484            final TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
485                    unsubstitutedTypeParameters, configuration.originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters
486            );
487    
488            KotlinType substitutedReceiverParameterType = null;
489            if (configuration.newExtensionReceiverParameterType != null) {
490                substitutedReceiverParameterType = substitutor.substitute(configuration.newExtensionReceiverParameterType, Variance.IN_VARIANCE);
491                if (substitutedReceiverParameterType == null) {
492                    return null;
493                }
494            }
495    
496            ReceiverParameterDescriptor substitutedExpectedThis = null;
497            if (dispatchReceiverParameter != null) {
498                // When generating fake-overridden member it's dispatch receiver parameter has type of Base, and it's correct.
499                // E.g.
500                // class Base { fun foo() }
501                // class Derived : Base
502                // val x: Base
503                // if (x is Derived) {
504                //    // `x` shouldn't be marked as smart-cast
505                //    // but it would if fake-overridden `foo` had `Derived` as it's dispatch receiver parameter type
506                //    x.foo()
507                // }
508                substitutedExpectedThis = dispatchReceiverParameter.substitute(substitutor);
509                if (substitutedExpectedThis == null) {
510                    return null;
511                }
512            }
513    
514            List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(
515                    substitutedDescriptor, configuration.newValueParameterDescriptors, substitutor, configuration.dropOriginalInContainingParts
516            );
517            if (substitutedValueParameters == null) {
518                return null;
519            }
520    
521            KotlinType substitutedReturnType = substitutor.substitute(configuration.newReturnType, Variance.OUT_VARIANCE);
522            if (substitutedReturnType == null) {
523                return null;
524            }
525    
526            substitutedDescriptor.initialize(
527                    substitutedReceiverParameterType,
528                    substitutedExpectedThis,
529                    substitutedTypeParameters,
530                    substitutedValueParameters,
531                    substitutedReturnType,
532                    configuration.newModality,
533                    configuration.newVisibility
534            );
535            substitutedDescriptor.setOperator(isOperator);
536            substitutedDescriptor.setInfix(isInfix);
537            substitutedDescriptor.setExternal(isExternal);
538            substitutedDescriptor.setInline(isInline);
539            substitutedDescriptor.setTailrec(isTailrec);
540            substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames);
541            substitutedDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames);
542            substitutedDescriptor.setHidden(configuration.isHiddenToOvercomeSignatureClash);
543    
544            if (configuration.signatureChange || getInitialSignatureDescriptor() != null) {
545                FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this);
546                FunctionDescriptor initialSignatureSubstituted = initialSignature.substitute(substitutor);
547                substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted);
548            }
549    
550            if (configuration.copyOverrides && !getOriginal().getOverriddenDescriptors().isEmpty()) {
551                if (configuration.originalSubstitutor.isEmpty()) {
552                    Function0<Set<FunctionDescriptor>> overriddenFunctionsTask = lazyOverriddenFunctionsTask;
553                    if (overriddenFunctionsTask != null) {
554                        substitutedDescriptor.lazyOverriddenFunctionsTask = overriddenFunctionsTask;
555                    }
556                    else {
557                        substitutedDescriptor.setOverriddenDescriptors(getOverriddenDescriptors());
558                    }
559                }
560                else {
561                    substitutedDescriptor.lazyOverriddenFunctionsTask = new Function0<Set<FunctionDescriptor>>() {
562                        @Override
563                        public Set<FunctionDescriptor> invoke() {
564                            SmartSet<FunctionDescriptor> result = SmartSet.create();
565                            for (FunctionDescriptor overriddenFunction : getOverriddenDescriptors()) {
566                                result.add(overriddenFunction.substitute(substitutor));
567                            }
568                            return result;
569                        }
570                    };
571                }
572            }
573    
574            return substitutedDescriptor;
575        }
576    
577        @NotNull
578        @Override
579        public FunctionDescriptor copy(
580                DeclarationDescriptor newOwner,
581                Modality modality,
582                Visibility visibility,
583                Kind kind,
584                boolean copyOverrides
585        ) {
586            return newCopyBuilder()
587                    .setOwner(newOwner)
588                    .setModality(modality)
589                    .setVisibility(visibility)
590                    .setKind(kind)
591                    .setCopyOverrides(copyOverrides)
592                    .build();
593        }
594    
595        @NotNull
596        protected abstract FunctionDescriptorImpl createSubstitutedCopy(
597                @NotNull DeclarationDescriptor newOwner,
598                @Nullable FunctionDescriptor original,
599                @NotNull Kind kind,
600                @Nullable Name newName,
601                boolean preserveSource
602        );
603    
604        @NotNull
605        protected SourceElement getSourceToUseForCopy(boolean preserveSource, @Nullable FunctionDescriptor original) {
606            return preserveSource
607                   ? (original != null ? original.getSource() : getOriginal().getSource())
608                   : SourceElement.NO_SOURCE;
609        }
610    
611        @Override
612        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
613            return visitor.visitFunctionDescriptor(this, data);
614        }
615    
616        @Nullable
617        public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
618                FunctionDescriptor substitutedDescriptor,
619                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
620                @NotNull TypeSubstitutor substitutor,
621                boolean dropOriginal
622        ) {
623            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(unsubstitutedValueParameters.size());
624            for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
625                // TODO : Lazy?
626                KotlinType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
627                KotlinType varargElementType = unsubstitutedValueParameter.getVarargElementType();
628                KotlinType substituteVarargElementType =
629                        varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
630                if (substitutedType == null) return null;
631                result.add(
632                        new ValueParameterDescriptorImpl(
633                                substitutedDescriptor,
634                                dropOriginal ? null : unsubstitutedValueParameter,
635                                unsubstitutedValueParameter.getIndex(),
636                                unsubstitutedValueParameter.getAnnotations(),
637                                unsubstitutedValueParameter.getName(),
638                                substitutedType,
639                                unsubstitutedValueParameter.declaresDefaultValue(),
640                                unsubstitutedValueParameter.isCrossinline(),
641                                unsubstitutedValueParameter.isNoinline(),
642                                substituteVarargElementType,
643                                SourceElement.NO_SOURCE
644                        )
645                );
646            }
647            return result;
648        }
649    
650        @Override
651        @Nullable
652        public FunctionDescriptor getInitialSignatureDescriptor() {
653            return initialSignatureDescriptor;
654        }
655    
656        public void setInitialSignatureDescriptor(@Nullable FunctionDescriptor initialSignatureDescriptor) {
657            this.initialSignatureDescriptor = initialSignatureDescriptor;
658        }
659    }