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.*;
032    
033    import static org.jetbrains.kotlin.resolve.descriptorUtil.DescriptorUtilPackage.getBuiltIns;
034    
035    public class PropertyDescriptorImpl extends VariableDescriptorImpl implements PropertyDescriptor {
036        private final Modality modality;
037        private Visibility visibility;
038        private final boolean isVar;
039        private final Set<PropertyDescriptor> overriddenProperties = new LinkedHashSet<PropertyDescriptor>(); // LinkedHashSet is essential here
040        private final PropertyDescriptor original;
041        private final Kind kind;
042    
043        private ReceiverParameterDescriptor dispatchReceiverParameter;
044        private ReceiverParameterDescriptor extensionReceiverParameter;
045        private List<TypeParameterDescriptor> typeParameters;
046        private PropertyGetterDescriptorImpl getter;
047        private PropertySetterDescriptor setter;
048        private boolean setterProjectedOut;
049    
050        protected PropertyDescriptorImpl(
051                @NotNull DeclarationDescriptor containingDeclaration,
052                @Nullable PropertyDescriptor original,
053                @NotNull Annotations annotations,
054                @NotNull Modality modality,
055                @NotNull Visibility visibility,
056                boolean isVar,
057                @NotNull Name name,
058                @NotNull Kind kind,
059                @NotNull SourceElement source
060        ) {
061            super(containingDeclaration, annotations, name, null, source);
062            this.isVar = isVar;
063            this.modality = modality;
064            this.visibility = visibility;
065            this.original = original == null ? this : original;
066            this.kind = kind;
067        }
068    
069        @NotNull
070        public static PropertyDescriptorImpl create(
071                @NotNull DeclarationDescriptor containingDeclaration,
072                @NotNull Annotations annotations,
073                @NotNull Modality modality,
074                @NotNull Visibility visibility,
075                boolean isVar,
076                @NotNull Name name,
077                @NotNull Kind kind,
078                @NotNull SourceElement source
079        ) {
080            return new PropertyDescriptorImpl(containingDeclaration, null, annotations, modality, visibility, isVar, name, kind, source);
081        }
082    
083        public void setType(
084                @NotNull JetType outType,
085                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
086                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
087                @Nullable JetType receiverType
088        ) {
089            ReceiverParameterDescriptor extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverType);
090            setType(outType, typeParameters, dispatchReceiverParameter, extensionReceiverParameter);
091        }
092    
093        public void setType(
094                @NotNull JetType outType,
095                @NotNull List<? extends TypeParameterDescriptor> typeParameters,
096                @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
097                @Nullable ReceiverParameterDescriptor extensionReceiverParameter
098        ) {
099            setOutType(outType);
100    
101            this.typeParameters = new ArrayList<TypeParameterDescriptor>(typeParameters);
102    
103            this.extensionReceiverParameter = extensionReceiverParameter;
104            this.dispatchReceiverParameter = dispatchReceiverParameter;
105        }
106    
107        public void initialize(@Nullable PropertyGetterDescriptorImpl getter, @Nullable PropertySetterDescriptor setter) {
108            this.getter = getter;
109            this.setter = setter;
110        }
111    
112        public void setSetterProjectedOut(boolean setterProjectedOut) {
113            this.setterProjectedOut = setterProjectedOut;
114        }
115    
116        public void setVisibility(@NotNull Visibility visibility) {
117            this.visibility = visibility;
118        }
119    
120        @NotNull
121        @Override
122        public List<TypeParameterDescriptor> getTypeParameters() {
123            return typeParameters;
124        }
125    
126        @Override
127        @Nullable
128        public ReceiverParameterDescriptor getExtensionReceiverParameter() {
129            return extensionReceiverParameter;
130        }
131    
132        @Nullable
133        @Override
134        public ReceiverParameterDescriptor getDispatchReceiverParameter() {
135            return dispatchReceiverParameter;
136        }
137    
138        @NotNull
139        @Override
140        public JetType getReturnType() {
141            return getType();
142        }
143    
144        @Override
145        public boolean isVar() {
146            return isVar;
147        }
148    
149        @NotNull
150        @Override
151        public Modality getModality() {
152            return modality;
153        }
154    
155        @NotNull
156        @Override
157        public Visibility getVisibility() {
158            return visibility;
159        }
160    
161        @Override
162        @Nullable
163        public PropertyGetterDescriptorImpl getGetter() {
164            return getter;
165        }
166    
167        @Override
168        @Nullable
169        public PropertySetterDescriptor getSetter() {
170            return setter;
171        }
172    
173        @Override
174        public boolean isSetterProjectedOut() {
175            return setterProjectedOut;
176        }
177    
178        @Override
179        @NotNull
180        public List<PropertyAccessorDescriptor> getAccessors() {
181            List<PropertyAccessorDescriptor> result = new ArrayList<PropertyAccessorDescriptor>(2);
182            if (getter != null) {
183                result.add(getter);
184            }
185            if (setter != null) {
186                result.add(setter);
187            }
188            return result;
189        }
190    
191        @Override
192        public PropertyDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
193            if (originalSubstitutor.isEmpty()) {
194                return this;
195            }
196            return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, getOriginal(), true, getKind());
197        }
198    
199        @Nullable
200        private PropertyDescriptor doSubstitute(
201                @NotNull TypeSubstitutor originalSubstitutor,
202                @NotNull DeclarationDescriptor newOwner,
203                @NotNull Modality newModality,
204                @NotNull Visibility newVisibility,
205                @Nullable PropertyDescriptor original,
206                boolean copyOverrides,
207                @NotNull Kind kind
208        ) {
209            PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, newModality, newVisibility, original, kind);
210    
211            List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
212            List<TypeParameterDescriptor> substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
213            TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
214                    originalTypeParameters, originalSubstitutor, substitutedDescriptor, substitutedTypeParameters
215            );
216    
217            JetType originalOutType = getType();
218            JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
219            if (outType == null) {
220                return null; // TODO : tell the user that the property was projected out
221            }
222    
223    
224            ReceiverParameterDescriptor substitutedDispatchReceiver;
225            ReceiverParameterDescriptor dispatchReceiver = getDispatchReceiverParameter();
226            if (dispatchReceiver != null) {
227                substitutedDispatchReceiver = dispatchReceiver.substitute(substitutor);
228                if (substitutedDispatchReceiver == null) return null;
229            }
230            else {
231                substitutedDispatchReceiver = null;
232            }
233    
234            JetType substitutedReceiverType;
235            if (extensionReceiverParameter != null) {
236                substitutedReceiverType = substitutor.substitute(extensionReceiverParameter.getType(), Variance.IN_VARIANCE);
237                if (substitutedReceiverType == null) return null;
238            }
239            else {
240                substitutedReceiverType = null;
241            }
242    
243            substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedDispatchReceiver, substitutedReceiverType);
244    
245            PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
246                    substitutedDescriptor, getter.getAnnotations(), newModality, convertVisibility(getter.getVisibility(), newVisibility),
247                    getter.hasBody(), getter.isDefault(), kind, getter.getOriginal(), SourceElement.NO_SOURCE
248            );
249            if (newGetter != null) {
250                JetType returnType = getter.getReturnType();
251                newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
252            }
253            PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
254                    substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility),
255                    setter.hasBody(), setter.isDefault(), kind, setter.getOriginal(), SourceElement.NO_SOURCE
256            );
257            if (newSetter != null) {
258                List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(newSetter, setter, substitutor);
259                if (substitutedValueParameters == null) {
260                    // The setter is projected out, e.g. in this case:
261                    //     trait Tr<T> { var v: T }
262                    //     fun test(tr: Tr<out Any?>) { ... }
263                    // we want to tell the user that although the property is declared as a var,
264                    // it can not be assigned to because of the projection
265                    substitutedDescriptor.setSetterProjectedOut(true);
266                    substitutedValueParameters = Collections.<ValueParameterDescriptor>singletonList(
267                            PropertySetterDescriptorImpl.createSetterParameter(newSetter, getBuiltIns(newOwner).getNothingType())
268                    );
269                }
270                if (substitutedValueParameters.size() != 1) {
271                    throw new IllegalStateException();
272                }
273                newSetter.initialize(substitutedValueParameters.get(0));
274            }
275    
276            substitutedDescriptor.initialize(newGetter, newSetter);
277    
278            if (copyOverrides) {
279                for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
280                    OverridingUtil.bindOverride(substitutedDescriptor, propertyDescriptor.substitute(substitutor));
281                }
282            }
283    
284            return substitutedDescriptor;
285        }
286    
287        @NotNull
288        protected PropertyDescriptorImpl createSubstitutedCopy(
289                @NotNull DeclarationDescriptor newOwner,
290                @NotNull Modality newModality,
291                @NotNull Visibility newVisibility,
292                @Nullable PropertyDescriptor original,
293                @NotNull Kind kind
294        ) {
295            return new PropertyDescriptorImpl(newOwner, original,
296                                              getAnnotations(), newModality, newVisibility, isVar(), getName(), kind, SourceElement.NO_SOURCE);
297        }
298    
299        @NotNull
300        private static Visibility convertVisibility(Visibility orig, Visibility candidate) {
301            if (candidate == Visibilities.INHERITED) {
302                return candidate;
303            }
304    
305            Integer result = Visibilities.compare(orig, candidate);
306            return result != null && result < 0 ? candidate : orig;
307        }
308    
309        @Override
310        public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
311            return visitor.visitPropertyDescriptor(this, data);
312        }
313    
314        @NotNull
315        @Override
316        public PropertyDescriptor getOriginal() {
317            return original == this ? this : original.getOriginal();
318        }
319    
320        @NotNull
321        @Override
322        public Kind getKind() {
323            return kind;
324        }
325    
326        @Override
327        public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overridden) {
328            overriddenProperties.add((PropertyDescriptorImpl) overridden);
329        }
330    
331        @NotNull
332        @Override
333        public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
334            return overriddenProperties;
335        }
336    
337        @NotNull
338        @Override
339        public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
340            return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, null, copyOverrides, kind);
341        }
342    }