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    }