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.MutableClassDescriptor;
027 import org.jetbrains.jet.lang.psi.*;
028 import org.jetbrains.jet.lang.resolve.calls.CallResolver;
029 import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
030 import org.jetbrains.jet.lang.resolve.calls.context.ResolutionResultsCacheImpl;
031 import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
032 import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
033 import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
034 import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
035 import org.jetbrains.jet.lang.resolve.scopes.*;
036 import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
037 import org.jetbrains.jet.lang.types.*;
038 import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
039 import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
040 import org.jetbrains.jet.lang.types.expressions.LabelResolver;
041 import org.jetbrains.jet.lexer.JetTokens;
042 import org.jetbrains.jet.util.Box;
043 import org.jetbrains.jet.util.ReenteringLazyValueComputationException;
044 import org.jetbrains.jet.util.slicedmap.WritableSlice;
045
046 import javax.inject.Inject;
047 import java.util.*;
048
049 import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
050 import static org.jetbrains.jet.lang.diagnostics.Errors.*;
051 import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
052 import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
053
054 public class BodyResolver {
055 @NotNull
056 private BodiesResolveContext context;
057 @NotNull
058 private TopDownAnalysisParameters topDownAnalysisParameters;
059 @NotNull
060 private ScriptBodyResolver scriptBodyResolverResolver;
061 @NotNull
062 private ExpressionTypingServices expressionTypingServices;
063 @NotNull
064 private CallResolver callResolver;
065 @NotNull
066 private ObservableBindingTrace trace;
067 @NotNull
068 private ControlFlowAnalyzer controlFlowAnalyzer;
069 @NotNull
070 private DeclarationsChecker declarationsChecker;
071 @NotNull
072 private AnnotationResolver annotationResolver;
073 @NotNull
074 private DelegatedPropertyResolver delegatedPropertyResolver;
075 @NotNull
076 private FunctionAnalyzerExtension functionAnalyzerExtension;
077
078 @Inject
079 public void setTopDownAnalysisParameters(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
080 this.topDownAnalysisParameters = topDownAnalysisParameters;
081 }
082
083 @Inject
084 public void setScriptBodyResolverResolver(@NotNull ScriptBodyResolver scriptBodyResolverResolver) {
085 this.scriptBodyResolverResolver = scriptBodyResolverResolver;
086 }
087
088 @Inject
089 public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
090 this.expressionTypingServices = expressionTypingServices;
091 }
092
093 @Inject
094 public void setCallResolver(@NotNull CallResolver callResolver) {
095 this.callResolver = callResolver;
096 }
097
098 @Inject
099 public void setTrace(@NotNull BindingTrace trace) {
100 this.trace = new ObservableBindingTrace(trace);
101 }
102
103 @Inject
104 public void setControlFlowAnalyzer(@NotNull ControlFlowAnalyzer controlFlowAnalyzer) {
105 this.controlFlowAnalyzer = controlFlowAnalyzer;
106 }
107
108 @Inject
109 public void setDeclarationsChecker(@NotNull DeclarationsChecker declarationsChecker) {
110 this.declarationsChecker = declarationsChecker;
111 }
112
113 @Inject
114 public void setContext(@NotNull BodiesResolveContext context) {
115 this.context = context;
116 }
117
118 @Inject
119 public void setAnnotationResolver(@NotNull AnnotationResolver annotationResolver) {
120 this.annotationResolver = annotationResolver;
121 }
122
123 @Inject
124 public void setDelegatedPropertyResolver(@NotNull DelegatedPropertyResolver delegatedPropertyResolver) {
125 this.delegatedPropertyResolver = delegatedPropertyResolver;
126 }
127
128 @Inject
129 public void setFunctionAnalyzerExtension(@NotNull FunctionAnalyzerExtension functionAnalyzerExtension) {
130 this.functionAnalyzerExtension = functionAnalyzerExtension;
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 functionAnalyzerExtension.process(context);
158 }
159
160 private void resolveDelegationSpecifierLists() {
161 // TODO : Make sure the same thing is not initialized twice
162 for (Map.Entry<JetClassOrObject, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
163 JetClassOrObject classOrObject = entry.getKey();
164 MutableClassDescriptor descriptor = entry.getValue();
165 resolveDelegationSpecifierList(classOrObject, descriptor,
166 descriptor.getUnsubstitutedPrimaryConstructor(),
167 descriptor.getScopeForSupertypeResolution(),
168 descriptor.getScopeForMemberResolution());
169 }
170 }
171
172 public void resolveDelegationSpecifierList(@NotNull JetClassOrObject jetClass, @NotNull final ClassDescriptor descriptor,
173 @Nullable final ConstructorDescriptor primaryConstructor,
174 @NotNull JetScope scopeForSupertypeResolution,
175 @NotNull final JetScope scopeForMemberResolution) {
176 if (!context.completeAnalysisNeeded(jetClass)) return;
177 final JetScope scopeForConstructor = primaryConstructor == null
178 ? null
179 : FunctionDescriptorUtil.getFunctionInnerScope(scopeForSupertypeResolution, primaryConstructor, trace);
180 final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow
181
182 final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
183 JetVisitorVoid visitor = new JetVisitorVoid() {
184 private void recordSupertype(JetTypeReference typeReference, JetType supertype) {
185 if (supertype == null) return;
186 supertypes.put(typeReference, supertype);
187 }
188
189 @Override
190 public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) {
191 if (descriptor.getKind() == ClassKind.TRAIT) {
192 trace.report(DELEGATION_IN_TRAIT.on(specifier));
193 }
194 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
195 recordSupertype(specifier.getTypeReference(), supertype);
196 if (supertype != null) {
197 DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
198 if (declarationDescriptor instanceof ClassDescriptor) {
199 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
200 if (classDescriptor.getKind() != ClassKind.TRAIT) {
201 trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
202 }
203 }
204 }
205 JetExpression delegateExpression = specifier.getDelegateExpression();
206 if (delegateExpression != null) {
207 JetScope scope = scopeForConstructor == null
208 ? scopeForMemberResolution
209 : scopeForConstructor;
210 JetType type = typeInferrer.getType(scope, delegateExpression, NO_EXPECTED_TYPE, context.getOuterDataFlowInfo(), trace);
211 if (type != null && supertype != null) {
212 SimpleResolutionContext simpleResolutionContext = new SimpleResolutionContext(
213 trace, scope, supertype, context.getOuterDataFlowInfo(), ContextDependency.INDEPENDENT,
214 ResolutionResultsCacheImpl.create(), LabelResolver.create(),
215 expressionTypingServices.createExtension(scope, false), false);
216 DataFlowUtils.checkType(type, delegateExpression, simpleResolutionContext);
217 }
218 }
219 }
220
221 @Override
222 public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
223 JetValueArgumentList valueArgumentList = call.getValueArgumentList();
224 PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
225 if (descriptor.getKind() == ClassKind.TRAIT) {
226 trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
227 }
228 JetTypeReference typeReference = call.getTypeReference();
229 if (typeReference == null) return;
230 if (primaryConstructor == null) {
231 assert descriptor.getKind() == ClassKind.TRAIT;
232 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
233 return;
234 }
235 OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
236 trace, scopeForConstructor,
237 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, context.getOuterDataFlowInfo(), false);
238 if (results.isSuccess()) {
239 JetType supertype = results.getResultingDescriptor().getReturnType();
240 recordSupertype(typeReference, supertype);
241 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
242 if (classDescriptor != null) {
243 if (classDescriptor.getKind() == ClassKind.TRAIT) {
244 trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark));
245 }
246 }
247 }
248 else {
249 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
250 }
251 }
252
253 @Override
254 public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) {
255 JetTypeReference typeReference = specifier.getTypeReference();
256 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
257 recordSupertype(typeReference, supertype);
258 if (supertype == null) return;
259 ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype);
260 if (superClass == null) return;
261 if (superClass.getKind().isSingleton()) {
262 // A "singleton in supertype" diagnostic will be reported later
263 return;
264 }
265 if (descriptor.getKind() != ClassKind.TRAIT && !superClass.getConstructors().isEmpty() && !ErrorUtils.isError(superClass)) {
266 trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
267 }
268 }
269
270 @Override
271 public void visitDelegationToThisCall(@NotNull JetDelegatorToThisCall thisCall) {
272 throw new IllegalStateException("This-calls should be prohibited by the parser");
273 }
274
275 @Override
276 public void visitJetElement(@NotNull JetElement element) {
277 throw new UnsupportedOperationException(element.getText() + " : " + element);
278 }
279 };
280
281 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
282 delegationSpecifier.accept(visitor);
283 }
284
285 Set<TypeConstructor> parentEnum =
286 jetClass instanceof JetEnumEntry
287 ? Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor())
288 : Collections.<TypeConstructor>emptySet();
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 (DescriptorUtils.isSingleton(classDescriptor)) {
329 trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference));
330 }
331 else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) {
332 trace.report(FINAL_SUPERTYPE.on(typeReference));
333 }
334 }
335 }
336
337 private void resolveClassAnnotations() {
338 for (Map.Entry<JetClassOrObject, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
339 resolveAnnotationArguments(entry.getValue().getScopeForSupertypeResolution(), entry.getKey());
340 }
341 }
342
343 private void resolveAnonymousInitializers() {
344 for (Map.Entry<JetClassOrObject, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
345 JetClassOrObject classOrObject = entry.getKey();
346 MutableClassDescriptor descriptor = entry.getValue();
347 resolveAnonymousInitializers(classOrObject, descriptor.getUnsubstitutedPrimaryConstructor(),
348 descriptor.getScopeForInitializers());
349 }
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, context.getOuterDataFlowInfo(), 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<JetClassOrObject, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
373 if (!(entry.getKey() instanceof JetClass)) continue;
374 JetClass klass = (JetClass) entry.getKey();
375 MutableClassDescriptor classDescriptor = entry.getValue();
376 ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
377
378 annotationResolver.resolveAnnotationsArguments(classDescriptor.getScopeForSupertypeResolution(), klass.getPrimaryConstructorModifierList(), trace);
379
380 if (unsubstitutedPrimaryConstructor != null) {
381 WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForSupertypeResolution(), unsubstitutedPrimaryConstructor);
382 expressionTypingServices.resolveValueParameters(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
383 parameterScope, context.getOuterDataFlowInfo(), trace);
384 }
385 }
386 }
387
388 private static WritableScope getPrimaryConstructorParametersScope(
389 JetScope originalScope,
390 ConstructorDescriptor unsubstitutedPrimaryConstructor
391 ) {
392 WritableScope parameterScope = new WritableScopeImpl(
393 originalScope,
394 unsubstitutedPrimaryConstructor,
395 RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor"
396 );
397 for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
398 parameterScope.addVariableDescriptor(valueParameterDescriptor);
399 }
400 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
401 return parameterScope;
402 }
403
404 private void resolvePropertyDeclarationBodies() {
405
406 // Member properties
407 Set<JetProperty> processed = Sets.newHashSet();
408 for (Map.Entry<JetClassOrObject, MutableClassDescriptor> entry : context.getClasses().entrySet()) {
409 if (!(entry.getKey() instanceof JetClass)) continue;
410 JetClass jetClass = (JetClass) entry.getKey();
411 if (!context.completeAnalysisNeeded(jetClass)) continue;
412 MutableClassDescriptor classDescriptor = entry.getValue();
413
414 for (JetProperty property : jetClass.getProperties()) {
415 PropertyDescriptor propertyDescriptor = this.context.getProperties().get(property);
416 assert propertyDescriptor != null;
417
418 computeDeferredType(propertyDescriptor.getReturnType());
419
420 JetExpression initializer = property.getInitializer();
421 JetScope propertyScope = getScopeForProperty(property);
422 if (initializer != null) {
423 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
424 if (primaryConstructor != null) {
425 resolvePropertyInitializer(property, propertyDescriptor, initializer, propertyScope);
426 }
427 }
428
429 JetExpression delegateExpression = property.getDelegateExpression();
430 if (delegateExpression != null) {
431 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
432 resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberResolution(), propertyScope);
433 }
434
435 resolveAnnotationArguments(propertyScope, property);
436
437 resolvePropertyAccessors(property, propertyDescriptor);
438 processed.add(property);
439 }
440 }
441
442 // Top-level properties & properties of objects
443 for (Map.Entry<JetProperty, PropertyDescriptor> entry : this.context.getProperties().entrySet()) {
444 JetProperty property = entry.getKey();
445 if (!context.completeAnalysisNeeded(property)) continue;
446 if (processed.contains(property)) continue;
447
448 PropertyDescriptor propertyDescriptor = entry.getValue();
449
450 computeDeferredType(propertyDescriptor.getReturnType());
451
452 JetExpression initializer = property.getInitializer();
453 JetScope propertyScope = getScopeForProperty(property);
454 if (initializer != null) {
455 resolvePropertyInitializer(property, propertyDescriptor, initializer, propertyScope);
456 }
457
458 JetExpression delegateExpression = property.getDelegateExpression();
459 if (delegateExpression != null) {
460 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
461 resolvePropertyDelegate(property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
462 }
463
464 resolveAnnotationArguments(propertyScope, property);
465
466 resolvePropertyAccessors(property, propertyDescriptor);
467 }
468 }
469
470 private JetScope makeScopeForPropertyAccessor(@NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
471 JetScope accessorDeclaringScope = context.getDeclaringScopes().apply(accessor);
472 assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
473 return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, trace);
474 }
475
476 public void resolvePropertyAccessors(JetProperty property, PropertyDescriptor propertyDescriptor) {
477 ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
478
479 JetPropertyAccessor getter = property.getGetter();
480 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
481 if (getter != null && getterDescriptor != null) {
482 JetScope accessorScope = makeScopeForPropertyAccessor(getter, propertyDescriptor);
483 resolveAnnotationArguments(accessorScope, getter);
484 resolveFunctionBody(fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
485 }
486
487 JetPropertyAccessor setter = property.getSetter();
488 PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
489 if (setter != null && setterDescriptor != null) {
490 JetScope accessorScope = makeScopeForPropertyAccessor(setter, propertyDescriptor);
491 resolveAnnotationArguments(accessorScope, setter);
492 resolveFunctionBody(fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
493 }
494 }
495
496 private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
497 return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
498 @Override
499 public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
500 if (expression instanceof JetSimpleNameExpression) {
501 JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
502 if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
503 // This check may be considered redundant as long as $x is only accessible from accessors to $x
504 if (descriptor == propertyDescriptor) { // TODO : original?
505 trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
506 }
507 }
508 }
509 }
510 });
511 }
512
513 public void resolvePropertyDelegate(
514 @NotNull JetProperty jetProperty,
515 @NotNull PropertyDescriptor propertyDescriptor,
516 @NotNull JetExpression delegateExpression,
517 @NotNull JetScope parentScopeForAccessor,
518 @NotNull JetScope propertyScope
519 ) {
520 JetPropertyAccessor getter = jetProperty.getGetter();
521 if (getter != null) {
522 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
523 }
524
525 JetPropertyAccessor setter = jetProperty.getSetter();
526 if (setter != null) {
527 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
528 }
529
530 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
531 propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
532 JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
533 propertyDescriptor, parentScopeForAccessor, trace);
534
535 JetType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
536 delegateExpression, jetProperty, propertyDescriptor, propertyDeclarationInnerScope, accessorScope, trace,
537 context.getOuterDataFlowInfo());
538
539 delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
540 trace, accessorScope);
541
542 if (jetProperty.isVar()) {
543 delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
544 trace, accessorScope);
545 }
546 }
547
548 public void resolvePropertyInitializer(
549 @NotNull JetProperty property,
550 @NotNull PropertyDescriptor propertyDescriptor,
551 @NotNull JetExpression initializer,
552 @NotNull JetScope scope
553 ) {
554 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
555 scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
556 JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
557 expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, context.getOuterDataFlowInfo(), trace);
558 if (AnnotationUtils.isPropertyAcceptableAsAnnotationParameter(propertyDescriptor)) {
559 CompileTimeConstant<?> constant = annotationResolver.resolveExpressionToCompileTimeValue(initializer, expectedTypeForInitializer, trace);
560 if (constant != null) {
561 trace.record(BindingContext.COMPILE_TIME_INITIALIZER, propertyDescriptor, constant);
562 }
563 }
564 }
565
566 @NotNull
567 private JetScope getScopeForProperty(@NotNull JetProperty property) {
568 JetScope scope = this.context.getDeclaringScopes().apply(property);
569 assert scope != null : "Scope for property " + property.getText() + " should exists";
570 return scope;
571 }
572
573 private void resolveFunctionBodies() {
574 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : this.context.getFunctions().entrySet()) {
575 JetNamedFunction declaration = entry.getKey();
576 SimpleFunctionDescriptor descriptor = entry.getValue();
577
578 computeDeferredType(descriptor.getReturnType());
579
580 JetScope declaringScope = this.context.getDeclaringScopes().apply(declaration);
581 assert declaringScope != null;
582
583 resolveAnnotationArguments(declaringScope, declaration);
584 resolveFunctionBody(trace, declaration, descriptor, declaringScope);
585
586 assert descriptor.getReturnType() != null;
587 }
588 }
589
590 public void resolveFunctionBody(
591 @NotNull BindingTrace trace,
592 @NotNull JetDeclarationWithBody function,
593 @NotNull FunctionDescriptor functionDescriptor,
594 @NotNull JetScope declaringScope) {
595 if (!context.completeAnalysisNeeded(function)) return;
596
597 JetExpression bodyExpression = function.getBodyExpression();
598 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
599 if (bodyExpression != null) {
600 expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, context.getOuterDataFlowInfo(), null, trace);
601 }
602
603 List<JetParameter> valueParameters = function.getValueParameters();
604 List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
605
606 expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, functionInnerScope, context.getOuterDataFlowInfo(), trace);
607
608 assert functionDescriptor.getReturnType() != null;
609 }
610
611 public void resolveConstructorParameterDefaultValuesAndAnnotations(
612 @NotNull BindingTrace trace,
613 @NotNull JetClass klass,
614 @NotNull ConstructorDescriptor constructorDescriptor,
615 @NotNull JetScope declaringScope
616 ) {
617 if (!context.completeAnalysisNeeded(klass)) return;
618
619 List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters();
620 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
621
622 JetScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor);
623
624 expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, scope, context.getOuterDataFlowInfo(), trace);
625 }
626
627 private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
628 annotationResolver.resolveAnnotationsArguments(scope, owner.getModifierList(), trace);
629 }
630
631 private static void computeDeferredType(JetType type) {
632 // handle type inference loop: function or property body contains a reference to itself
633 // fun f() = { f() }
634 // val x = x
635 // type resolution must be started before body resolution
636 if (type instanceof DeferredType) {
637 DeferredType deferredType = (DeferredType) type;
638 if (!deferredType.isComputed()) {
639 deferredType.getActualType();
640 }
641 }
642 }
643
644 private void computeDeferredTypes() {
645 Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
646 if (deferredTypes != null) {
647 // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
648 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
649 trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
650 @Override
651 public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
652 queue.addLast(key.getData());
653 }
654 });
655 for (Box<DeferredType> deferredType : deferredTypes) {
656 queue.addLast(deferredType.getData());
657 }
658 while (!queue.isEmpty()) {
659 DeferredType deferredType = queue.pullFirst();
660 if (!deferredType.isComputed()) {
661 try {
662 deferredType.getActualType(); // to compute
663 }
664 catch (ReenteringLazyValueComputationException e) {
665 // A problem should be reported while computing the type
666 }
667 }
668 }
669 }
670 }
671
672 }