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