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