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