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