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 }