001 /*
002 * Copyright 2010-2015 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.kotlin.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 kotlin.jvm.functions.Function1;
024 import org.jetbrains.annotations.NotNull;
025 import org.jetbrains.annotations.Nullable;
026 import org.jetbrains.kotlin.descriptors.*;
027 import org.jetbrains.kotlin.lexer.JetTokens;
028 import org.jetbrains.kotlin.psi.*;
029 import org.jetbrains.kotlin.resolve.calls.CallResolver;
030 import org.jetbrains.kotlin.resolve.calls.checkers.CallChecker;
031 import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
032 import org.jetbrains.kotlin.resolve.calls.results.OverloadResolutionResults;
033 import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
034 import org.jetbrains.kotlin.resolve.calls.util.CallMaker;
035 import org.jetbrains.kotlin.resolve.constants.CompileTimeConstant;
036 import org.jetbrains.kotlin.resolve.scopes.*;
037 import org.jetbrains.kotlin.resolve.scopes.receivers.ReceiverValue;
038 import org.jetbrains.kotlin.types.*;
039 import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
040 import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
041 import org.jetbrains.kotlin.types.expressions.ValueParameterResolver;
042 import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryPackage;
043 import org.jetbrains.kotlin.util.Box;
044 import org.jetbrains.kotlin.util.ReenteringLazyValueComputationException;
045 import org.jetbrains.kotlin.util.slicedMap.WritableSlice;
046
047 import javax.inject.Inject;
048 import java.util.*;
049
050 import static org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
051 import static org.jetbrains.kotlin.diagnostics.Errors.*;
052 import static org.jetbrains.kotlin.resolve.BindingContext.*;
053 import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
054
055 public class BodyResolver {
056 private ScriptBodyResolver scriptBodyResolverResolver;
057 private ExpressionTypingServices expressionTypingServices;
058 private CallResolver callResolver;
059 private ObservableBindingTrace trace;
060 private ControlFlowAnalyzer controlFlowAnalyzer;
061 private DeclarationsChecker declarationsChecker;
062 private AnnotationResolver annotationResolver;
063 private DelegatedPropertyResolver delegatedPropertyResolver;
064 private FunctionAnalyzerExtension functionAnalyzerExtension;
065 private AdditionalCheckerProvider additionalCheckerProvider;
066 private ValueParameterResolver valueParameterResolver;
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 @Inject
114 public void setAdditionalCheckerProvider(AdditionalCheckerProvider additionalCheckerProvider) {
115 this.additionalCheckerProvider = additionalCheckerProvider;
116 }
117
118 @Inject
119 public void setValueParameterResolver(ValueParameterResolver valueParameterResolver) {
120 this.valueParameterResolver = valueParameterResolver;
121 }
122
123 private void resolveBehaviorDeclarationBodies(@NotNull BodiesResolveContext c) {
124 resolveDelegationSpecifierLists(c);
125
126 resolvePropertyDeclarationBodies(c);
127
128 resolveAnonymousInitializers(c);
129 resolvePrimaryConstructorParameters(c);
130 resolveSecondaryConstructors(c);
131
132 resolveFunctionBodies(c);
133
134 // SCRIPT: resolve script bodies
135 scriptBodyResolverResolver.resolveScriptBodies(c);
136
137 if (!c.getTopDownAnalysisMode().getIsLocalDeclarations()) {
138 computeDeferredTypes();
139 }
140 }
141
142 private void resolveSecondaryConstructors(@NotNull BodiesResolveContext c) {
143 for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : c.getSecondaryConstructors().entrySet()) {
144 JetScope declaringScope = c.getDeclaringScopes().apply(entry.getKey());
145 assert declaringScope != null : "Declaring scope should be registered before body resolve";
146 resolveSecondaryConstructorBody(c, trace, entry.getKey(), entry.getValue(), declaringScope);
147 }
148 if (c.getSecondaryConstructors().isEmpty()) return;
149 Set<ConstructorDescriptor> visitedConstructors = Sets.newHashSet();
150 for (Map.Entry<JetSecondaryConstructor, ConstructorDescriptor> entry : c.getSecondaryConstructors().entrySet()) {
151 checkCyclicConstructorDelegationCall(entry.getValue(), visitedConstructors);
152 }
153 }
154
155 public void resolveSecondaryConstructorBody(
156 @NotNull final BodiesResolveContext c,
157 @NotNull final BindingTrace trace,
158 @NotNull final JetSecondaryConstructor constructor,
159 @NotNull final ConstructorDescriptor descriptor,
160 @NotNull JetScope declaringScope
161 ) {
162 AnnotationResolver.resolveAnnotationsArguments(descriptor.getAnnotations());
163
164 final CallChecker callChecker = new ConstructorHeaderCallChecker(descriptor, additionalCheckerProvider.getCallChecker());
165 resolveFunctionBody(c, trace, constructor, descriptor, declaringScope,
166 new Function1<JetScope, DataFlowInfo>() {
167 @Override
168 public DataFlowInfo invoke(@NotNull JetScope headerInnerScope) {
169 return resolveSecondaryConstructorDelegationCall(c, trace, headerInnerScope, constructor, descriptor,
170 callChecker);
171 }
172 },
173 callChecker);
174 }
175
176 @Nullable
177 private DataFlowInfo resolveSecondaryConstructorDelegationCall(
178 @NotNull BodiesResolveContext c,
179 @NotNull BindingTrace trace,
180 @NotNull JetScope scope,
181 @NotNull JetSecondaryConstructor constructor,
182 @NotNull ConstructorDescriptor descriptor,
183 @NotNull CallChecker callChecker
184 ) {
185 OverloadResolutionResults<?> results = callResolver.resolveConstructorDelegationCall(
186 trace, scope, c.getOuterDataFlowInfo(),
187 descriptor, constructor.getDelegationCall(),
188 callChecker);
189
190 if (results != null && results.isSingleResult()) {
191 ResolvedCall<? extends CallableDescriptor> resolvedCall = results.getResultingCall();
192 recordConstructorDelegationCall(trace, descriptor, resolvedCall);
193 return resolvedCall.getDataFlowInfoForArguments().getResultInfo();
194 }
195 return null;
196 }
197
198 private void checkCyclicConstructorDelegationCall(
199 @NotNull ConstructorDescriptor constructorDescriptor,
200 @NotNull Set<ConstructorDescriptor> visitedConstructors
201 ) {
202 if (visitedConstructors.contains(constructorDescriptor)) return;
203
204 // if visit constructor that is already in current chain
205 // such constructor is on cycle
206 Set<ConstructorDescriptor> visitedInCurrentChain = Sets.newHashSet();
207 ConstructorDescriptor currentConstructorDescriptor = constructorDescriptor;
208 while (true) {
209 visitedInCurrentChain.add(currentConstructorDescriptor);
210 ConstructorDescriptor delegatedConstructorDescriptor = getDelegatedConstructor(currentConstructorDescriptor);
211 if (delegatedConstructorDescriptor == null) break;
212
213 // if next delegation call is super or primary constructor or already visited
214 if (!constructorDescriptor.getContainingDeclaration().equals(delegatedConstructorDescriptor.getContainingDeclaration()) ||
215 delegatedConstructorDescriptor.isPrimary() ||
216 visitedConstructors.contains(delegatedConstructorDescriptor)) {
217 break;
218 }
219
220 if (visitedInCurrentChain.contains(delegatedConstructorDescriptor)) {
221 reportEachConstructorOnCycle(delegatedConstructorDescriptor);
222 break;
223 }
224 currentConstructorDescriptor = delegatedConstructorDescriptor;
225 }
226 visitedConstructors.addAll(visitedInCurrentChain);
227 }
228
229 private void reportEachConstructorOnCycle(@NotNull ConstructorDescriptor startConstructor) {
230 ConstructorDescriptor currentConstructor = startConstructor;
231 do {
232 PsiElement constructorToReport = DescriptorToSourceUtils.descriptorToDeclaration(currentConstructor);
233 if (constructorToReport != null) {
234 JetConstructorDelegationCall call = ((JetSecondaryConstructor) constructorToReport).getDelegationCall();
235 assert call.getCalleeExpression() != null
236 : "Callee expression of delegation call should not be null on cycle as there should be explicit 'this' calls";
237 trace.report(CYCLIC_CONSTRUCTOR_DELEGATION_CALL.on(call.getCalleeExpression()));
238 }
239
240 currentConstructor = getDelegatedConstructor(currentConstructor);
241 assert currentConstructor != null : "Delegated constructor should not be null in cycle";
242 } while (startConstructor != currentConstructor);
243 }
244
245 @Nullable
246 private ConstructorDescriptor getDelegatedConstructor(@NotNull ConstructorDescriptor constructor) {
247 ResolvedCall<ConstructorDescriptor> call = trace.get(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor);
248 return call == null || !call.getStatus().isSuccess() ? null : call.getResultingDescriptor().getOriginal();
249 }
250
251 public void resolveBodies(@NotNull BodiesResolveContext c) {
252 resolveBehaviorDeclarationBodies(c);
253 controlFlowAnalyzer.process(c);
254 declarationsChecker.process(c);
255 functionAnalyzerExtension.process(c);
256 }
257
258 private void resolveDelegationSpecifierLists(@NotNull BodiesResolveContext c) {
259 // TODO : Make sure the same thing is not initialized twice
260 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
261 JetClassOrObject classOrObject = entry.getKey();
262 ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
263
264 resolveDelegationSpecifierList(c, classOrObject, descriptor,
265 descriptor.getUnsubstitutedPrimaryConstructor(),
266 descriptor.getScopeForClassHeaderResolution(),
267 descriptor.getScopeForMemberDeclarationResolution());
268 }
269 }
270
271 public void resolveDelegationSpecifierList(
272 @NotNull final BodiesResolveContext c,
273 @NotNull JetClassOrObject jetClass,
274 @NotNull final ClassDescriptor descriptor,
275 @Nullable final ConstructorDescriptor primaryConstructor,
276 @NotNull JetScope scopeForSupertypeResolution,
277 @NotNull final JetScope scopeForMemberResolution) {
278 final JetScope scopeForConstructor = primaryConstructor == null
279 ? null
280 : FunctionDescriptorUtil.getFunctionInnerScope(scopeForSupertypeResolution, primaryConstructor, trace);
281 final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow
282
283 final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
284 final ResolvedCall<?>[] primaryConstructorDelegationCall = new ResolvedCall[1];
285 JetVisitorVoid visitor = new JetVisitorVoid() {
286 private void recordSupertype(JetTypeReference typeReference, JetType supertype) {
287 if (supertype == null) return;
288 supertypes.put(typeReference, supertype);
289 }
290
291 @Override
292 public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) {
293 if (descriptor.getKind() == ClassKind.INTERFACE) {
294 trace.report(DELEGATION_IN_TRAIT.on(specifier));
295 }
296 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
297 recordSupertype(specifier.getTypeReference(), supertype);
298 if (supertype != null) {
299 DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
300 if (declarationDescriptor instanceof ClassDescriptor) {
301 ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
302 if (classDescriptor.getKind() != ClassKind.INTERFACE) {
303 trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
304 }
305 }
306 }
307 JetExpression delegateExpression = specifier.getDelegateExpression();
308 if (delegateExpression != null) {
309 JetScope scope = scopeForConstructor == null ? scopeForMemberResolution : scopeForConstructor;
310 JetType expectedType = supertype != null ? supertype : NO_EXPECTED_TYPE;
311 typeInferrer.getType(scope, delegateExpression, expectedType, c.getOuterDataFlowInfo(), trace);
312 }
313 if (primaryConstructor == null) {
314 trace.report(UNSUPPORTED.on(specifier, "Delegation without primary constructor is not supported"));
315 }
316 }
317
318 @Override
319 public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
320 JetValueArgumentList valueArgumentList = call.getValueArgumentList();
321 PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
322 if (descriptor.getKind() == ClassKind.INTERFACE) {
323 trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
324 }
325 JetTypeReference typeReference = call.getTypeReference();
326 if (typeReference == null) return;
327 if (primaryConstructor == null) {
328 if (descriptor.getKind() != ClassKind.INTERFACE) {
329 trace.report(SUPERTYPE_INITIALIZED_WITHOUT_PRIMARY_CONSTRUCTOR.on(call));
330 }
331 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
332 return;
333 }
334 OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
335 trace, scopeForConstructor,
336 CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), false);
337 if (results.isSuccess()) {
338 JetType supertype = results.getResultingDescriptor().getReturnType();
339 recordSupertype(typeReference, supertype);
340 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
341 if (classDescriptor != null) {
342 // allow only one delegating constructor
343 if (primaryConstructorDelegationCall[0] == null) {
344 primaryConstructorDelegationCall[0] = results.getResultingCall();
345 }
346 else {
347 primaryConstructorDelegationCall[0] = null;
348 }
349 }
350 // Recording type info for callee to use later in JetObjectLiteralExpression
351 trace.record(PROCESSED, call.getCalleeExpression(), true);
352 trace.record(EXPRESSION_TYPE_INFO, call.getCalleeExpression(),
353 TypeInfoFactoryPackage.noTypeInfo(results.getResultingCall().getDataFlowInfoForArguments().getResultInfo()));
354 }
355 else {
356 recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
357 }
358 }
359
360 @Override
361 public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) {
362 JetTypeReference typeReference = specifier.getTypeReference();
363 JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
364 recordSupertype(typeReference, supertype);
365 if (supertype == null) return;
366 ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype);
367 if (superClass == null) return;
368 if (superClass.getKind().isSingleton()) {
369 // A "singleton in supertype" diagnostic will be reported later
370 return;
371 }
372 if (descriptor.getKind() != ClassKind.INTERFACE &&
373 descriptor.getUnsubstitutedPrimaryConstructor() != null &&
374 superClass.getKind() != ClassKind.INTERFACE &&
375 !superClass.getConstructors().isEmpty() &&
376 !ErrorUtils.isError(superClass)
377 ) {
378 trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
379 }
380 }
381
382 @Override
383 public void visitJetElement(@NotNull JetElement element) {
384 throw new UnsupportedOperationException(element.getText() + " : " + element);
385 }
386 };
387
388 for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
389 delegationSpecifier.accept(visitor);
390 }
391
392 if (DescriptorUtils.isAnnotationClass(descriptor) && jetClass.getDelegationSpecifierList() != null) {
393 trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(jetClass.getDelegationSpecifierList()));
394 }
395
396 Set<TypeConstructor> parentEnum =
397 jetClass instanceof JetEnumEntry
398 ? Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor())
399 : Collections.<TypeConstructor>emptySet();
400
401 if (primaryConstructorDelegationCall[0] != null && primaryConstructor != null) {
402 recordConstructorDelegationCall(trace, primaryConstructor, primaryConstructorDelegationCall[0]);
403 }
404 checkSupertypeList(descriptor, supertypes, parentEnum);
405 }
406
407 private static void recordConstructorDelegationCall(
408 @NotNull BindingTrace trace,
409 @NotNull ConstructorDescriptor constructor,
410 @NotNull ResolvedCall<?> call
411 ) {
412 //noinspection unchecked
413 trace.record(CONSTRUCTOR_RESOLVED_DELEGATION_CALL, constructor, (ResolvedCall<ConstructorDescriptor>) call);
414 }
415
416 // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
417 private void checkSupertypeList(
418 @NotNull ClassDescriptor supertypeOwner,
419 @NotNull Map<JetTypeReference, JetType> supertypes,
420 @NotNull Set<TypeConstructor> allowedFinalSupertypes
421 ) {
422 Set<TypeConstructor> typeConstructors = Sets.newHashSet();
423 boolean classAppeared = false;
424 for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
425 JetTypeReference typeReference = entry.getKey();
426 JetType supertype = entry.getValue();
427
428 ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
429 if (classDescriptor != null) {
430 if (ErrorUtils.isError(classDescriptor)) continue;
431
432 if (classDescriptor.getKind() != ClassKind.INTERFACE) {
433 if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
434 trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
435 }
436 else if (supertypeOwner.getKind() == ClassKind.INTERFACE &&
437 !classAppeared && !TypesPackage.isDynamic(supertype) /* avoid duplicate diagnostics */) {
438 trace.report(TRAIT_WITH_SUPERCLASS.on(typeReference));
439 }
440 if (classAppeared) {
441 trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
442 }
443 else {
444 classAppeared = true;
445 }
446 }
447 }
448 else {
449 trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
450 }
451
452 TypeConstructor constructor = supertype.getConstructor();
453 if (!typeConstructors.add(constructor)) {
454 trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
455 }
456
457 if (DescriptorUtils.isSingleton(classDescriptor)) {
458 trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference));
459 }
460 else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) {
461 trace.report(FINAL_SUPERTYPE.on(typeReference));
462 }
463 }
464 }
465
466 private void resolveAnonymousInitializers(@NotNull BodiesResolveContext c) {
467 for (Map.Entry<JetClassInitializer, ClassDescriptorWithResolutionScopes> entry : c.getAnonymousInitializers().entrySet()) {
468 JetClassInitializer initializer = entry.getKey();
469 ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
470 resolveAnonymousInitializer(c, initializer, descriptor);
471 }
472 }
473
474 public void resolveAnonymousInitializer(
475 @NotNull BodiesResolveContext c,
476 @NotNull JetClassInitializer anonymousInitializer,
477 @NotNull ClassDescriptorWithResolutionScopes classDescriptor
478 ) {
479 JetScope scopeForInitializers = classDescriptor.getScopeForInitializerResolution();
480 if (!classDescriptor.getConstructors().isEmpty()) {
481 JetExpression body = anonymousInitializer.getBody();
482 if (body != null) {
483 expressionTypingServices.getType(scopeForInitializers, body, NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), trace);
484 }
485 processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
486 }
487 else {
488 trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer));
489 processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
490 }
491 }
492
493 private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) {
494 JetModifierList modifierList = owner.getModifierList();
495 if (modifierList == null) return;
496
497 annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
498
499 ModifiersChecker.reportIllegalModifiers(modifierList, Arrays.asList(JetTokens.MODIFIER_KEYWORDS_ARRAY), trace);
500 }
501
502 private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
503 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
504 JetClassOrObject klass = entry.getKey();
505 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
506 ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
507 if (unsubstitutedPrimaryConstructor != null) {
508 AnnotationResolver.resolveAnnotationsArguments(unsubstitutedPrimaryConstructor.getAnnotations());
509
510 WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(),
511 unsubstitutedPrimaryConstructor);
512 valueParameterResolver.resolveValueParameters(klass.getPrimaryConstructorParameters(),
513 unsubstitutedPrimaryConstructor.getValueParameters(),
514 parameterScope, c.getOuterDataFlowInfo(), trace);
515 }
516 }
517 }
518
519 private static WritableScope getPrimaryConstructorParametersScope(
520 JetScope originalScope,
521 ConstructorDescriptor unsubstitutedPrimaryConstructor
522 ) {
523 WritableScope parameterScope = new WritableScopeImpl(
524 originalScope,
525 unsubstitutedPrimaryConstructor,
526 RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor"
527 );
528 for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
529 parameterScope.addVariableDescriptor(valueParameterDescriptor);
530 }
531 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
532 return parameterScope;
533 }
534
535 private void resolvePropertyDeclarationBodies(@NotNull BodiesResolveContext c) {
536
537 // Member properties
538 Set<JetProperty> processed = Sets.newHashSet();
539 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
540 if (!(entry.getKey() instanceof JetClass)) continue;
541 JetClass jetClass = (JetClass) entry.getKey();
542 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
543
544 for (JetProperty property : jetClass.getProperties()) {
545 PropertyDescriptor propertyDescriptor = c.getProperties().get(property);
546 assert propertyDescriptor != null;
547
548 computeDeferredType(propertyDescriptor.getReturnType());
549
550 JetExpression initializer = property.getInitializer();
551 JetScope propertyScope = getScopeForProperty(c, property);
552 if (initializer != null) {
553 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
554 }
555
556 JetExpression delegateExpression = property.getDelegateExpression();
557 if (delegateExpression != null) {
558 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
559 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberDeclarationResolution(), propertyScope);
560 }
561
562 AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations());
563
564 resolvePropertyAccessors(c, property, propertyDescriptor);
565 processed.add(property);
566 }
567 }
568
569 // Top-level properties & properties of objects
570 for (Map.Entry<JetProperty, PropertyDescriptor> entry : c.getProperties().entrySet()) {
571 JetProperty property = entry.getKey();
572 if (processed.contains(property)) continue;
573
574 PropertyDescriptor propertyDescriptor = entry.getValue();
575
576 computeDeferredType(propertyDescriptor.getReturnType());
577
578 JetExpression initializer = property.getInitializer();
579 JetScope propertyScope = getScopeForProperty(c, property);
580 if (initializer != null) {
581 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
582 }
583
584 JetExpression delegateExpression = property.getDelegateExpression();
585 if (delegateExpression != null) {
586 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
587 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
588 }
589
590 AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations());
591
592 resolvePropertyAccessors(c, property, propertyDescriptor);
593 }
594 }
595
596 private JetScope makeScopeForPropertyAccessor(@NotNull BodiesResolveContext c, @NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
597 JetScope accessorDeclaringScope = c.getDeclaringScopes().apply(accessor);
598 assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
599 return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, trace);
600 }
601
602 public void resolvePropertyAccessors(
603 @NotNull BodiesResolveContext c,
604 @NotNull JetProperty property,
605 @NotNull PropertyDescriptor propertyDescriptor
606 ) {
607 ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
608
609 JetPropertyAccessor getter = property.getGetter();
610 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
611 if (getter != null && getterDescriptor != null) {
612 JetScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
613 AnnotationResolver.resolveAnnotationsArguments(getterDescriptor.getAnnotations());
614 resolveFunctionBody(c, fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
615 }
616
617 JetPropertyAccessor setter = property.getSetter();
618 PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
619 if (setter != null && setterDescriptor != null) {
620 JetScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
621 AnnotationResolver.resolveAnnotationsArguments(setterDescriptor.getAnnotations());
622 resolveFunctionBody(c, fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
623 }
624 }
625
626 private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
627 return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
628 @Override
629 public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
630 if (expression instanceof JetSimpleNameExpression) {
631 JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
632 if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
633 // This check may be considered redundant as long as $x is only accessible from accessors to $x
634 if (descriptor == propertyDescriptor) { // TODO : original?
635 trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
636 }
637 }
638 }
639 }
640 });
641 }
642
643 public void resolvePropertyDelegate(
644 @NotNull BodiesResolveContext c,
645 @NotNull JetProperty jetProperty,
646 @NotNull PropertyDescriptor propertyDescriptor,
647 @NotNull JetExpression delegateExpression,
648 @NotNull JetScope parentScopeForAccessor,
649 @NotNull JetScope propertyScope
650 ) {
651 JetPropertyAccessor getter = jetProperty.getGetter();
652 if (getter != null && getter.hasBody()) {
653 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
654 }
655
656 JetPropertyAccessor setter = jetProperty.getSetter();
657 if (setter != null && setter.hasBody()) {
658 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
659 }
660
661 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
662 propertyDescriptor, propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
663 JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
664 propertyDescriptor, parentScopeForAccessor, trace);
665
666 JetType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
667 delegateExpression, jetProperty, propertyDescriptor, propertyDeclarationInnerScope, accessorScope, trace,
668 c.getOuterDataFlowInfo());
669
670 delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
671 trace, accessorScope);
672
673 if (jetProperty.isVar()) {
674 delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
675 trace, accessorScope);
676 }
677
678 delegatedPropertyResolver.resolveDelegatedPropertyPDMethod(propertyDescriptor, delegateExpression, delegateType,
679 trace, accessorScope);
680 }
681
682 public void resolvePropertyInitializer(
683 @NotNull BodiesResolveContext c,
684 @NotNull JetProperty property,
685 @NotNull PropertyDescriptor propertyDescriptor,
686 @NotNull JetExpression initializer,
687 @NotNull JetScope scope
688 ) {
689 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
690 propertyDescriptor, scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
691 JetType expectedTypeForInitializer = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
692 CompileTimeConstant<?> compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer();
693 if (compileTimeInitializer == null) {
694 expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer,
695 c.getOuterDataFlowInfo(), trace);
696 }
697 }
698
699 @NotNull
700 private JetScope getScopeForProperty(@NotNull BodiesResolveContext c, @NotNull JetProperty property) {
701 JetScope scope = c.getDeclaringScopes().apply(property);
702 assert scope != null : "Scope for property " + property.getText() + " should exists";
703 return scope;
704 }
705
706 private void resolveFunctionBodies(@NotNull BodiesResolveContext c) {
707 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : c.getFunctions().entrySet()) {
708 JetNamedFunction declaration = entry.getKey();
709 SimpleFunctionDescriptor descriptor = entry.getValue();
710
711 computeDeferredType(descriptor.getReturnType());
712
713 JetScope declaringScope = c.getDeclaringScopes().apply(declaration);
714 assert declaringScope != null;
715
716 resolveFunctionBody(c, trace, declaration, descriptor, declaringScope);
717
718 assert descriptor.getReturnType() != null;
719 }
720 }
721
722 public void resolveFunctionBody(
723 @NotNull BodiesResolveContext c,
724 @NotNull BindingTrace trace,
725 @NotNull JetDeclarationWithBody function,
726 @NotNull FunctionDescriptor functionDescriptor,
727 @NotNull JetScope declaringScope
728 ) {
729 resolveFunctionBody(c, trace, function, functionDescriptor, declaringScope, null, null);
730 }
731
732 public void resolveFunctionBody(
733 @NotNull BodiesResolveContext c,
734 @NotNull BindingTrace trace,
735 @NotNull JetDeclarationWithBody function,
736 @NotNull FunctionDescriptor functionDescriptor,
737 @NotNull JetScope scope,
738 @Nullable Function1<JetScope, DataFlowInfo> beforeBlockBody,
739 @Nullable CallChecker callChecker
740 ) {
741 JetScope innerScope = FunctionDescriptorUtil.getFunctionInnerScope(scope, functionDescriptor, trace);
742 List<JetParameter> valueParameters = function.getValueParameters();
743 List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
744
745 valueParameterResolver.resolveValueParameters(
746 valueParameters, valueParameterDescriptors,
747 ExpressionTypingContext.newContext(
748 additionalCheckerProvider, trace, innerScope, c.getOuterDataFlowInfo(), NO_EXPECTED_TYPE, callChecker)
749 );
750
751 DataFlowInfo dataFlowInfo = null;
752
753 if (beforeBlockBody != null) {
754 dataFlowInfo = beforeBlockBody.invoke(innerScope);
755 }
756
757 if (function.hasBody()) {
758 expressionTypingServices.checkFunctionReturnType(
759 innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : c.getOuterDataFlowInfo(), null, trace);
760 }
761
762 assert functionDescriptor.getReturnType() != null;
763 }
764
765 public void resolveConstructorParameterDefaultValuesAndAnnotations(
766 @NotNull BodiesResolveContext c,
767 @NotNull BindingTrace trace,
768 @NotNull JetClass klass,
769 @NotNull ConstructorDescriptor constructorDescriptor,
770 @NotNull JetScope declaringScope
771 ) {
772 List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters();
773 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
774
775 JetScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor);
776
777 valueParameterResolver.resolveValueParameters(valueParameters, valueParameterDescriptors, scope,
778 c.getOuterDataFlowInfo(), trace);
779 }
780
781 private static void computeDeferredType(JetType type) {
782 // handle type inference loop: function or property body contains a reference to itself
783 // fun f() = { f() }
784 // val x = x
785 // type resolution must be started before body resolution
786 if (type instanceof DeferredType) {
787 DeferredType deferredType = (DeferredType) type;
788 if (!deferredType.isComputed()) {
789 deferredType.getDelegate();
790 }
791 }
792 }
793
794 private void computeDeferredTypes() {
795 Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
796 if (deferredTypes != null) {
797 // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
798 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
799 trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
800 @Override
801 public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
802 queue.addLast(key.getData());
803 }
804 });
805 for (Box<DeferredType> deferredType : deferredTypes) {
806 queue.addLast(deferredType.getData());
807 }
808 while (!queue.isEmpty()) {
809 DeferredType deferredType = queue.pullFirst();
810 if (!deferredType.isComputed()) {
811 try {
812 deferredType.getDelegate(); // to compute
813 }
814 catch (ReenteringLazyValueComputationException e) {
815 // A problem should be reported while computing the type
816 }
817 }
818 }
819 }
820 }
821
822 }