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.AnnotationDescriptor;
025    import org.jetbrains.jet.lang.resolve.DescriptorResolver;
026    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
027    import org.jetbrains.jet.lang.resolve.OverridingUtil;
028    import org.jetbrains.jet.lang.resolve.name.Name;
029    import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
030    import org.jetbrains.jet.lang.types.JetType;
031    import org.jetbrains.jet.lang.types.TypeSubstitutor;
032    import org.jetbrains.jet.lang.types.Variance;
033    
034    import java.util.Collections;
035    import java.util.List;
036    import java.util.Set;
037    
038    public class PropertyDescriptorImpl extends VariableDescriptorImpl implements PropertyDescriptor {
039    
040        private final Modality modality;
041        private Visibility visibility;
042        private final boolean isVar;
043        private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet(); // LinkedHashSet is essential here
044        private final PropertyDescriptor original;
045        private final Kind kind;
046    
047        private ReceiverParameterDescriptor expectedThisObject;
048        private ReceiverParameterDescriptor receiverParameter;
049        private List<TypeParameterDescriptor> typeParameters;
050        private PropertyGetterDescriptorImpl getter;
051        private PropertySetterDescriptor setter;
052    
053        private PropertyDescriptorImpl(
054                @Nullable PropertyDescriptor original,
055                @NotNull DeclarationDescriptor containingDeclaration,
056                @NotNull List<AnnotationDescriptor> annotations,
057                @NotNull Modality modality,
058                @NotNull Visibility visibility,
059                boolean isVar,
060                @NotNull Name name,
061                @NotNull Kind kind
062        ) {
063            super(containingDeclaration, annotations, name);
064            this.isVar = isVar;
065            this.modality = modality;
066            this.visibility = visibility;
067            this.original = original == null ? this : original;
068            this.kind = kind;
069        }
070    
071        public PropertyDescriptorImpl(
072                @NotNull DeclarationDescriptor containingDeclaration,
073                @NotNull List<AnnotationDescriptor> annotations,
074                @NotNull Modality modality,
075                @NotNull Visibility visibility,
076                boolean isVar,
077                @NotNull Name name,
078                @NotNull Kind kind
079        ) {
080            this(null, containingDeclaration, annotations, modality, visibility, isVar, name, kind);
081        }
082    
083        public PropertyDescriptorImpl(
084                @NotNull DeclarationDescriptor containingDeclaration,
085                @NotNull List<AnnotationDescriptor> annotations,
086                @NotNull Modality modality,
087                @NotNull Visibility visibility,
088                boolean isVar,
089                @Nullable JetType receiverType,
090                @Nullable ReceiverParameterDescriptor expectedThisObject,
091                @NotNull Name name,
092                @NotNull JetType outType,
093                @NotNull Kind kind
094        ) {
095            this(containingDeclaration, annotations, modality, visibility, isVar, name, kind);
096            setType(outType, Collections.<TypeParameterDescriptor>emptyList(), expectedThisObject, receiverType);
097        }
098    
099        public void setType(
100                @NotNull JetType outType,
101                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
102                @Nullable ReceiverParameterDescriptor expectedThisObject,
103                @Nullable JetType receiverType
104        ) {
105            ReceiverParameterDescriptor receiverParameter = DescriptorResolver.resolveReceiverParameterFor(this, receiverType);
106            setType(outType, typeParameters, expectedThisObject, receiverParameter);
107        }
108    
109        public void setType(
110                @NotNull JetType outType,
111                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
112                @Nullable ReceiverParameterDescriptor expectedThisObject,
113                @Nullable ReceiverParameterDescriptor receiverParameter
114        ) {
115            setOutType(outType);
116    
117            this.typeParameters = Lists.newArrayList(typeParameters);
118    
119            this.receiverParameter = receiverParameter;
120            this.expectedThisObject = expectedThisObject;
121        }
122    
123        public void initialize(@Nullable PropertyGetterDescriptorImpl getter, @Nullable PropertySetterDescriptor setter) {
124            this.getter = getter;
125            this.setter = setter;
126        }
127    
128        public void setVisibility(@NotNull Visibility visibility) {
129            this.visibility = visibility;
130        }
131    
132        @NotNull
133        @Override
134        public List<TypeParameterDescriptor> getTypeParameters() {
135            return typeParameters;
136        }
137    
138        @Override
139        @Nullable
140        public ReceiverParameterDescriptor getReceiverParameter() {
141            return receiverParameter;
142        }
143    
144        @Nullable
145        @Override
146        public ReceiverParameterDescriptor getExpectedThisObject() {
147            return expectedThisObject;
148        }
149    
150        @NotNull
151        @Override
152        public JetType getReturnType() {
153            return getType();
154        }
155    
156        @Override
157        public boolean isVar() {
158            return isVar;
159        }
160    
161        @NotNull
162        @Override
163        public Modality getModality() {
164            return modality;
165        }
166    
167        @NotNull
168        @Override
169        public Visibility getVisibility() {
170            return visibility;
171        }
172    
173        @Override
174        @Nullable
175        public PropertyGetterDescriptorImpl getGetter() {
176            return getter;
177        }
178    
179        @Override
180        @Nullable
181        public PropertySetterDescriptor getSetter() {
182            return setter;
183        }
184    
185        @Override
186        @NotNull
187        public List<PropertyAccessorDescriptor> getAccessors() {
188            List<PropertyAccessorDescriptor> r = Lists.newArrayListWithCapacity(2);
189            if (getter != null) {
190                r.add(getter);
191            }
192            if (setter != null) {
193                r.add(setter);
194            }
195            return r;
196        }
197    
198        @Override
199        public PropertyDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
200            if (originalSubstitutor.isEmpty()) {
201                return this;
202            }
203            return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, true, true, getKind());
204        }
205    
206        private PropertyDescriptor doSubstitute(TypeSubstitutor originalSubstitutor,
207                DeclarationDescriptor newOwner, Modality newModality, Visibility newVisibility, boolean preserveOriginal, boolean copyOverrides, Kind kind) {
208            PropertyDescriptorImpl substitutedDescriptor = new PropertyDescriptorImpl(preserveOriginal ? getOriginal() : null, newOwner,
209                    getAnnotations(), newModality, newVisibility, isVar(), getName(), kind);
210    
211            List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
212            TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
213    
214            JetType originalOutType = getType();
215            JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
216            if (outType == null) {
217                return null; // TODO : tell the user that the property was projected out
218            }
219    
220    
221            ReceiverParameterDescriptor substitutedExpectedThisObject;
222            ReceiverParameterDescriptor expectedThisObject = getExpectedThisObject();
223            if (expectedThisObject != null) {
224                substitutedExpectedThisObject = expectedThisObject.substitute(substitutor);
225                if (substitutedExpectedThisObject == null) return null;
226            }
227            else {
228                substitutedExpectedThisObject = null;
229            }
230    
231            JetType substitutedReceiverType;
232            if (receiverParameter != null) {
233                substitutedReceiverType = substitutor.substitute(receiverParameter.getType(), Variance.IN_VARIANCE);
234                if (substitutedReceiverType == null) return null;
235            }
236            else {
237                substitutedReceiverType = null;
238            }
239    
240            substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedExpectedThisObject, substitutedReceiverType);
241    
242            PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
243                    substitutedDescriptor, Lists.newArrayList(getter.getAnnotations()),
244                    DescriptorUtils.convertModality(getter.getModality(), false), convertVisibility(getter.getVisibility(), newVisibility),
245                    getter.hasBody(), getter.isDefault(), kind, getter.getOriginal());
246            if (newGetter != null) {
247                JetType returnType = getter.getReturnType();
248                newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
249            }
250            PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
251                    substitutedDescriptor, Lists.newArrayList(setter.getAnnotations()), DescriptorUtils.convertModality(setter.getModality(), false),
252                    convertVisibility(setter.getVisibility(), newVisibility), setter.hasBody(), setter.isDefault(), kind, setter.getOriginal());
253            if (newSetter != null) {
254                List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorUtil.getSubstitutedValueParameters(newSetter, setter, substitutor);
255                if (substitutedValueParameters == null) {
256                    return null;
257                }
258                if (substitutedValueParameters.size() != 1) {
259                    throw new IllegalStateException();
260                }
261                newSetter.initialize(substitutedValueParameters.get(0));
262            }
263    
264            substitutedDescriptor.initialize(newGetter, newSetter);
265    
266            if (copyOverrides) {
267                for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
268                    OverridingUtil.bindOverride(substitutedDescriptor, propertyDescriptor.substitute(substitutor));
269                }
270            }
271    
272            return substitutedDescriptor;
273        }
274    
275        @NotNull
276        private static Visibility convertVisibility(Visibility orig, Visibility candidate) {
277            if (candidate == Visibilities.INHERITED) {
278                return candidate;
279            }
280    
281            Integer result = Visibilities.compare(orig, candidate);
282            return result != null && result < 0 ? candidate : orig;
283        }
284    
285        @Override
286        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
287            return visitor.visitPropertyDescriptor(this, data);
288        }
289    
290        @NotNull
291        @Override
292        public PropertyDescriptor getOriginal() {
293            return original == this ? this : original.getOriginal();
294        }
295    
296        @Override
297        public Kind getKind() {
298            return kind;
299        }
300    
301        @Override
302        public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overridden) {
303            overriddenProperties.add((PropertyDescriptorImpl) overridden);
304        }
305    
306        @NotNull
307        @Override
308        public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
309            return overriddenProperties;
310        }
311    
312        @NotNull
313        @Override
314        public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
315            return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, false, copyOverrides, kind);
316        }
317    }