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