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