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(constructor.getModifierList(), trace);
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
508 AnnotationResolver.resolveAnnotationsArguments(klass.getPrimaryConstructorModifierList(), trace);
509
510 if (unsubstitutedPrimaryConstructor != null) {
511 WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(), unsubstitutedPrimaryConstructor);
512 valueParameterResolver.resolveValueParameters(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
513 parameterScope, c.getOuterDataFlowInfo(), trace);
514 }
515 }
516 }
517
518 private static WritableScope getPrimaryConstructorParametersScope(
519 JetScope originalScope,
520 ConstructorDescriptor unsubstitutedPrimaryConstructor
521 ) {
522 WritableScope parameterScope = new WritableScopeImpl(
523 originalScope,
524 unsubstitutedPrimaryConstructor,
525 RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor"
526 );
527 for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
528 parameterScope.addVariableDescriptor(valueParameterDescriptor);
529 }
530 parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
531 return parameterScope;
532 }
533
534 private void resolvePropertyDeclarationBodies(@NotNull BodiesResolveContext c) {
535
536 // Member properties
537 Set<JetProperty> processed = Sets.newHashSet();
538 for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
539 if (!(entry.getKey() instanceof JetClass)) continue;
540 JetClass jetClass = (JetClass) entry.getKey();
541 ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
542
543 for (JetProperty property : jetClass.getProperties()) {
544 PropertyDescriptor propertyDescriptor = c.getProperties().get(property);
545 assert propertyDescriptor != null;
546
547 computeDeferredType(propertyDescriptor.getReturnType());
548
549 JetExpression initializer = property.getInitializer();
550 JetScope propertyScope = getScopeForProperty(c, property);
551 if (initializer != null) {
552 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
553 }
554
555 JetExpression delegateExpression = property.getDelegateExpression();
556 if (delegateExpression != null) {
557 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
558 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberDeclarationResolution(), propertyScope);
559 }
560
561 resolveAnnotationArguments(propertyScope, property);
562
563 resolvePropertyAccessors(c, property, propertyDescriptor);
564 processed.add(property);
565 }
566 }
567
568 // Top-level properties & properties of objects
569 for (Map.Entry<JetProperty, PropertyDescriptor> entry : c.getProperties().entrySet()) {
570 JetProperty property = entry.getKey();
571 if (processed.contains(property)) continue;
572
573 PropertyDescriptor propertyDescriptor = entry.getValue();
574
575 computeDeferredType(propertyDescriptor.getReturnType());
576
577 JetExpression initializer = property.getInitializer();
578 JetScope propertyScope = getScopeForProperty(c, property);
579 if (initializer != null) {
580 resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
581 }
582
583 JetExpression delegateExpression = property.getDelegateExpression();
584 if (delegateExpression != null) {
585 assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
586 resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
587 }
588
589 resolveAnnotationArguments(propertyScope, property);
590
591 resolvePropertyAccessors(c, property, propertyDescriptor);
592 }
593 }
594
595 private JetScope makeScopeForPropertyAccessor(@NotNull BodiesResolveContext c, @NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
596 JetScope accessorDeclaringScope = c.getDeclaringScopes().apply(accessor);
597 assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
598 return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, trace);
599 }
600
601 public void resolvePropertyAccessors(
602 @NotNull BodiesResolveContext c,
603 @NotNull JetProperty property,
604 @NotNull PropertyDescriptor propertyDescriptor
605 ) {
606 ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
607
608 JetPropertyAccessor getter = property.getGetter();
609 PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
610 if (getter != null && getterDescriptor != null) {
611 JetScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
612 resolveAnnotationArguments(accessorScope, getter);
613 resolveFunctionBody(c, fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
614 }
615
616 JetPropertyAccessor setter = property.getSetter();
617 PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
618 if (setter != null && setterDescriptor != null) {
619 JetScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
620 resolveAnnotationArguments(accessorScope, setter);
621 resolveFunctionBody(c, fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
622 }
623 }
624
625 private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
626 return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
627 @Override
628 public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
629 if (expression instanceof JetSimpleNameExpression) {
630 JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
631 if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
632 // This check may be considered redundant as long as $x is only accessible from accessors to $x
633 if (descriptor == propertyDescriptor) { // TODO : original?
634 trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
635 }
636 }
637 }
638 }
639 });
640 }
641
642 public void resolvePropertyDelegate(
643 @NotNull BodiesResolveContext c,
644 @NotNull JetProperty jetProperty,
645 @NotNull PropertyDescriptor propertyDescriptor,
646 @NotNull JetExpression delegateExpression,
647 @NotNull JetScope parentScopeForAccessor,
648 @NotNull JetScope propertyScope
649 ) {
650 JetPropertyAccessor getter = jetProperty.getGetter();
651 if (getter != null && getter.hasBody()) {
652 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
653 }
654
655 JetPropertyAccessor setter = jetProperty.getSetter();
656 if (setter != null && setter.hasBody()) {
657 trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
658 }
659
660 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
661 propertyDescriptor, propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
662 JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
663 propertyDescriptor, parentScopeForAccessor, trace);
664
665 JetType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
666 delegateExpression, jetProperty, propertyDescriptor, propertyDeclarationInnerScope, accessorScope, trace,
667 c.getOuterDataFlowInfo());
668
669 delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
670 trace, accessorScope);
671
672 if (jetProperty.isVar()) {
673 delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
674 trace, accessorScope);
675 }
676
677 delegatedPropertyResolver.resolveDelegatedPropertyPDMethod(propertyDescriptor, delegateExpression, delegateType,
678 trace, accessorScope);
679 }
680
681 public void resolvePropertyInitializer(
682 @NotNull BodiesResolveContext c,
683 @NotNull JetProperty property,
684 @NotNull PropertyDescriptor propertyDescriptor,
685 @NotNull JetExpression initializer,
686 @NotNull JetScope scope
687 ) {
688 JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
689 propertyDescriptor, scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
690 JetType expectedTypeForInitializer = property.getTypeReference() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
691 CompileTimeConstant<?> compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer();
692 if (compileTimeInitializer == null) {
693 expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer,
694 c.getOuterDataFlowInfo(), trace);
695 }
696 }
697
698 @NotNull
699 private JetScope getScopeForProperty(@NotNull BodiesResolveContext c, @NotNull JetProperty property) {
700 JetScope scope = c.getDeclaringScopes().apply(property);
701 assert scope != null : "Scope for property " + property.getText() + " should exists";
702 return scope;
703 }
704
705 private void resolveFunctionBodies(@NotNull BodiesResolveContext c) {
706 for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : c.getFunctions().entrySet()) {
707 JetNamedFunction declaration = entry.getKey();
708 SimpleFunctionDescriptor descriptor = entry.getValue();
709
710 computeDeferredType(descriptor.getReturnType());
711
712 JetScope declaringScope = c.getDeclaringScopes().apply(declaration);
713 assert declaringScope != null;
714
715 resolveFunctionBody(c, trace, declaration, descriptor, declaringScope);
716
717 assert descriptor.getReturnType() != null;
718 }
719 }
720
721 public void resolveFunctionBody(
722 @NotNull BodiesResolveContext c,
723 @NotNull BindingTrace trace,
724 @NotNull JetDeclarationWithBody function,
725 @NotNull FunctionDescriptor functionDescriptor,
726 @NotNull JetScope declaringScope
727 ) {
728 resolveFunctionBody(c, trace, function, functionDescriptor, declaringScope, null, null);
729 }
730
731 public void resolveFunctionBody(
732 @NotNull BodiesResolveContext c,
733 @NotNull BindingTrace trace,
734 @NotNull JetDeclarationWithBody function,
735 @NotNull FunctionDescriptor functionDescriptor,
736 @NotNull JetScope scope,
737 @Nullable Function1<JetScope, DataFlowInfo> beforeBlockBody,
738 @Nullable CallChecker callChecker
739 ) {
740 JetScope innerScope = FunctionDescriptorUtil.getFunctionInnerScope(scope, functionDescriptor, trace);
741 List<JetParameter> valueParameters = function.getValueParameters();
742 List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
743
744 valueParameterResolver.resolveValueParameters(
745 valueParameters, valueParameterDescriptors,
746 ExpressionTypingContext.newContext(
747 additionalCheckerProvider, trace, innerScope, c.getOuterDataFlowInfo(), NO_EXPECTED_TYPE, callChecker)
748 );
749
750 DataFlowInfo dataFlowInfo = null;
751
752 if (beforeBlockBody != null) {
753 dataFlowInfo = beforeBlockBody.invoke(innerScope);
754 }
755
756 if (function.hasBody()) {
757 expressionTypingServices.checkFunctionReturnType(
758 innerScope, function, functionDescriptor, dataFlowInfo != null ? dataFlowInfo : c.getOuterDataFlowInfo(), null, trace);
759 }
760
761 assert functionDescriptor.getReturnType() != null;
762 }
763
764 public void resolveConstructorParameterDefaultValuesAndAnnotations(
765 @NotNull BodiesResolveContext c,
766 @NotNull BindingTrace trace,
767 @NotNull JetClass klass,
768 @NotNull ConstructorDescriptor constructorDescriptor,
769 @NotNull JetScope declaringScope
770 ) {
771 List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters();
772 List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
773
774 JetScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor);
775
776 valueParameterResolver.resolveValueParameters(valueParameters, valueParameterDescriptors, scope,
777 c.getOuterDataFlowInfo(), trace);
778 }
779
780 private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
781 AnnotationResolver.resolveAnnotationsArguments(owner.getModifierList(), trace);
782 }
783
784 private static void computeDeferredType(JetType type) {
785 // handle type inference loop: function or property body contains a reference to itself
786 // fun f() = { f() }
787 // val x = x
788 // type resolution must be started before body resolution
789 if (type instanceof DeferredType) {
790 DeferredType deferredType = (DeferredType) type;
791 if (!deferredType.isComputed()) {
792 deferredType.getDelegate();
793 }
794 }
795 }
796
797 private void computeDeferredTypes() {
798 Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
799 if (deferredTypes != null) {
800 // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
801 final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
802 trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
803 @Override
804 public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
805 queue.addLast(key.getData());
806 }
807 });
808 for (Box<DeferredType> deferredType : deferredTypes) {
809 queue.addLast(deferredType.getData());
810 }
811 while (!queue.isEmpty()) {
812 DeferredType deferredType = queue.pullFirst();
813 if (!deferredType.isComputed()) {
814 try {
815 deferredType.getDelegate(); // to compute
816 }
817 catch (ReenteringLazyValueComputationException e) {
818 // A problem should be reported while computing the type
819 }
820 }
821 }
822 }
823 }
824
825 }