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