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 com.google.common.collect.Lists;
020 import com.google.common.collect.Sets;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
025 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
026 import org.jetbrains.jet.lang.resolve.OverridingUtil;
027 import org.jetbrains.jet.lang.resolve.name.Name;
028 import org.jetbrains.jet.lang.types.DescriptorSubstitutor;
029 import org.jetbrains.jet.lang.types.JetType;
030 import org.jetbrains.jet.lang.types.TypeSubstitutor;
031 import org.jetbrains.jet.lang.types.Variance;
032 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
033
034 import java.util.Collections;
035 import java.util.List;
036 import java.util.Set;
037
038 public class PropertyDescriptorImpl extends VariableDescriptorImpl implements PropertyDescriptor {
039
040 private final Modality modality;
041 private Visibility visibility;
042 private final boolean isVar;
043 private final Set<PropertyDescriptor> overriddenProperties = Sets.newLinkedHashSet(); // LinkedHashSet is essential here
044 private final PropertyDescriptor original;
045 private final Kind kind;
046
047 private ReceiverParameterDescriptor expectedThisObject;
048 private ReceiverParameterDescriptor receiverParameter;
049 private List<TypeParameterDescriptor> typeParameters;
050 private PropertyGetterDescriptorImpl getter;
051 private PropertySetterDescriptor setter;
052 private boolean setterProjectedOut;
053
054 protected PropertyDescriptorImpl(
055 @NotNull DeclarationDescriptor containingDeclaration,
056 @Nullable PropertyDescriptor original,
057 @NotNull Annotations annotations,
058 @NotNull Modality modality,
059 @NotNull Visibility visibility,
060 boolean isVar,
061 @NotNull Name name,
062 @NotNull Kind kind,
063 @NotNull SourceElement source
064 ) {
065 super(containingDeclaration, annotations, name, null, source);
066 this.isVar = isVar;
067 this.modality = modality;
068 this.visibility = visibility;
069 this.original = original == null ? this : original;
070 this.kind = kind;
071 }
072
073 @NotNull
074 public static PropertyDescriptorImpl create(
075 @NotNull DeclarationDescriptor containingDeclaration,
076 @NotNull Annotations annotations,
077 @NotNull Modality modality,
078 @NotNull Visibility visibility,
079 boolean isVar,
080 @NotNull Name name,
081 @NotNull Kind kind,
082 @NotNull SourceElement source
083 ) {
084 return new PropertyDescriptorImpl(containingDeclaration, null, annotations, modality, visibility, isVar, name, kind, source);
085 }
086
087 public void setType(
088 @NotNull JetType outType,
089 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
090 @Nullable ReceiverParameterDescriptor expectedThisObject,
091 @Nullable JetType receiverType
092 ) {
093 ReceiverParameterDescriptor receiverParameter = DescriptorFactory.createReceiverParameterForCallable(this, receiverType);
094 setType(outType, typeParameters, expectedThisObject, receiverParameter);
095 }
096
097 public void setType(
098 @NotNull JetType outType,
099 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
100 @Nullable ReceiverParameterDescriptor expectedThisObject,
101 @Nullable ReceiverParameterDescriptor receiverParameter
102 ) {
103 setOutType(outType);
104
105 this.typeParameters = Lists.newArrayList(typeParameters);
106
107 this.receiverParameter = receiverParameter;
108 this.expectedThisObject = expectedThisObject;
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 getReceiverParameter() {
133 return receiverParameter;
134 }
135
136 @Nullable
137 @Override
138 public ReceiverParameterDescriptor getExpectedThisObject() {
139 return expectedThisObject;
140 }
141
142 @NotNull
143 @Override
144 public JetType getReturnType() {
145 return getType();
146 }
147
148 @Override
149 public boolean isVar() {
150 return isVar;
151 }
152
153 @NotNull
154 @Override
155 public Modality getModality() {
156 return modality;
157 }
158
159 @NotNull
160 @Override
161 public Visibility getVisibility() {
162 return visibility;
163 }
164
165 @Override
166 @Nullable
167 public PropertyGetterDescriptorImpl getGetter() {
168 return getter;
169 }
170
171 @Override
172 @Nullable
173 public PropertySetterDescriptor getSetter() {
174 return setter;
175 }
176
177 @Override
178 public boolean isSetterProjectedOut() {
179 return setterProjectedOut;
180 }
181
182 @Override
183 @NotNull
184 public List<PropertyAccessorDescriptor> getAccessors() {
185 List<PropertyAccessorDescriptor> r = Lists.newArrayListWithCapacity(2);
186 if (getter != null) {
187 r.add(getter);
188 }
189 if (setter != null) {
190 r.add(setter);
191 }
192 return r;
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> substitutedTypeParameters = Lists.newArrayList();
216 TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
217
218 JetType originalOutType = getType();
219 JetType outType = substitutor.substitute(originalOutType, Variance.OUT_VARIANCE);
220 if (outType == null) {
221 return null; // TODO : tell the user that the property was projected out
222 }
223
224
225 ReceiverParameterDescriptor substitutedExpectedThisObject;
226 ReceiverParameterDescriptor expectedThisObject = getExpectedThisObject();
227 if (expectedThisObject != null) {
228 substitutedExpectedThisObject = expectedThisObject.substitute(substitutor);
229 if (substitutedExpectedThisObject == null) return null;
230 }
231 else {
232 substitutedExpectedThisObject = null;
233 }
234
235 JetType substitutedReceiverType;
236 if (receiverParameter != null) {
237 substitutedReceiverType = substitutor.substitute(receiverParameter.getType(), Variance.IN_VARIANCE);
238 if (substitutedReceiverType == null) return null;
239 }
240 else {
241 substitutedReceiverType = null;
242 }
243
244 substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedExpectedThisObject, substitutedReceiverType);
245
246 PropertyGetterDescriptorImpl newGetter = getter == null ? null : new PropertyGetterDescriptorImpl(
247 substitutedDescriptor, getter.getAnnotations(), newModality, convertVisibility(getter.getVisibility(), newVisibility),
248 getter.hasBody(), getter.isDefault(), kind, getter.getOriginal(), SourceElement.NO_SOURCE
249 );
250 if (newGetter != null) {
251 JetType returnType = getter.getReturnType();
252 newGetter.initialize(returnType != null ? substitutor.substitute(returnType, Variance.OUT_VARIANCE) : null);
253 }
254 PropertySetterDescriptorImpl newSetter = setter == null ? null : new PropertySetterDescriptorImpl(
255 substitutedDescriptor, setter.getAnnotations(), newModality, convertVisibility(setter.getVisibility(), newVisibility),
256 setter.hasBody(), setter.isDefault(), kind, setter.getOriginal(), SourceElement.NO_SOURCE
257 );
258 if (newSetter != null) {
259 List<ValueParameterDescriptor> substitutedValueParameters = FunctionDescriptorImpl.getSubstitutedValueParameters(newSetter, setter, substitutor);
260 if (substitutedValueParameters == null) {
261 // The setter is projected out, e.g. in this case:
262 // trait Tr<T> { var v: T }
263 // fun test(tr: Tr<out Any?>) { ... }
264 // we want to tell the user that although the property is declared as a var,
265 // it can not be assigned to because of the projection
266 substitutedDescriptor.setSetterProjectedOut(true);
267 substitutedValueParameters = Collections.<ValueParameterDescriptor>singletonList(
268 PropertySetterDescriptorImpl.createSetterParameter(newSetter, KotlinBuiltIns.getInstance().getNothingType())
269 );
270 }
271 if (substitutedValueParameters.size() != 1) {
272 throw new IllegalStateException();
273 }
274 newSetter.initialize(substitutedValueParameters.get(0));
275 }
276
277 substitutedDescriptor.initialize(newGetter, newSetter);
278
279 if (copyOverrides) {
280 for (PropertyDescriptor propertyDescriptor : overriddenProperties) {
281 OverridingUtil.bindOverride(substitutedDescriptor, propertyDescriptor.substitute(substitutor));
282 }
283 }
284
285 return substitutedDescriptor;
286 }
287
288 @NotNull
289 protected PropertyDescriptorImpl createSubstitutedCopy(
290 @NotNull DeclarationDescriptor newOwner,
291 @NotNull Modality newModality,
292 @NotNull Visibility newVisibility,
293 @Nullable PropertyDescriptor original,
294 @NotNull Kind kind
295 ) {
296 return new PropertyDescriptorImpl(newOwner, original,
297 getAnnotations(), newModality, newVisibility, isVar(), getName(), kind, SourceElement.NO_SOURCE);
298 }
299
300 @NotNull
301 private static Visibility convertVisibility(Visibility orig, Visibility candidate) {
302 if (candidate == Visibilities.INHERITED) {
303 return candidate;
304 }
305
306 Integer result = Visibilities.compare(orig, candidate);
307 return result != null && result < 0 ? candidate : orig;
308 }
309
310 @Override
311 public <R, D> R accept(DeclarationDescriptorVisitor<R, D> visitor, D data) {
312 return visitor.visitPropertyDescriptor(this, data);
313 }
314
315 @NotNull
316 @Override
317 public PropertyDescriptor getOriginal() {
318 return original == this ? this : original.getOriginal();
319 }
320
321 @NotNull
322 @Override
323 public Kind getKind() {
324 return kind;
325 }
326
327 @Override
328 public void addOverriddenDescriptor(@NotNull CallableMemberDescriptor overridden) {
329 overriddenProperties.add((PropertyDescriptorImpl) overridden);
330 }
331
332 @NotNull
333 @Override
334 public Set<? extends PropertyDescriptor> getOverriddenDescriptors() {
335 return overriddenProperties;
336 }
337
338 @NotNull
339 @Override
340 public PropertyDescriptor copy(DeclarationDescriptor newOwner, Modality modality, Visibility visibility, Kind kind, boolean copyOverrides) {
341 return doSubstitute(TypeSubstitutor.EMPTY, newOwner, modality, visibility, null, copyOverrides, kind);
342 }
343 }