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