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