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 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 JetType outType,
093 @ReadOnly @NotNull List<? extends TypeParameterDescriptor> typeParameters,
094 @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
095 @Nullable JetType receiverType
096 ) {
097 ReceiverParameterDescriptor extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverType);
098 setType(outType, typeParameters, dispatchReceiverParameter, extensionReceiverParameter);
099 }
100
101 public void setType(
102 @NotNull JetType 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 JetType 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 JetType originalOutType = getType();
231 JetType 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 JetType 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, convertVisibility(getter.getVisibility(), newVisibility),
260 getter.hasBody(), getter.isDefault(), kind, original == null ? null : original.getGetter(), SourceElement.NO_SOURCE
261 );
262 if (newGetter != null) {
263 JetType returnType = getter.getReturnType();
264 newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
265 }
266 PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
267 substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility),
268 setter.hasBody(), setter.isDefault(), kind, original == null ? null : original.getSetter(), SourceElement.NO_SOURCE
269 );
270 if (newSetter != null) {
271 List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(
272 newSetter, setter.getValueParameters(), substitutor
273 );
274 if (substitutedValueParameters == null) {
275 // The setter is projected out, e.g. in this case:
276 // trait Tr<T> { var v: T }
277 // fun test(tr: Tr<out Any?>) { ... }
278 // we want to tell the user that although the property is declared as a var,
279 // it can not be assigned to because of the projection
280 substitutedDescriptor.setSetterProjectedOut(true);
281 substitutedValueParameters = Collections.<ValueParameterDescriptor>singletonList(
282 PropertySetterDescriptorImpl.createSetterParameter(newSetter, getBuiltIns(newOwner).getNothingType())
283 );
284 }
285 if (substitutedValueParameters.size() != 1) {
286 throw new IllegalStateException();
287 }
288 newSetter.initialize(substitutedValueParameters.get(0));
289 }
290
291 substitutedDescriptor.initialize(newGetter, newSetter);
292
293 if (copyOverrides) {
294 for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
295 substitutedDescriptor.addOverriddenDescriptor(propertyDescriptor.substitute(substitutor));
296 }
297 }
298
299 return substitutedDescriptor;
300 }
301
302 @NotNull
303 protected PropertyDescriptorImpl createSubstitutedCopy(
304 @NotNull DeclarationDescriptor newOwner,
305 @NotNull Modality newModality,
306 @NotNull Visibility newVisibility,
307 @Nullable PropertyDescriptor original,
308 @NotNull Kind kind
309 ) {
310 return new PropertyDescriptorImpl(newOwner, original,
311 getAnnotations(), newModality, newVisibility,
312 isVar(), getName(), kind, SourceElement.NO_SOURCE, isLateInit(), isConst());
313 }
314
315 @NotNull
316 private static Visibility convertVisibility(Visibility orig, Visibility candidate) {
317 if (candidate == Visibilities.INHERITED) {
318 return candidate;
319 }
320
321 Integer result = Visibilities.compare(orig, candidate);
322 return result != null && result < 0 ? candidate : orig;
323 }
324
325 @Override
326 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
327 return visitor.visitPropertyDescriptor(this, data);
328 }
329
330 @NotNull
331 @Override
332 public PropertyDescriptor getOriginal() {
333 return original == this ? this : original.getOriginal();
334 }
335
336 @NotNull
337 @Override
338 public Kind getKind() {
339 return kind;
340 }
341
342 @Override
343 public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overridden) {
344 overriddenProperties.add((PropertyDescriptorImpl) overridden);
345 }
346
347 @NotNull
348 @Override
349 public Collection<? extends PropertyDescriptor> getOverriddenDescriptors() {
350 return overriddenProperties;
351 }
352
353 @NotNull
354 @Override
355 public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
356 return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, null, copyOverrides, kind);
357 }
358 }