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