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 ModifiersChecker.reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY), trace);
383 }
384
385 private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
386 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
387 if (!(entry.getKey() instanceof JetClass)) continue;
388 JetClass klass = (JetClass) entry.getKey();
389 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
390 ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
391
392 AnnotationResolver.resolveAnnotationsArguments(klass.getPrimaryConstructorModifierList(), trace);
393
394 if (unsubstitutedPrimaryConstructor != null) {
395 WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(), unsubstitutedPrimaryConstructor);
396 expressionTypingServices.resolveValueParameters(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
397 parameterScope, c.getOuterDataFlowInfo(), trace, c.completeAnalysisNeeded(klass));
398 }
399 }
400 }
401
402 private static WritableScope getPrimaryConstructorParametersScope(
403 JetScope originalScope,
404 ConstructorDescriptor unsubstitutedPrimaryConstructor
405 ) {
406 WritableScope parameterScope = new WritableScopeImpl(
407 originalScope,
408 unsubstitutedPrimaryConstructor,
409 RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor"
410 );
411 for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
412 parameterScope.addVariableDescriptor(valueParameterDescriptor);
413 }
414 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
415 return parameterScope;
416 }
417
418 private void resolvePropertyDeclarationBodies(@NotNull BodiesResolveContext c) {
419
420 // Member properties
421 Set<JetProperty> processed = Sets.newHashSet();
422 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
423 if (!(entry.getKey() instanceof JetClass)) continue;
424 JetClass jetClass = (JetClass) entry.getKey();
425 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
426
427 for (JetProperty property : jetClass.getProperties()) {
428 PropertyDescriptor propertyDescriptor = c.getProperties().get(property);
429 assert propertyDescriptor != null;
430
431 computeDeferredType(propertyDescriptor.getReturnType());
432
433 JetExpression initializer = property.getInitializer();
434 JetScope propertyScope = getScopeForProperty(c, property);
435 if (initializer != null) {
436 ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
437 if (primaryConstructor != null) {
438 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
439 }
440 }
441
442 JetExpression delegateExpression = property.getDelegateExpression();
443 if (delegateExpression != null) {
444 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
445 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberDeclarationResolution(), propertyScope);
446 }
447
448 resolveAnnotationArguments(propertyScope, property);
449
450 resolvePropertyAccessors(c, property, propertyDescriptor);
451 processed.add(property);
452 }
453 }
454
455 // Top-level properties & properties of objects
456 for (Map.Entry<JetProperty, PropertyDescriptor> entry : c.getProperties().entrySet()) {
457 JetProperty property = entry.getKey();
458 if (processed.contains(property)) continue;
459
460 PropertyDescriptor propertyDescriptor = entry.getValue();
461
462 computeDeferredType(propertyDescriptor.getReturnType());
463
464 JetExpression initializer = property.getInitializer();
465 JetScope propertyScope = getScopeForProperty(c, property);
466 if (initializer != null) {
467 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
468 }
469
470 JetExpression delegateExpression = property.getDelegateExpression();
471 if (delegateExpression != null) {
472 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
473 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
474 }
475
476 resolveAnnotationArguments(propertyScope, property);
477
478 resolvePropertyAccessors(c, property, propertyDescriptor);
479 }
480 }
481
482 private JetScope makeScopeForPropertyAccessor(@NotNull BodiesResolveContext c, @NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
483 JetScope accessorDeclaringScope = c.getDeclaringScopes().apply(accessor);
484 assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
485 return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, trace);
486 }
487
488 public void resolvePropertyAccessors(
489 @NotNull BodiesResolveContext c,
490 @NotNull JetProperty property,
491 @NotNull PropertyDescriptor propertyDescriptor
492 ) {
493 ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
494
495 JetPropertyAccessor getter = property.getGetter();
496 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
497 if (getter != null && getterDescriptor != null) {
498 JetScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
499 resolveAnnotationArguments(accessorScope, getter);
500 resolveFunctionBody(c, fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
501 }
502
503 JetPropertyAccessor setter = property.getSetter();
504 PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
505 if (setter != null && setterDescriptor != null) {
506 JetScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
507 resolveAnnotationArguments(accessorScope, setter);
508 resolveFunctionBody(c, fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
509 }
510 }
511
512 private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
513 return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
514 @Override
515 public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
516 if (expression instanceof JetSimpleNameExpression) {
517 JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
518 if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
519 // This check may be considered redundant as long as $x is only accessible from accessors to $x
520 if (descriptor == propertyDescriptor) { // TODO : original?
521 trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
522 }
523 }
524 }
525 }
526 });
527 }
528
529 public void resolvePropertyDelegate(
530 @NotNull BodiesResolveContext c,
531 @NotNull JetProperty jetProperty,
532 @NotNull PropertyDescriptor propertyDescriptor,
533 @NotNull JetExpression delegateExpression,
534 @NotNull JetScope parentScopeForAccessor,
535 @NotNull JetScope propertyScope
536 ) {
537 JetPropertyAccessor getter = jetProperty.getGetter();
538 if (getter != null) {
539 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
540 }
541
542 JetPropertyAccessor setter = jetProperty.getSetter();
543 if (setter != null) {
544 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
545 }
546
547 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
548 propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
549 JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
550 propertyDescriptor, parentScopeForAccessor, trace);
551
552 JetType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
553 delegateExpression, jetProperty, propertyDescriptor, propertyDeclarationInnerScope, accessorScope, trace,
554 c.getOuterDataFlowInfo());
555
556 delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
557 trace, accessorScope);
558
559 if (jetProperty.isVar()) {
560 delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
561 trace, accessorScope);
562 }
563 }
564
565 public void resolvePropertyInitializer(
566 @NotNull BodiesResolveContext c,
567 @NotNull JetProperty property,
568 @NotNull PropertyDescriptor propertyDescriptor,
569 @NotNull JetExpression initializer,
570 @NotNull JetScope scope
571 ) {
572 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
573 scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
574 JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
575 CompileTimeConstant<?> compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer();
576 if (compileTimeInitializer == null) {
577 expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace);
578 }
579 }
580
581 @NotNull
582 private JetScope getScopeForProperty(@NotNull BodiesResolveContext c, @NotNull JetProperty property) {
583 JetScope scope = c.getDeclaringScopes().apply(property);
584 assert scope != null : "Scope for property " + property.getText() + " should exists";
585 return scope;
586 }
587
588 private void resolveFunctionBodies(@NotNull BodiesResolveContext c) {
589 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : c.getFunctions().entrySet()) {
590 JetNamedFunction declaration = entry.getKey();
591 SimpleFunctionDescriptor descriptor = entry.getValue();
592
593 computeDeferredType(descriptor.getReturnType());
594
595 JetScope declaringScope = c.getDeclaringScopes().apply(declaration);
596 assert declaringScope != null;
597
598 if (!c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
599 resolveAnnotationArguments(declaringScope, declaration);
600 }
601 resolveFunctionBody(c, trace, declaration, descriptor, declaringScope);
602
603 assert descriptor.getReturnType() != null;
604 }
605 }
606
607 public void resolveFunctionBody(
608 @NotNull BodiesResolveContext c,
609 @NotNull BindingTrace trace,
610 @NotNull JetDeclarationWithBody function,
611 @NotNull FunctionDescriptor functionDescriptor,
612 @NotNull JetScope declaringScope
613 ) {
614 JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
615
616 List<JetParameter> valueParameters = function.getValueParameters();
617 List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
618
619 boolean needCompleteAnalysis = c.completeAnalysisNeeded(function);
620
621 expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, functionInnerScope,
622 c.getOuterDataFlowInfo(), trace, needCompleteAnalysis);
623
624 if (!needCompleteAnalysis) return;
625
626 if (function.hasBody()) {
627 expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, c.getOuterDataFlowInfo(), null, trace);
628 }
629
630 assert functionDescriptor.getReturnType() != null;
631 }
632
633 public void resolveConstructorParameterDefaultValuesAndAnnotations(
634 @NotNull BodiesResolveContext c,
635 @NotNull BindingTrace trace,
636 @NotNull JetClass klass,
637 @NotNull ConstructorDescriptor constructorDescriptor,
638 @NotNull JetScope declaringScope
639 ) {
640 if (!c.completeAnalysisNeeded(klass)) return;
641
642 List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters();
643 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
644
645 JetScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor);
646
647 expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, scope,
648 c.getOuterDataFlowInfo(), trace, /* needCompleteAnalysis = */ true);
649 }
650
651 private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
652 AnnotationResolver.resolveAnnotationsArguments(owner.getModifierList(), trace);
653 }
654
655 private static void computeDeferredType(JetType type) {
656 // handle type inference loop: function or property body contains a reference to itself
657 // fun f() = { f() }
658 // val x = x
659 // type resolution must be started before body resolution
660 if (type instanceof DeferredType) {
661 DeferredType deferredType = (DeferredType) type;
662 if (!deferredType.isComputed()) {
663 deferredType.getDelegate();
664 }
665 }
666 }
667
668 private void computeDeferredTypes() {
669 Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
670 if (deferredTypes != null) {
671 // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
672 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
673 trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
674 @Override
675 public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
676 queue.addLast(key.getData());
677 }
678 });
679 for (Box<DeferredType> deferredType : deferredTypes) {
680 queue.addLast(deferredType.getData());
681 }
682 while (!queue.isEmpty()) {
683 DeferredType deferredType = queue.pullFirst();
684 if (!deferredType.isComputed()) {
685 try {
686 deferredType.getDelegate(); // to compute
687 }
688 catch (ReenteringLazyValueComputationException e) {
689 // A problem should be reported while computing the type
690 }
691 }
692 }
693 }
694 }
695
696 }