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