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