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.resolve;
018
019 import com.google.common.collect.Maps;
020 import com.google.common.collect.Sets;
021 import com.intellij.psi.PsiElement;
022 import com.intellij.util.containers.Queue;
023 import org.jetbrains.annotations.NotNull;
024 import org.jetbrains.annotations.Nullable;
025 import org.jetbrains.jet.lang.descriptors.*;
026 import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
027 import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
028 import org.jetbrains.jet.lang.psi.*;
029 import org.jetbrains.jet.lang.resolve.calls.CallResolver;
030 import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
031 import org.jetbrains.jet.lang.resolve.calls.context.ExpressionPosition;
032 import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCacheImpl;
033 import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
034 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
035 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
036 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemCompleter;
037 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
038 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
039 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
040 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
041 import org.jetbrains.jet.lang.resolve.scopes.*;
042 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
043 import org.jetbrains.jet.lang.types.*;
044 import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
045 import org.jetbrains.jet.lang.types.expressions.DelegatedPropertyUtils;
046 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
047 import org.jetbrains.jet.lang.types.expressions.LabelResolver;
048 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
049 import org.jetbrains.jet.lexer.JetTokens;
050 import org.jetbrains.jet.util.Box;
051 import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
052 import org.jetbrains.jet.util.slicedmap.WritableSlice;
053
054 import javax.inject.Inject;
055 import java.util.*;
056
057 import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
058 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
059 import static org.jetbrains.jet.lang.resolve.BindingContext.CONSTRAINT_SYSTEM_COMPLETER;
060 import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
061 import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code;
062 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
063
064 public class BodyResolver {
065 @NotNull
066 private BodiesResolveContext context;
067 @NotNull
068 private TopDownAnalysisParameters topDownAnalysisParameters;
069 @NotNull
070 private DescriptorResolver descriptorResolver;
071 @NotNull
072 private ScriptBodyResolver scriptBodyResolverResolver;
073 @NotNull
074 private ExpressionTypingServices expressionTypingServices;
075 @NotNull
076 private CallResolver callResolver;
077 @NotNull
078 private ObservableBindingTrace trace;
079 @NotNull
080 private ControlFlowAnalyzer controlFlowAnalyzer;
081 @NotNull
082 private DeclarationsChecker declarationsChecker;
083 @NotNull
084 private AnnotationResolver annotationResolver;
085
086 @Inject
087 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
088 this.topDownAnalysisParameters = topDownAnalysisParameters;
089 }
090
091 @Inject
092 public void setDescriptorResolver(@NotNull DescriptorResolver descriptorResolver) {
093 this.descriptorResolver = descriptorResolver;
094 }
095
096 @Inject
097 public void setScriptBodyResolverResolver(@NotNull ScriptBodyResolver scriptBodyResolverResolver) {
098 this.scriptBodyResolverResolver = scriptBodyResolverResolver;
099 }
100
101 @Inject
102 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
103 this.expressionTypingServices = expressionTypingServices;
104 }
105
106 @Inject
107 public void setCallResolver(@NotNull CallResolver callResolver) {
108 this.callResolver = callResolver;
109 }
110
111 @Inject
112 public void setTrace(@NotNull BindingTrace trace) {
113 this.trace = new ObservableBindingTrace(trace);
114 }
115
116 @Inject
117 public void setControlFlowAnalyzer(@NotNull ControlFlowAnalyzer controlFlowAnalyzer) {
118 this.controlFlowAnalyzer = controlFlowAnalyzer;
119 }
120
121 @Inject
122 public void setDeclarationsChecker(@NotNull DeclarationsChecker declarationsChecker) {
123 this.declarationsChecker = declarationsChecker;
124 }
125
126 @Inject
127 public void setContext(@NotNull BodiesResolveContext context) {
128 this.context = context;
129 }
130
131 @Inject
132 public void setAnnotationResolver(@NotNull AnnotationResolver annotationResolver) {
133 this.annotationResolver = annotationResolver;
134 }
135
136 private void resolveBehaviorDeclarationBodies(@NotNull BodiesResolveContext bodiesResolveContext) {
137 // Initialize context
138 context = bodiesResolveContext;
139
140 resolveDelegationSpecifierLists();
141
142 resolvePropertyDeclarationBodies();
143 resolveClassAnnotations();
144 resolveAnonymousInitializers();
145 resolvePrimaryConstructorParameters();
146
147 resolveFunctionBodies();
148
149 scriptBodyResolverResolver.resolveScriptBodies();
150
151 if (!topDownAnalysisParameters.isDeclaredLocally()) {
152 computeDeferredTypes();
153 }
154 }
155
156 public void resolveBodies() {
157 resolveBehaviorDeclarationBodies(context);
158 controlFlowAnalyzer.process(context);
159 declarationsChecker.process(context);
160 }
161
162 private void resolveDelegationSpecifierLists() {
163 // TODO : Make sure the same thing is not initialized twice
164 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
165 resolveDelegationSpecifierList(entry.getKey(), entry.getValue());
166 }
167 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
168 resolveDelegationSpecifierList(entry.getKey(), entry.getValue());
169 }
170 }
171
172 private void resolveDelegationSpecifierList(JetClassOrObject jetClass, MutableClassDescriptor descriptor) {
173 resolveDelegationSpecifierList(jetClass, descriptor,
174 descriptor.getUnsubstitutedPrimaryConstructor(),
175 descriptor.getScopeForSupertypeResolution(),
176 descriptor.getScopeForMemberResolution());
177 }
178
179 public void resolveDelegationSpecifierList(@NotNull JetClassOrObject jetClass, @NotNull final ClassDescriptor descriptor,
180 @Nullable final ConstructorDescriptor primaryConstructor,
181 @NotNull JetScope scopeForSupertypeResolution,
182 @NotNull final JetScope scopeForMemberResolution) {
183 if (!context.completeAnalysisNeeded(jetClass)) return;
184 final JetScope scopeForConstructor = primaryConstructor == null
185 ? null
186 : FunctionDescriptorUtil.getFunctionInnerScope(scopeForSupertypeResolution, primaryConstructor, trace);
187 final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow
188
189 final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
190 JetVisitorVoid visitor = new JetVisitorVoid() {
191 private void recordSupertype(JetTypeReference typeReference, JetType supertype) {
192 if (supertype == null) return;
193 supertypes.put(typeReference, supertype);
194 }
195
196 @Override
197 public void visitDelegationByExpressionSpecifier(JetDelegatorByExpressionSpecifier specifier) {
198 if (descriptor.getKind() == ClassKind.TRAIT) {
199 trace.report(DELEGATION_IN_TRAIT.on(specifier));
200 }
201 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
202 recordSupertype(specifier.getTypeReference(), supertype);
203 if (supertype != null) {
204 DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
205 if (declarationDescriptor instanceof ClassDescriptor) {
206 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
207 if (classDescriptor.getKind() != ClassKind.TRAIT) {
208 trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
209 }
210 }
211 }
212 JetExpression delegateExpression = specifier.getDelegateExpression();
213 if (delegateExpression != null) {
214 JetScope scope = scopeForConstructor == null
215 ? scopeForMemberResolution
216 : scopeForConstructor;
217 JetType type = typeInferrer.getType(scope, delegateExpression, NO_EXPECTED_TYPE, context.getOuterDataFlowInfo(), trace);
218 if (type != null && supertype != null) {
219 SimpleResolutionContext simpleResolutionContext = new SimpleResolutionContext(
220 trace, scope, supertype, context.getOuterDataFlowInfo(), ExpressionPosition.FREE, ContextDependency.INDEPENDENT,
221 ResolutionResultsCacheImpl.create(), LabelResolver.create());
222 DataFlowUtils.checkType(type, delegateExpression, simpleResolutionContext);
223 }
224 }
225 }
226
227 @Override
228 public void visitDelegationToSuperCallSpecifier(JetDelegatorToSuperCall call) {
229 JetValueArgumentList valueArgumentList = call.getValueArgumentList();
230 PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
231 if (descriptor.getKind() == ClassKind.TRAIT) {
232 trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
233 }
234 JetTypeReference typeReference = call.getTypeReference();
235 if (typeReference == null) return;
236 if (primaryConstructor == null) {
237 assert descriptor.getKind() == ClassKind.TRAIT;
238 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
239 return;
240 }
241 OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
242 trace, scopeForConstructor,
243 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, context.getOuterDataFlowInfo());
244 if (results.isSuccess()) {
245 JetType supertype = results.getResultingDescriptor().getReturnType();
246 recordSupertype(typeReference, supertype);
247 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
248 if (classDescriptor != null) {
249 if (classDescriptor.getKind() == ClassKind.TRAIT) {
250 trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark));
251 }
252 }
253 }
254 else {
255 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
256 }
257 }
258
259 @Override
260 public void visitDelegationToSuperClassSpecifier(JetDelegatorToSuperClass specifier) {
261 JetTypeReference typeReference = specifier.getTypeReference();
262 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
263 recordSupertype(typeReference, supertype);
264 if (supertype == null) return;
265 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
266 if (classDescriptor == null) return;
267 if (descriptor.getKind() != ClassKind.TRAIT && !classDescriptor.getConstructors().isEmpty() &&
268 !ErrorUtils.isError(classDescriptor.getTypeConstructor()) && classDescriptor.getKind() != ClassKind.TRAIT) {
269 trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
270 }
271 }
272
273 @Override
274 public void visitDelegationToThisCall(JetDelegatorToThisCall thisCall) {
275 throw new IllegalStateException("This-calls should be prohibited by the parser");
276 }
277
278 @Override
279 public void visitJetElement(JetElement element) {
280 throw new UnsupportedOperationException(element.getText() + " : " + element);
281 }
282 };
283
284 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
285 delegationSpecifier.accept(visitor);
286 }
287
288
289 Set<TypeConstructor> parentEnum = Collections.emptySet();
290 if (jetClass instanceof JetEnumEntry) {
291 parentEnum = Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration().getContainingDeclaration()).getTypeConstructor());
292 }
293
294 checkSupertypeList(descriptor, supertypes, parentEnum);
295 }
296
297 // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
298 private void checkSupertypeList(
299 @NotNull ClassDescriptor supertypeOwner,
300 @NotNull Map<JetTypeReference, JetType> supertypes,
301 @NotNull Set<TypeConstructor> allowedFinalSupertypes
302 ) {
303 Set<TypeConstructor> typeConstructors = Sets.newHashSet();
304 boolean classAppeared = false;
305 for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
306 JetTypeReference typeReference = entry.getKey();
307 JetType supertype = entry.getValue();
308
309 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
310 if (classDescriptor != null) {
311 if (classDescriptor.getKind() != ClassKind.TRAIT) {
312 if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
313 trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
314 }
315 if (classAppeared) {
316 trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
317 }
318 else {
319 classAppeared = true;
320 }
321 }
322 }
323 else {
324 trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
325 }
326
327 TypeConstructor constructor = supertype.getConstructor();
328 if (!typeConstructors.add(constructor)) {
329 trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
330 }
331
332 if (constructor.isSealed() && !allowedFinalSupertypes.contains(constructor)) {
333 trace.report(FINAL_SUPERTYPE.on(typeReference));
334 }
335 }
336 }
337
338 private void resolveClassAnnotations() {
339 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
340 resolveAnnotationArguments(entry.getValue().getScopeForSupertypeResolution(), entry.getKey());
341 }
342 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
343 resolveAnnotationArguments(entry.getValue().getScopeForSupertypeResolution(), entry.getKey());
344 }
345 }
346
347 private void resolveAnonymousInitializers() {
348 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
349 resolveAnonymousInitializers(entry.getKey(), entry.getValue());
350 }
351 for (Map.Entry<JetObjectDeclaration, MutableClassDescriptor> entry : context.getObjects().entrySet()) {
352 resolveAnonymousInitializers(entry.getKey(), entry.getValue());
353 }
354 }
355
356 private void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject, MutableClassDescriptor classDescriptor) {
357 resolveAnonymousInitializers(jetClassOrObject, classDescriptor.getUnsubstitutedPrimaryConstructor(),
358 classDescriptor.getScopeForInitializers());
359 }
360
361 public void resolveAnonymousInitializers(JetClassOrObject jetClassOrObject,
362 @Nullable ConstructorDescriptor primaryConstructor,
363 @NotNull JetScope scopeForInitializers) {
364 if (!context.completeAnalysisNeeded(jetClassOrObject)) {
365 return;
366 }
367 List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers();
368 if (primaryConstructor != null) {
369 for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
370 expressionTypingServices.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, context.getOuterDataFlowInfo(), trace);
371 }
372 }
373 else {
374 for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
375 trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer));
376 }
377 }
378 }
379
380 private void resolvePrimaryConstructorParameters() {
381 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
382 JetClass klass = entry.getKey();
383 MutableClassDescriptor classDescriptor = entry.getValue();
384 ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
385
386 annotationResolver.resolveAnnotationsArguments(classDescriptor.getScopeForSupertypeResolution(), klass.getPrimaryConstructorModifierList(), trace);
387
388 if (unsubstitutedPrimaryConstructor != null) {
389 WritableScope parameterScope = new WritableScopeImpl(classDescriptor.getScopeForSupertypeResolution(), unsubstitutedPrimaryConstructor,
390 RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor");
391 for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
392 parameterScope.addVariableDescriptor(valueParameterDescriptor);
393 }
394 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
395 resolveValueParameter(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
396 parameterScope);
397 }
398 }
399 }
400
401 private void resolvePropertyDeclarationBodies() {
402
403 // Member properties
404 Set<JetProperty> processed = Sets.newHashSet();
405 for (Map.Entry<JetClass, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
406 JetClass jetClass = entry.getKey();
407 if (!context.completeAnalysisNeeded(jetClass)) continue;
408 MutableClassDescriptor classDescriptor = entry.getValue();
409
410 for (JetProperty property : jetClass.getProperties()) {
411 PropertyDescriptor propertyDescriptor = this.context.getProperties().get(property);
412 assert propertyDescriptor != null;
413
414 computeDeferredType(propertyDescriptor.getReturnType());
415
416 JetExpression initializer = property.getInitializer();
417 JetScope propertyScope = getScopeForProperty(property);
418 if (initializer != null) {
419 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
420 if (primaryConstructor != null) {
421 resolvePropertyInitializer(property, propertyDescriptor, initializer, propertyScope);
422 }
423 }
424
425 JetExpression delegateExpression = property.getDelegateExpression();
426 if (delegateExpression != null) {
427 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
428 resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberResolution(), propertyScope);
429 }
430
431 resolveAnnotationArguments(propertyScope, property);
432
433 resolvePropertyAccessors(property, propertyDescriptor);
434 processed.add(property);
435 }
436 }
437
438 // Top-level properties & properties of objects
439 for (Map.Entry<JetProperty, PropertyDescriptor> entry : this.context.getProperties().entrySet()) {
440 JetProperty property = entry.getKey();
441 if (!context.completeAnalysisNeeded(property)) continue;
442 if (processed.contains(property)) continue;
443
444 PropertyDescriptor propertyDescriptor = entry.getValue();
445
446 computeDeferredType(propertyDescriptor.getReturnType());
447
448 JetExpression initializer = property.getInitializer();
449 JetScope propertyScope = getScopeForProperty(property);
450 if (initializer != null) {
451 resolvePropertyInitializer(property, propertyDescriptor, initializer, propertyScope);
452 }
453
454 JetExpression delegateExpression = property.getDelegateExpression();
455 if (delegateExpression != null) {
456 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
457 resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
458 }
459
460 resolveAnnotationArguments(propertyScope, property);
461
462 resolvePropertyAccessors(property, propertyDescriptor);
463 }
464 }
465
466 private JetScope makeScopeForPropertyAccessor(@NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
467 JetScope accessorDeclaringScope = context.getDeclaringScopes().apply(accessor);
468 assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
469 return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, descriptorResolver, trace);
470 }
471
472 public void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor) {
473 ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
474
475 JetPropertyAccessor getter = property.getGetter();
476 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
477 if (getter != null && getterDescriptor != null) {
478 JetScope accessorScope = makeScopeForPropertyAccessor(getter, propertyDescriptor);
479 resolveAnnotationArguments(accessorScope, getter);
480 resolveFunctionBody(fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
481 }
482
483 JetPropertyAccessor setter = property.getSetter();
484 PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
485 if (setter != null && setterDescriptor != null) {
486 JetScope accessorScope = makeScopeForPropertyAccessor(setter, propertyDescriptor);
487 resolveAnnotationArguments(accessorScope, setter);
488 resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
489 }
490 }
491
492 private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
493 return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
494 @Override
495 public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
496 if (expression instanceof JetSimpleNameExpression) {
497 JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
498 if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
499 // This check may be considered redundant as long as $x is only accessible from accessors to $x
500 if (descriptor == propertyDescriptor) { // TODO : original?
501 trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
502 }
503 }
504 }
505 }
506 });
507 }
508
509 public void resolvePropertyDelegate(
510 @NotNull JetProperty jetProperty,
511 @NotNull PropertyDescriptor propertyDescriptor,
512 @NotNull JetExpression delegateExpression,
513 @NotNull JetScope parentScopeForAccessor,
514 @NotNull JetScope propertyScope
515 ) {
516 JetPropertyAccessor getter = jetProperty.getGetter();
517 if (getter != null) {
518 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
519 }
520
521 JetPropertyAccessor setter = jetProperty.getSetter();
522 if (setter != null) {
523 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
524 }
525
526 JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScopeForInitializer(
527 propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
528 TemporaryBindingTrace traceToResolveDelegatedProperty = TemporaryBindingTrace.create(trace, "Trace to resolve delegated property");
529 JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
530 propertyDescriptor, parentScopeForAccessor, descriptorResolver, trace);
531
532 JetExpression calleeExpression = JetPsiUtil.getCalleeExpressionIfAny(delegateExpression);
533 ConstraintSystemCompleter completer =
534 createConstraintSystemCompleter(jetProperty, propertyDescriptor, delegateExpression, accessorScope);
535 if (calleeExpression != null) {
536 traceToResolveDelegatedProperty.record(CONSTRAINT_SYSTEM_COMPLETER, calleeExpression, completer);
537 }
538 JetType delegateType = expressionTypingServices.safeGetType(propertyDeclarationInnerScope, delegateExpression, NO_EXPECTED_TYPE,
539 context.getOuterDataFlowInfo(), traceToResolveDelegatedProperty);
540 traceToResolveDelegatedProperty.commit(new TraceEntryFilter() {
541 @Override
542 public boolean accept(@NotNull WritableSlice<?, ?> slice, Object key) {
543 return slice != CONSTRAINT_SYSTEM_COMPLETER;
544 }
545 }, true);
546
547 DelegatedPropertyUtils.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
548 expressionTypingServices, trace, accessorScope);
549
550 if (jetProperty.isVar()) {
551 DelegatedPropertyUtils.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
552 expressionTypingServices, trace, accessorScope);
553 }
554 }
555
556 private ConstraintSystemCompleter createConstraintSystemCompleter(
557 JetProperty property,
558 final PropertyDescriptor propertyDescriptor,
559 final JetExpression delegateExpression,
560 final JetScope accessorScope
561 ) {
562 final JetType expectedType = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
563 return new ConstraintSystemCompleter() {
564 @Override
565 public void completeConstraintSystem(
566 @NotNull ConstraintSystem constraintSystem, @NotNull ResolvedCall<?> resolvedCall
567 ) {
568 JetType returnType = resolvedCall.getCandidateDescriptor().getReturnType();
569 if (returnType == null) return;
570
571 TemporaryBindingTrace traceToResolveConventionMethods =
572 TemporaryBindingTrace.create(trace, "Trace to resolve delegated property convention methods");
573 OverloadResolutionResults<FunctionDescriptor>
574 getMethodResults = DelegatedPropertyUtils.getDelegatedPropertyConventionMethod(
575 propertyDescriptor, delegateExpression, returnType, expressionTypingServices,
576 traceToResolveConventionMethods, accessorScope, true);
577
578 if (conventionMethodFound(getMethodResults)) {
579 FunctionDescriptor descriptor = getMethodResults.getResultingDescriptor();
580 JetType returnTypeOfGetMethod = descriptor.getReturnType();
581 if (returnTypeOfGetMethod != null) {
582 constraintSystem.addSupertypeConstraint(expectedType, returnTypeOfGetMethod, ConstraintPosition.FROM_COMPLETER);
583 }
584 addConstraintForThisValue(constraintSystem, descriptor);
585 }
586 if (!propertyDescriptor.isVar()) return;
587
588 OverloadResolutionResults<FunctionDescriptor> setMethodResults =
589 DelegatedPropertyUtils.getDelegatedPropertyConventionMethod(
590 propertyDescriptor, delegateExpression, returnType, expressionTypingServices,
591 traceToResolveConventionMethods, accessorScope, false);
592
593 if (conventionMethodFound(setMethodResults)) {
594 FunctionDescriptor descriptor = setMethodResults.getResultingDescriptor();
595 List<ValueParameterDescriptor> valueParameters = descriptor.getValueParameters();
596 if (valueParameters.size() == 3) {
597 ValueParameterDescriptor valueParameterForThis = valueParameters.get(2);
598
599 constraintSystem.addSubtypeConstraint(expectedType, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER);
600 addConstraintForThisValue(constraintSystem, descriptor);
601 }
602 }
603 }
604
605 private boolean conventionMethodFound(@NotNull OverloadResolutionResults<FunctionDescriptor> results) {
606 return results.isSuccess() ||
607 (results.isSingleResult() && results.getResultCode() == Code.SINGLE_CANDIDATE_ARGUMENT_MISMATCH);
608 }
609
610 private void addConstraintForThisValue(ConstraintSystem constraintSystem, FunctionDescriptor resultingDescriptor) {
611 ReceiverParameterDescriptor receiverParameter = propertyDescriptor.getReceiverParameter();
612 ReceiverParameterDescriptor thisObject = propertyDescriptor.getExpectedThisObject();
613 JetType typeOfThis =
614 receiverParameter != null ? receiverParameter.getType() :
615 thisObject != null ? thisObject.getType() :
616 KotlinBuiltIns.getInstance().getNullableNothingType();
617
618 List<ValueParameterDescriptor> valueParameters = resultingDescriptor.getValueParameters();
619 if (valueParameters.isEmpty()) return;
620 ValueParameterDescriptor valueParameterForThis = valueParameters.get(0);
621
622 constraintSystem.addSubtypeConstraint(typeOfThis, valueParameterForThis.getType(), ConstraintPosition.FROM_COMPLETER);
623 }
624 };
625 }
626
627 public void resolvePropertyInitializer(
628 @NotNull JetProperty property,
629 @NotNull PropertyDescriptor propertyDescriptor,
630 @NotNull JetExpression initializer,
631 @NotNull JetScope scope
632 ) {
633 JetScope propertyDeclarationInnerScope = descriptorResolver.getPropertyDeclarationInnerScopeForInitializer(
634 scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
635 JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
636 expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, context.getOuterDataFlowInfo(), trace);
637 if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) {
638 CompileTimeConstant<?> constant = annotationResolver.resolveExpressionToCompileTimeValue(initializer, expectedTypeForInitializer, trace);
639 if (constant != null) {
640 trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant);
641 }
642 }
643 }
644
645 @NotNull
646 private JetScope getScopeForProperty(@NotNull JetProperty property) {
647 JetScope scope = this.context.getDeclaringScopes().apply(property);
648 assert scope != null : "Scope for property " + property.getText() + " should exists";
649 return scope;
650 }
651
652 private void resolveFunctionBodies() {
653 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : this.context.getFunctions().entrySet()) {
654 JetNamedFunction declaration = entry.getKey();
655 SimpleFunctionDescriptor descriptor = entry.getValue();
656
657 computeDeferredType(descriptor.getReturnType());
658
659 JetScope declaringScope = this.context.getDeclaringScopes().apply(declaration);
660 assert declaringScope != null;
661
662 resolveAnnotationArguments(declaringScope, declaration);
663 resolveFunctionBody(trace, declaration, descriptor, declaringScope);
664
665 assert descriptor.getReturnType() != null;
666 }
667 }
668
669 public void resolveFunctionBody(
670 @NotNull BindingTrace trace,
671 @NotNull JetDeclarationWithBody function,
672 @NotNull FunctionDescriptor functionDescriptor,
673 @NotNull JetScope declaringScope) {
674 if (!context.completeAnalysisNeeded(function)) return;
675
676 JetExpression bodyExpression = function.getBodyExpression();
677 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
678 if (bodyExpression != null) {
679 expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.getOuterDataFlowInfo(), null, trace);
680 }
681
682 List<JetParameter> valueParameters = function.getValueParameters();
683 List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
684
685 resolveValueParameter(valueParameters, valueParameterDescriptors, functionInnerScope);
686
687 assert functionDescriptor.getReturnType() != null;
688 }
689
690 private void resolveValueParameter(
691 @NotNull List<JetParameter> valueParameters,
692 @NotNull List<ValueParameterDescriptor> valueParameterDescriptors,
693 @NotNull JetScope declaringScope
694 ) {
695 for (int i = 0; i < valueParameters.size(); i++) {
696 ValueParameterDescriptor valueParameterDescriptor = valueParameterDescriptors.get(i);
697 JetParameter jetParameter = valueParameters.get(i);
698
699 resolveAnnotationArguments(declaringScope, jetParameter);
700
701 resolveDefaultValue(declaringScope, valueParameterDescriptor, jetParameter);
702 }
703 }
704
705 private void resolveDefaultValue(
706 @NotNull JetScope declaringScope,
707 @NotNull ValueParameterDescriptor valueParameterDescriptor,
708 @NotNull JetParameter jetParameter
709 ) {
710 if (valueParameterDescriptor.hasDefaultValue()) {
711 JetExpression defaultValue = jetParameter.getDefaultValue();
712 if (defaultValue != null) {
713 expressionTypingServices.getType(declaringScope, defaultValue, valueParameterDescriptor.getType(), context.getOuterDataFlowInfo(), trace);
714 if (DescriptorUtils.isAnnotationClass(DescriptorUtils.getContainingClass(declaringScope))) {
715 CompileTimeConstant<?> constant =
716 annotationResolver.resolveExpressionToCompileTimeValue(defaultValue, valueParameterDescriptor.getType(), trace);
717 if (constant != null) {
718 trace.record(BindingContext.COMPILE_TIME_VALUE, defaultValue, constant);
719 }
720 }
721 }
722 }
723 }
724
725 private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
726 annotationResolver.resolveAnnotationsArguments(scope, owner.getModifierList(), trace);
727 }
728
729 private static void computeDeferredType(JetType type) {
730 // handle type inference loop: function or property body contains a reference to itself
731 // fun f() = { f() }
732 // val x = x
733 // type resolution must be started before body resolution
734 if (type instanceof DeferredType) {
735 DeferredType deferredType = (DeferredType) type;
736 if (!deferredType.isComputed()) {
737 deferredType.getActualType();
738 }
739 }
740 }
741
742 private void computeDeferredTypes() {
743 Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
744 if (deferredTypes != null) {
745 // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
746 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
747 trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
748 @Override
749 public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
750 queue.addLast(key.getData());
751 }
752 });
753 for (Box<DeferredType> deferredType : deferredTypes) {
754 queue.addLast(deferredType.getData());
755 }
756 while (!queue.isEmpty()) {
757 DeferredType deferredType = queue.pullFirst();
758 if (!deferredType.isComputed()) {
759 try {
760 deferredType.getActualType(); // to compute
761 }
762 catch (ReenteringLazyValueComputationException e) {
763 // A problem should be reported while computing the type
764 }
765 }
766 }
767 }
768 }
769
770 }