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