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 }