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