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 hasStableParameterNames = true;
051        private boolean hasSynthesizedParameterNames = false;
052        private final Set<FunctionDescriptor> overriddenFunctions = SmartSet.create();
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 setReturnType(@NotNull KotlinType unsubstitutedReturnType) {
133            if (this.unsubstitutedReturnType != null) {
134                // TODO: uncomment and fix tests
135                //throw new IllegalStateException("returnType already set");
136            }
137            this.unsubstitutedReturnType = unsubstitutedReturnType;
138        }
139    
140        public void setHasStableParameterNames(boolean hasStableParameterNames) {
141            this.hasStableParameterNames = hasStableParameterNames;
142        }
143    
144        public void setHasSynthesizedParameterNames(boolean hasSynthesizedParameterNames) {
145            this.hasSynthesizedParameterNames = hasSynthesizedParameterNames;
146        }
147    
148        @Nullable
149        @Override
150        public ReceiverParameterDescriptor getExtensionReceiverParameter() {
151            return extensionReceiverParameter;
152        }
153    
154        @Nullable
155        @Override
156        public ReceiverParameterDescriptor getDispatchReceiverParameter() {
157            return dispatchReceiverParameter;
158        }
159    
160        @NotNull
161        @Override
162        public Collection<? extends FunctionDescriptor> getOverriddenDescriptors() {
163            return overriddenFunctions;
164        }
165    
166        @NotNull
167        @Override
168        public Modality getModality() {
169            return modality;
170        }
171    
172        @NotNull
173        @Override
174        public Visibility getVisibility() {
175            return visibility;
176        }
177    
178        @Override
179        public boolean isOperator() {
180            if (isOperator) return true;
181    
182            for (FunctionDescriptor descriptor : overriddenFunctions) {
183                if (descriptor.isOperator()) return true;
184            }
185    
186            return false;
187        }
188    
189        @Override
190        public boolean isInfix() {
191            if (isInfix) return true;
192    
193            for (FunctionDescriptor descriptor : overriddenFunctions) {
194                if (descriptor.isInfix()) return true;
195            }
196    
197            return false;
198        }
199    
200        @Override
201        public boolean isExternal() {
202            return isExternal;
203        }
204    
205        @Override
206        public boolean isInline() {
207            return isInline;
208        }
209    
210        @Override
211        public boolean isTailrec() {
212            return isTailrec;
213        }
214    
215        @Override
216        public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overriddenFunction) {
217            overriddenFunctions.add((FunctionDescriptor) overriddenFunction);
218        }
219    
220        @Override
221        @NotNull
222        public List<TypeParameterDescriptor> getTypeParameters() {
223            return typeParameters;
224        }
225    
226        @Override
227        @NotNull
228        public List<ValueParameterDescriptor> getValueParameters() {
229            return unsubstitutedValueParameters;
230        }
231    
232        @Override
233        public boolean hasStableParameterNames() {
234            return hasStableParameterNames;
235        }
236    
237        @Override
238        public boolean hasSynthesizedParameterNames() {
239            return hasSynthesizedParameterNames;
240        }
241    
242        @Override
243        public KotlinType getReturnType() {
244            return unsubstitutedReturnType;
245        }
246    
247        @NotNull
248        @Override
249        public FunctionDescriptor getOriginal() {
250            return original == this ? this : original.getOriginal();
251        }
252    
253        @NotNull
254        @Override
255        public Kind getKind() {
256            return kind;
257        }
258    
259        @Override
260        public FunctionDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
261            if (originalSubstitutor.isEmpty()) {
262                return this;
263            }
264            return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility,
265                                isOperator, isInfix, isExternal, isInline, isTailrec,
266                                hasStableParameterNames, hasSynthesizedParameterNames,
267                                getOriginal(), true, getKind());
268        }
269    
270        @Nullable
271        protected FunctionDescriptor doSubstitute(@NotNull TypeSubstitutor originalSubstitutor,
272                @NotNull DeclarationDescriptor newOwner,
273                @NotNull Modality newModality,
274                @NotNull Visibility newVisibility,
275                boolean isOperator,
276                boolean isInfix,
277                boolean isExternal,
278                boolean isInline,
279                boolean isTailrec,
280                boolean hasStableParameterNames,
281                boolean hasSynthesizedParameterNames,
282                @Nullable FunctionDescriptor original,
283                boolean copyOverrides,
284                @NotNull Kind kind
285        ) {
286            return doSubstitute(originalSubstitutor,
287                                newOwner, newModality, newVisibility, isOperator, isInfix, isExternal, isInline, isTailrec,
288                                hasStableParameterNames, hasSynthesizedParameterNames,
289                                original, copyOverrides, kind,
290                                getValueParameters(), getExtensionReceiverParameterType(), getReturnType(),
291                                null, /* preserveSource = */ false, /* signatureChange */ false);
292        }
293    
294        @Nullable
295        protected KotlinType getExtensionReceiverParameterType() {
296            if (extensionReceiverParameter == null) return null;
297            return extensionReceiverParameter.getType();
298        }
299    
300    
301        @Nullable
302        protected FunctionDescriptor doSubstitute(
303                @NotNull TypeSubstitutor originalSubstitutor,
304                @NotNull DeclarationDescriptor newOwner,
305                @NotNull Modality newModality,
306                @NotNull Visibility newVisibility,
307                boolean isOperator,
308                boolean isInfix,
309                boolean isExternal,
310                boolean isInline,
311                boolean isTailrec,
312                boolean hasStableParameterNames,
313                boolean hasSynthesizedParameterNames,
314                @Nullable FunctionDescriptor original,
315                boolean copyOverrides,
316                @NotNull Kind kind,
317                @NotNull List<ValueParameterDescriptor> newValueParameterDescriptors,
318                @Nullable KotlinType newExtensionReceiverParameterType,
319                @NotNull KotlinType newReturnType,
320                @Nullable Name name,
321                boolean preserveSource,
322                boolean signatureChange
323        ) {
324            FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, original, kind, name, preserveSource);
325    
326            List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
327            List<TypeParameterDescriptor> substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
328            TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
329                    originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters
330            );
331    
332            KotlinType substitutedReceiverParameterType = null;
333            if (newExtensionReceiverParameterType != null) {
334                substitutedReceiverParameterType = substitutor.substitute(newExtensionReceiverParameterType, Variance.IN_VARIANCE);
335                if (substitutedReceiverParameterType == null) {
336                    return null;
337                }
338            }
339    
340            ReceiverParameterDescriptor substitutedExpectedThis = null;
341            if (dispatchReceiverParameter != null) {
342                // When generating fake-overridden member it's dispatch receiver parameter has type of Base, and it's correct.
343                // E.g.
344                // class Base { fun foo() }
345                // class Derived : Base
346                // val x: Base
347                // if (x is Derived) {
348                //    // `x` shouldn't be marked as smart-cast
349                //    // but it would if fake-overridden `foo` had `Derived` as it's dispatch receiver parameter type
350                //    x.foo()
351                // }
352                substitutedExpectedThis = dispatchReceiverParameter.substitute(substitutor);
353                if (substitutedExpectedThis == null) {
354                    return null;
355                }
356            }
357    
358            List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(
359                    substitutedDescriptor, newValueParameterDescriptors, substitutor
360            );
361            if (substitutedValueParameters == null) {
362                return null;
363            }
364    
365            KotlinType substitutedReturnType = substitutor.substitute(newReturnType, Variance.OUT_VARIANCE);
366            if (substitutedReturnType == null) {
367                return null;
368            }
369    
370            substitutedDescriptor.initialize(
371                    substitutedReceiverParameterType,
372                    substitutedExpectedThis,
373                    substitutedTypeParameters,
374                    substitutedValueParameters,
375                    substitutedReturnType,
376                    newModality,
377                    newVisibility
378            );
379            substitutedDescriptor.setOperator(isOperator);
380            substitutedDescriptor.setInfix(isInfix);
381            substitutedDescriptor.setExternal(isExternal);
382            substitutedDescriptor.setInline(isInline);
383            substitutedDescriptor.setTailrec(isTailrec);
384            substitutedDescriptor.setHasStableParameterNames(hasStableParameterNames);
385            substitutedDescriptor.setHasSynthesizedParameterNames(hasSynthesizedParameterNames);
386    
387            if (signatureChange || getInitialSignatureDescriptor() != null) {
388                FunctionDescriptor initialSignature = (getInitialSignatureDescriptor() != null ? getInitialSignatureDescriptor() : this);
389                FunctionDescriptor initialSignatureSubstituted = initialSignature.substitute(substitutor);
390                substitutedDescriptor.setInitialSignatureDescriptor(initialSignatureSubstituted);
391            }
392    
393            if (copyOverrides) {
394                for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
395                    substitutedDescriptor.addOverriddenDescriptor(overriddenFunction.substitute(substitutor));
396                }
397            }
398    
399            return substitutedDescriptor;
400        }
401    
402        @NotNull
403        protected abstract FunctionDescriptorImpl createSubstitutedCopy(
404                @NotNull DeclarationDescriptor newOwner,
405                @Nullable FunctionDescriptor original,
406                @NotNull Kind kind,
407                @Nullable Name newName,
408                boolean preserveSource
409        );
410    
411        @NotNull
412        protected SourceElement getSourceToUseForCopy(boolean preserveSource, @Nullable FunctionDescriptor original) {
413            return preserveSource
414                   ? (original != null ? original.getSource() : getOriginal().getSource())
415                   : SourceElement.NO_SOURCE;
416        }
417    
418        @Override
419        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
420            return visitor.visitFunctionDescriptor(this, data);
421        }
422    
423        @Nullable
424        public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
425                FunctionDescriptor substitutedDescriptor,
426                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
427                @NotNull TypeSubstitutor substitutor
428        ) {
429            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(unsubstitutedValueParameters.size());
430            for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
431                // TODO : Lazy?
432                KotlinType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
433                KotlinType varargElementType = unsubstitutedValueParameter.getVarargElementType();
434                KotlinType substituteVarargElementType =
435                        varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
436                if (substitutedType == null) return null;
437                result.add(
438                        new ValueParameterDescriptorImpl(
439                                substitutedDescriptor,
440                                unsubstitutedValueParameter,
441                                unsubstitutedValueParameter.getIndex(),
442                                unsubstitutedValueParameter.getAnnotations(),
443                                unsubstitutedValueParameter.getName(),
444                                substitutedType,
445                                unsubstitutedValueParameter.declaresDefaultValue(),
446                                unsubstitutedValueParameter.isCrossinline(),
447                                unsubstitutedValueParameter.isNoinline(),
448                                substituteVarargElementType,
449                                SourceElement.NO_SOURCE
450                        )
451                );
452            }
453            return result;
454        }
455    
456        @Override
457        @Nullable
458        public FunctionDescriptor getInitialSignatureDescriptor() {
459            return initialSignatureDescriptor;
460        }
461    
462        public void setInitialSignatureDescriptor(@Nullable FunctionDescriptor initialSignatureDescriptor) {
463            this.initialSignatureDescriptor = initialSignatureDescriptor;
464        }
465    }