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