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