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 ) {
064 super(containingDeclaration, annotations, name, null);
065 this.isVar = isVar;
066 this.modality = modality;
067 this.visibility = visibility;
068 this.original = original == null ? this : original;
069 this.kind = kind;
070 }
071
072 @NotNull
073 public static PropertyDescriptorImpl create(
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 return new PropertyDescriptorImpl(containingDeclaration, null, annotations, modality, visibility, isVar, name, kind);
083 }
084
085 public void setType(
086 @NotNull JetType outType,
087 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
088 @Nullable ReceiverParameterDescriptor expectedThisObject,
089 @Nullable JetType receiverType
090 ) {
091 ReceiverParameterDescriptor receiverParameter = DescriptorFactory.createReceiverParameterForCallable(this, receiverType);
092 setType(outType, typeParameters, expectedThisObject, receiverParameter);
093 }
094
095 public void setType(
096 @NotNull JetType outType,
097 @NotNull List<? extends TypeParameterDescriptor> typeParameters,
098 @Nullable ReceiverParameterDescriptor expectedThisObject,
099 @Nullable ReceiverParameterDescriptor receiverParameter
100 ) {
101 setOutType(outType);
102
103 this.typeParameters = Lists.newArrayList(typeParameters);
104
105 this.receiverParameter = receiverParameter;
106 this.expectedThisObject = expectedThisObject;
107 }
108
109 public void initialize(@Nullable PropertyGetterDescriptorImpl getter, @Nullable PropertySetterDescriptor setter) {
110 this.getter = getter;
111 this.setter = setter;
112 }
113
114 public void setSetterProjectedOut(boolean setterProjectedOut) {
115 this.setterProjectedOut = setterProjectedOut;
116 }
117
118 public void setVisibility(@NotNull Visibility visibility) {
119 this.visibility = visibility;
120 }
121
122 @NotNull
123 @Override
124 public List<TypeParameterDescriptor> getTypeParameters() {
125 return typeParameters;
126 }
127
128 @Override
129 @Nullable
130 public ReceiverParameterDescriptor getReceiverParameter() {
131 return receiverParameter;
132 }
133
134 @Nullable
135 @Override
136 public ReceiverParameterDescriptor getExpectedThisObject() {
137 return expectedThisObject;
138 }
139
140 @NotNull
141 @Override
142 public JetType getReturnType() {
143 return getType();
144 }
145
146 @Override
147 public boolean isVar() {
148 return isVar;
149 }
150
151 @NotNull
152 @Override
153 public Modality getModality() {
154 return modality;
155 }
156
157 @NotNull
158 @Override
159 public Visibility getVisibility() {
160 return visibility;
161 }
162
163 @Override
164 @Nullable
165 public PropertyGetterDescriptorImpl getGetter() {
166 return getter;
167 }
168
169 @Override
170 @Nullable
171 public PropertySetterDescriptor getSetter() {
172 return setter;
173 }
174
175 @Override
176 public boolean isSetterProjectedOut() {
177 return setterProjectedOut;
178 }
179
180 @Override
181 @NotNull
182 public List<PropertyAccessorDescriptor> getAccessors() {
183 List<PropertyAccessorDescriptor> r = Lists.newArrayListWithCapacity(2);
184 if (getter != null) {
185 r.add(getter);
186 }
187 if (setter != null) {
188 r.add(setter);
189 }
190 return r;
191 }
192
193 @Override
194 public PropertyDescriptor substitute(@NotNull TypeSubstitutor originalSubstitutor) {
195 if (originalSubstitutor.isEmpty()) {
196 return this;
197 }
198 return doSubstitute(originalSubstitutor, getContainingDeclaration(), modality, visibility, getOriginal(), true, getKind());
199 }
200
201 @Nullable
202 private PropertyDescriptor doSubstitute(
203 @NotNull TypeSubstitutor originalSubstitutor,
204 @NotNull DeclarationDescriptor newOwner,
205 @NotNull Modality newModality,
206 @NotNull Visibility newVisibility,
207 @Nullable PropertyDescriptor original,
208 boolean copyOverrides,
209 @NotNull Kind kind
210 ) {
211 PropertyDescriptorImpl substitutedDescriptor = createSubstitutedCopy(newOwner, newModality, newVisibility, original, kind);
212
213 List<TypeParameterDescriptor> substitutedTypeParameters = Lists.newArrayList();
214 TypeSubstitutor substitutor = DescriptorSubstitutor.substituteTypeParameters(getTypeParameters(), originalSubstitutor, substitutedDescriptor, substitutedTypeParameters);
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 substitutedExpectedThisObject;
224 ReceiverParameterDescriptor expectedThisObject = getExpectedThisObject();
225 if (expectedThisObject != null) {
226 substitutedExpectedThisObject = expectedThisObject.substitute(substitutor);
227 if (substitutedExpectedThisObject == null) return null;
228 }
229 else {
230 substitutedExpectedThisObject = null;
231 }
232
233 JetType substitutedReceiverType;
234 if (receiverParameter != null) {
235 substitutedReceiverType = substitutor.substitute(receiverParameter.getType(), Variance.IN_VARIANCE);
236 if (substitutedReceiverType == null) return null;
237 }
238 else {
239 substitutedReceiverType = null;
240 }
241
242 substitutedDescriptor.setType(outType, substitutedTypeParameters, substitutedExpectedThisObject, 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()
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()
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);
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 }