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