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