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