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.inference.ConstraintPosition;
030 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
031 import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemCompleter;
032 import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
033 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
034 import org.jetbrains.jet.lang.resolve.calls.CallResolver;
035 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
036 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
037 import org.jetbrains.jet.lang.resolve.scopes.*;
038 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
039 import org.jetbrains.jet.lang.types.*;
040 import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
041 import org.jetbrains.jet.lang.types.expressions.DelegatedPropertyUtils;
042 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
043 import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
044 import org.jetbrains.jet.lexer.JetTokens;
045 import org.jetbrains.jet.util.Box;
046 import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
047 import org.jetbrains.jet.util.slicedmap.WritableSlice;
048
049 import javax.inject.Inject;
050 import java.util.*;
051
052 import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
053 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
054 import static org.jetbrains.jet.lang.resolve.BindingContext.*;
055 import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code;
056 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
057
058 public 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 }