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 }