001 /*
002 * Copyright 2010-2013 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.jet.lang.descriptors.impl;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.descriptors.*;
022 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
023 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
024 import org.jetbrains.jet.lang.resolve.OverridingUtil;
025 import org.jetbrains.jet.lang.resolve.name.Name;
026 import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
027 import org.jetbrains.jet.lang.types.JetType;
028 import org.jetbrains.jet.lang.types.TypeSubstitutor;
029 import org.jetbrains.jet.lang.types.Variance;
030 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
031
032 import java.util.*;
033
034 public class PropertyDescriptorImpl extends VariableDescriptorImpl implements PropertyDescriptor {
035 private final Modality modality;
036 private Visibility visibility;
037 private final boolean isVar;
038 private final Set<PropertyDescriptor> overriddenProperties = new LinkedHashSet<PropertyDescriptor>(); // LinkedHashSet is essential here
039 private final PropertyDescriptor original;
040 private final Kind kind;
041
042 private ReceiverParameterDescriptor dispatchReceiverParameter;
043 private ReceiverParameterDescriptor extensionReceiverParameter;
044 private List<TypeParameterDescriptor> typeParameters;
045 private PropertyGetterDescriptorImpl getter;
046 private PropertySetterDescriptor setter;
047 private boolean setterProjectedOut;
048
049 protected PropertyDescriptorImpl(
050 @NotNull DeclarationDescriptor containingDeclaration,
051 @Nullable PropertyDescriptor original,
052 @NotNull Annotations annotations,
053 @NotNull Modality modality,
054 @NotNull Visibility visibility,
055 boolean isVar,
056 @NotNull Name name,
057 @NotNull Kind kind,
058 @NotNull SourceElement source
059 ) {
060 super(containingDeclaration, annotations, name, null, source);
061 this.isVar = isVar;
062 this.modality = modality;
063 this.visibility = visibility;
064 this.original = original == null ? this : original;
065 this.kind = kind;
066 }
067
068 @NotNull
069 public static PropertyDescriptorImpl create(
070 @NotNull DeclarationDescriptor containingDeclaration,
071 @NotNull Annotations annotations,
072 @NotNull Modality modality,
073 @NotNull Visibility visibility,
074 boolean isVar,
075 @NotNull Name name,
076 @NotNull Kind kind,
077 @NotNull SourceElement source
078 ) {
079 return new PropertyDescriptorImpl(containingDeclaration, null, annotations, modality, visibility, isVar, name, kind, source);
080 }
081
082 public void setType(
083 @NotNull JetType outType,
084 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
085 @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
086 @Nullable JetType receiverType
087 ) {
088 ReceiverParameterDescriptor extensionReceiverParameter = DescriptorFactory.createExtensionReceiverParameterForCallable(this, receiverType);
089 setType(outType, typeParameters, dispatchReceiverParameter, extensionReceiverParameter);
090 }
091
092 public void setType(
093 @NotNull JetType outType,
094 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
095 @Nullable ReceiverParameterDescriptor dispatchReceiverParameter,
096 @Nullable ReceiverParameterDescriptor extensionReceiverParameter
097 ) {
098 setOutType(outType);
099
100 this.typeParameters = new ArrayList<TypeParameterDescriptor>(typeParameters);
101
102 this.extensionReceiverParameter = extensionReceiverParameter;
103 this.dispatchReceiverParameter = dispatchReceiverParameter;
104 }
105
106 public void initialize(@Nullable PropertyGetterDescriptorImpl getter, @Nullable PropertySetterDescriptor setter) {
107 this.getter = getter;
108 this.setter = setter;
109 }
110
111 public void setSetterProjectedOut(boolean setterProjectedOut) {
112 this.setterProjectedOut = setterProjectedOut;
113 }
114
115 public void setVisibility(@NotNull Visibility visibility) {
116 this.visibility = visibility;
117 }
118
119 @NotNull
120 @Override
121 public List<TypeParameterDescriptor> getTypeParameters() {
122 return typeParameters;
123 }
124
125 @Override
126 @Nullable
127 public ReceiverParameterDescriptor getExtensionReceiverParameter() {
128 return extensionReceiverParameter;
129 }
130
131 @Nullable
132 @Override
133 public ReceiverParameterDescriptor getDispatchReceiverParameter() {
134 return dispatchReceiverParameter;
135 }
136
137 @NotNull
138 @Override
139 public JetType getReturnType() {
140 return getType();
141 }
142
143 @Override
144 public boolean isVar() {
145 return isVar;
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 @NotNull
179 public List<PropertyAccessorDescriptor> getAccessors() {
180 List<PropertyAccessorDescriptor> result = new ArrayList<PropertyAccessorDescriptor>(2);
181 if (getter != null) {
182 result.add(getter);
183 }
184 if (setter != null) {
185 result.add(setter);
186 }
187 return result;
188 }
189
190 @Override
191 public PropertyDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
192 if (originalSubstitutor.isEmpty()) {
193 return this;
194 }
195 return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, getOriginal(), true, getKind());
196 }
197
198 @Nullable
199 private PropertyDescriptor doSubstitute(
200 @NotNull TypeSubstitutor originalSubstitutor,
201 @NotNull DeclarationDescriptor newOwner,
202 @NotNull Modality newModality,
203 @NotNull Visibility newVisibility,
204 @Nullable PropertyDescriptor original,
205 boolean copyOverrides,
206 @NotNull Kind kind
207 ) {
208 PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, newModality, newVisibility, original, kind);
209
210 List<TypeParameterDescriptor> originalTypeParameters = getTypeParameters();
211 List<TypeParameterDescriptor> substitutedTypeParameters = new ArrayList<TypeParameterDescriptor>(originalTypeParameters.size());
212 TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(
213 originalTypeParameters, originalSubstitutor, substitutedDescriptor, substitutedTypeParameters
214 );
215
216 JetType originalOutType = getType();
217 JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
218 if (outType == null) {
219 return null; // TODO : tell the user that the property was projected out
220 }
221
222
223 ReceiverParameterDescriptor substitutedDispatchReceiver;
224 ReceiverParameterDescriptor dispatchReceiver = getDispatchReceiverParameter();
225 if (dispatchReceiver != null) {
226 substitutedDispatchReceiver = dispatchReceiver.substitute(substitutor);
227 if (substitutedDispatchReceiver == null) return null;
228 }
229 else {
230 substitutedDispatchReceiver = null;
231 }
232
233 JetType substitutedReceiverType;
234 if (extensionReceiverParameter != null) {
235 substitutedReceiverType = substitutor.substitute(extensionReceiverParameter.getType(), Variance.IN_VARIANCE);
236 if (substitutedReceiverType == null) return null;
237 }
238 else {
239 substitutedReceiverType = null;
240 }
241
242 substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedDispatchReceiver, substitutedReceiverType);
243
244 PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
245 substitutedDescriptor, getter.getAnnotations(), newModality, convertVisibility(getter.getVisibility(), newVisibility),
246 getter.hasBody(), getter.isDefault(), kind, getter.getOriginal(), SourceElement.NO_SOURCE
247 );
248 if (newGetter != null) {
249 JetType returnType = getter.getReturnType();
250 newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
251 }
252 PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
253 substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility),
254 setter.hasBody(), setter.isDefault(), kind, setter.getOriginal(), SourceElement.NO_SOURCE
255 );
256 if (newSetter != null) {
257 List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(newSetter, setter, substitutor);
258 if (substitutedValueParameters == null) {
259 // The setter is projected out, e.g. in this case:
260 // trait Tr<T> { var v: T }
261 // fun test(tr: Tr<out Any?>) { ... }
262 // we want to tell the user that although the property is declared as a var,
263 // it can not be assigned to because of the projection
264 substitutedDescriptor.setSetterProjectedOut(true);
265 substitutedValueParameters = Collections.<ValueParameterDescriptor>singletonList(
266 PropertySetterDescriptorImpl.createSetterParameter(newSetter, KotlinBuiltIns.getInstance().getNothingType())
267 );
268 }
269 if (substitutedValueParameters.size() != 1) {
270 throw new IllegalStateException();
271 }
272 newSetter.initialize(substitutedValueParameters.get(0));
273 }
274
275 substitutedDescriptor.initialize(newGetter, newSetter);
276
277 if (copyOverrides) {
278 for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
279 OverridingUtil.bindOverride(substitutedDescriptor, propertyDescriptor.substitute(substitutor));
280 }
281 }
282
283 return substitutedDescriptor;
284 }
285
286 @NotNull
287 protected PropertyDescriptorImpl createSubstitutedCopy(
288 @NotNull DeclarationDescriptor newOwner,
289 @NotNull Modality newModality,
290 @NotNull Visibility newVisibility,
291 @Nullable PropertyDescriptor original,
292 @NotNull Kind kind
293 ) {
294 return new PropertyDescriptorImpl(newOwner, original,
295 getAnnotations(), newModality, newVisibility, isVar(), getName(), kind, SourceElement.NO_SOURCE);
296 }
297
298 @NotNull
299 private static Visibility convertVisibility(Visibility orig, Visibility candidate) {
300 if (candidate == Visibilities.INHERITED) {
301 return candidate;
302 }
303
304 Integer result = Visibilities.compare(orig, candidate);
305 return result != null && result < 0 ? candidate : orig;
306 }
307
308 @Override
309 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
310 return visitor.visitPropertyDescriptor(this, data);
311 }
312
313 @NotNull
314 @Override
315 public PropertyDescriptor getOriginal() {
316 return original == this ? this : original.getOriginal();
317 }
318
319 @NotNull
320 @Override
321 public Kind getKind() {
322 return kind;
323 }
324
325 @Override
326 public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overridden) {
327 overriddenProperties.add((PropertyDescriptorImpl) overridden);
328 }
329
330 @NotNull
331 @Override
332 public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
333 return overriddenProperties;
334 }
335
336 @NotNull
337 @Override
338 public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
339 return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, null, copyOverrides, kind);
340 }
341 }