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    }