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