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