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