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