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