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 final Set<FunctionDescriptor> overriddenFunctions = SmartSet.create();
051        private final FunctionDescriptor original;
052        private final Kind kind;
053    
054        protected FunctionDescriptorImpl(
055                @NotNull DeclarationDescriptor containingDeclaration,
056                @Nullable FunctionDescriptor original,
057                @NotNull Annotations annotations,
058                @NotNull Name name,
059                @NotNull Kind kind,
060                @NotNull SourceElement source
061        ) {
062            super(containingDeclaration, annotations, name, source);
063            this.original = original == null ? this : original;
064            this.kind = kind;
065        }
066    
067        @NotNull
068        public FunctionDescriptorImpl initialize(
069                @Nullable KotlinType receiverParameterType,
070                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
071                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
072                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
073                @Nullable KotlinType unsubstitutedReturnType,
074                @Nullable Modality modality,
075                @NotNull Visibility visibility
076        ) {
077            this.typeParameters = CollectionsKt.toReadOnlyList(typeParameters);
078            this.unsubstitutedValueParameters = unsubstitutedValueParameters;
079            this.unsubstitutedReturnType = unsubstitutedReturnType;
080            this.modality = modality;
081            this.visibility = visibility;
082            this.extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverParameterType);
083            this.dispatchReceiverParameter = dispatchReceiverParameter;
084            
085            for (int i = 0; i < typeParameters.size(); ++i) {
086                TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
087                if (typeParameterDescriptor.getIndex() != i) {
088                    throw new IllegalStateException(typeParameterDescriptor + " index is " + typeParameterDescriptor.getIndex() + " but position is " + i);
089                }
090            }
091    
092            for (int i = 0; i < unsubstitutedValueParameters.size(); ++i) {
093                // TODO fill me
094                int firstValueParameterOffset = 0; // receiverParameter.exists() ? 1 : 0;
095                ValueParameterDescriptor valueParameterDescriptor = unsubstitutedValueParameters.get(i);
096                if (valueParameterDescriptor.getIndex() != i + firstValueParameterOffset) {
097                    throw new IllegalStateException(valueParameterDescriptor + "index is " + valueParameterDescriptor.getIndex() + " but position is " + i);
098                }
099            }
100    
101            return this;
102        }
103    
104        public void setVisibility(@NotNull Visibility visibility) {
105            this.visibility = visibility;
106        }
107    
108        public void setOperator(boolean isOperator) {
109            this.isOperator = isOperator;
110        }
111    
112        public void setInfix(boolean isInfix) {
113            this.isInfix = isInfix;
114        }
115    
116        public void setExternal(boolean isExternal) {
117            this.isExternal = isExternal;
118        }
119    
120        public void setInline(boolean isInline) {
121            this.isInline = isInline;
122        }
123    
124        public void setTailrec(boolean isTailrec) {
125            this.isTailrec = isTailrec;
126        }
127    
128        public void setReturnType(@NotNull KotlinType unsubstitutedReturnType) {
129            if (this.unsubstitutedReturnType != null) {
130                // TODO: uncomment and fix tests
131                //throw new IllegalStateException("returnType already set");
132            }
133            this.unsubstitutedReturnType = unsubstitutedReturnType;
134        }
135    
136        @Nullable
137        @Override
138        public ReceiverParameterDescriptor getExtensionReceiverParameter() {
139            return extensionReceiverParameter;
140        }
141    
142        @Nullable
143        @Override
144        public ReceiverParameterDescriptor getDispatchReceiverParameter() {
145            return dispatchReceiverParameter;
146        }
147    
148        @NotNull
149        @Override
150        public Collection<? extends FunctionDescriptor> getOverriddenDescriptors() {
151            return overriddenFunctions;
152        }
153    
154        @NotNull
155        @Override
156        public Modality getModality() {
157            return modality;
158        }
159    
160        @NotNull
161        @Override
162        public Visibility getVisibility() {
163            return visibility;
164        }
165    
166        @Override
167        public boolean isOperator() {
168            if (isOperator) return true;
169    
170            for (FunctionDescriptor descriptor : overriddenFunctions) {
171                if (descriptor.isOperator()) return true;
172            }
173    
174            return false;
175        }
176    
177        @Override
178        public boolean isInfix() {
179            if (isInfix) return true;
180    
181            for (FunctionDescriptor descriptor : overriddenFunctions) {
182                if (descriptor.isInfix()) return true;
183            }
184    
185            return false;
186        }
187    
188        @Override
189        public boolean isExternal() {
190            return isExternal;
191        }
192    
193        @Override
194        public boolean isInline() {
195            return isInline;
196        }
197    
198        @Override
199        public boolean isTailrec() {
200            return isTailrec;
201        }
202    
203        @Override
204        public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overriddenFunction) {
205            overriddenFunctions.add((FunctionDescriptor) overriddenFunction);
206        }
207    
208        @Override
209        @NotNull
210        public List<TypeParameterDescriptor> getTypeParameters() {
211            return typeParameters;
212        }
213    
214        @Override
215        @NotNull
216        public List<ValueParameterDescriptor> getValueParameters() {
217            return unsubstitutedValueParameters;
218        }
219    
220        @Override
221        public boolean hasStableParameterNames() {
222            return true;
223        }
224    
225        @Override
226        public boolean hasSynthesizedParameterNames() {
227            return false;
228        }
229    
230        @Override
231        public KotlinType getReturnType() {
232            return unsubstitutedReturnType;
233        }
234    
235        @NotNull
236        @Override
237        public FunctionDescriptor getOriginal() {
238            return original == this ? this : original.getOriginal();
239        }
240    
241        @NotNull
242        @Override
243        public Kind getKind() {
244            return kind;
245        }
246    
247        @Override
248        public final FunctionDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
249            if (originalSubstitutor.isEmpty()) {
250                return this;
251            }
252            return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility,
253                                isOperator, isInfix, isExternal, isInline, isTailrec,
254                                getOriginal(), true, getKind());
255        }
256    
257        @Nullable
258        protected FunctionDescriptor doSubstitute(@NotNull TypeSubstitutor originalSubstitutor,
259                @NotNull DeclarationDescriptor newOwner,
260                @NotNull Modality newModality,
261                @NotNull Visibility newVisibility,
262                boolean isOperator,
263                boolean isInfix,
264                boolean isExternal,
265                boolean isInline,
266                boolean isTailrec,
267                @Nullable FunctionDescriptor original,
268                boolean copyOverrides,
269                @NotNull Kind kind
270        ) {
271            return doSubstitute(originalSubstitutor,
272                    newOwner, newModality, newVisibility, isOperator, isInfix, isExternal, isInline, isTailrec, original, copyOverrides, kind,
273                    getValueParameters(), getExtensionReceiverParameterType(), getReturnType()
274            );
275        }
276    
277        @Nullable
278        protected KotlinType getExtensionReceiverParameterType() {
279            if (extensionReceiverParameter == null) return null;
280            return extensionReceiverParameter.getType();
281        }
282    
283    
284        @Nullable
285        protected FunctionDescriptor doSubstitute(@NotNull TypeSubstitutor originalSubstitutor,
286                @NotNull DeclarationDescriptor newOwner,
287                @NotNull Modality newModality,
288                @NotNull Visibility newVisibility,
289                boolean isOperator,
290                boolean isInfix,
291                boolean isExternal,
292                boolean isInline,
293                boolean isTailrec,
294                @Nullable FunctionDescriptor original,
295                boolean copyOverrides,
296                @NotNull Kind kind,
297                @NotNull List<ValueParameterDescriptor> newValueParameterDescriptors,
298                @Nullable KotlinType newExtensionReceiverParameterType,
299                @NotNull KotlinType newReturnType
300        ) {
301            FunctionDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, original, kind);
302    
303            List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
304            List<TypeParameterDescriptor> substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
305            TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
306                    originalTypeParameters, originalSubstitutor.getSubstitution(), substitutedDescriptor, substitutedTypeParameters
307            );
308    
309            KotlinType substitutedReceiverParameterType = null;
310            if (newExtensionReceiverParameterType != null) {
311                substitutedReceiverParameterType = substitutor.substitute(newExtensionReceiverParameterType, Variance.IN_VARIANCE);
312                if (substitutedReceiverParameterType == null) {
313                    return null;
314                }
315            }
316    
317            ReceiverParameterDescriptor substitutedExpectedThis = null;
318            if (dispatchReceiverParameter != null) {
319                // When generating fake-overridden member it's dispatch receiver parameter has type of Base, and it's correct.
320                // E.g.
321                // class Base { fun foo() }
322                // class Derived : Base
323                // val x: Base
324                // if (x is Derived) {
325                //    // `x` shouldn't be marked as smart-cast
326                //    // but it would if fake-overridden `foo` had `Derived` as it's dispatch receiver parameter type
327                //    x.foo()
328                // }
329                substitutedExpectedThis = dispatchReceiverParameter.substitute(substitutor);
330                if (substitutedExpectedThis == null) {
331                    return null;
332                }
333            }
334    
335            List<ValueParameterDescriptor> substitutedValueParameters = getSubstitutedValueParameters(
336                    substitutedDescriptor, newValueParameterDescriptors, substitutor
337            );
338            if (substitutedValueParameters == null) {
339                return null;
340            }
341    
342            KotlinType substitutedReturnType = substitutor.substitute(newReturnType, Variance.OUT_VARIANCE);
343            if (substitutedReturnType == null) {
344                return null;
345            }
346    
347            substitutedDescriptor.initialize(
348                    substitutedReceiverParameterType,
349                    substitutedExpectedThis,
350                    substitutedTypeParameters,
351                    substitutedValueParameters,
352                    substitutedReturnType,
353                    newModality,
354                    newVisibility
355            );
356            substitutedDescriptor.setOperator(isOperator);
357            substitutedDescriptor.setInfix(isInfix);
358            substitutedDescriptor.setExternal(isExternal);
359            substitutedDescriptor.setInline(isInline);
360            substitutedDescriptor.setTailrec(isTailrec);
361    
362            if (copyOverrides) {
363                for (FunctionDescriptor overriddenFunction : overriddenFunctions) {
364                    substitutedDescriptor.addOverriddenDescriptor(overriddenFunction.substitute(substitutor));
365                }
366            }
367    
368            return substitutedDescriptor;
369        }
370    
371        @NotNull
372        protected abstract FunctionDescriptorImpl createSubstitutedCopy(
373                @NotNull DeclarationDescriptor newOwner,
374                @Nullable FunctionDescriptor original,
375                @NotNull Kind kind
376        );
377    
378        @Override
379        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
380            return visitor.visitFunctionDescriptor(this, data);
381        }
382    
383        @Nullable
384        public static List<ValueParameterDescriptor> getSubstitutedValueParameters(
385                FunctionDescriptor substitutedDescriptor,
386                @NotNull List<ValueParameterDescriptor> unsubstitutedValueParameters,
387                @NotNull TypeSubstitutor substitutor
388        ) {
389            List<ValueParameterDescriptor> result = new ArrayList<ValueParameterDescriptor>(unsubstitutedValueParameters.size());
390            for (ValueParameterDescriptor unsubstitutedValueParameter : unsubstitutedValueParameters) {
391                // TODO : Lazy?
392                KotlinType substitutedType = substitutor.substitute(unsubstitutedValueParameter.getType(), Variance.IN_VARIANCE);
393                KotlinType varargElementType = unsubstitutedValueParameter.getVarargElementType();
394                KotlinType substituteVarargElementType =
395                        varargElementType == null ? null : substitutor.substitute(varargElementType, Variance.IN_VARIANCE);
396                if (substitutedType == null) return null;
397                result.add(
398                        new ValueParameterDescriptorImpl(
399                                substitutedDescriptor,
400                                unsubstitutedValueParameter,
401                                unsubstitutedValueParameter.getIndex(),
402                                unsubstitutedValueParameter.getAnnotations(),
403                                unsubstitutedValueParameter.getName(),
404                                substitutedType,
405                                unsubstitutedValueParameter.declaresDefaultValue(),
406                                unsubstitutedValueParameter.isCrossinline(),
407                                unsubstitutedValueParameter.isNoinline(),
408                                substituteVarargElementType,
409                                SourceElement.NO_SOURCE
410                        )
411                );
412            }
413            return result;
414        }
415    }