001    /*
002     * Copyright 2010-2014 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.jet.lang.resolve;
018    
019    import com.google.common.collect.Maps;
020    import com.google.common.collect.Sets;
021    import com.intellij.lang.ASTNode;
022    import com.intellij.psi.PsiElement;
023    import com.intellij.util.containers.Queue;
024    import org.jetbrains.annotations.NotNull;
025    import org.jetbrains.annotations.Nullable;
026    import org.jetbrains.jet.lang.descriptors.*;
027    import org.jetbrains.jet.lang.psi.*;
028    import org.jetbrains.jet.lang.resolve.calls.CallResolver;
029    import org.jetbrains.jet.lang.resolve.calls.context.ContextDependency;
030    import org.jetbrains.jet.lang.resolve.calls.context.SimpleResolutionContext;
031    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
032    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
033    import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
034    import org.jetbrains.jet.lang.resolve.scopes.*;
035    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
036    import org.jetbrains.jet.lang.types.*;
037    import org.jetbrains.jet.lang.types.expressions.DataFlowUtils;
038    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
039    import org.jetbrains.jet.lexer.JetModifierKeywordToken;
040    import org.jetbrains.jet.lexer.JetTokens;
041    import org.jetbrains.jet.util.Box;
042    import org.jetbrains.jet.util.ReenteringLazyValueComputationException;
043    import org.jetbrains.jet.util.slicedmap.WritableSlice;
044    
045    import javax.inject.Inject;
046    import java.util.*;
047    
048    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
049    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
050    import static org.jetbrains.jet.lang.resolve.BindingContext.DEFERRED_TYPE;
051    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
052    
053    public class BodyResolver {
054        @NotNull
055        private ScriptBodyResolver scriptBodyResolverResolver;
056        @NotNull
057        private ExpressionTypingServices expressionTypingServices;
058        @NotNull
059        private CallResolver callResolver;
060        @NotNull
061        private ObservableBindingTrace trace;
062        @NotNull
063        private ControlFlowAnalyzer controlFlowAnalyzer;
064        @NotNull
065        private DeclarationsChecker declarationsChecker;
066        @NotNull
067        private AnnotationResolver annotationResolver;
068        @NotNull
069        private DelegatedPropertyResolver delegatedPropertyResolver;
070        @NotNull
071        private FunctionAnalyzerExtension functionAnalyzerExtension;
072    
073        @Inject
074        public void setScriptBodyResolverResolver(@NotNull ScriptBodyResolver scriptBodyResolverResolver) {
075            this.scriptBodyResolverResolver = scriptBodyResolverResolver;
076        }
077    
078        @Inject
079        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
080            this.expressionTypingServices = expressionTypingServices;
081        }
082    
083        @Inject
084        public void setCallResolver(@NotNull CallResolver callResolver) {
085            this.callResolver = callResolver;
086        }
087    
088        @Inject
089        public void setTrace(@NotNull BindingTrace trace) {
090            this.trace = new ObservableBindingTrace(trace);
091        }
092    
093        @Inject
094        public void setControlFlowAnalyzer(@NotNull ControlFlowAnalyzer controlFlowAnalyzer) {
095            this.controlFlowAnalyzer = controlFlowAnalyzer;
096        }
097    
098        @Inject
099        public void setDeclarationsChecker(@NotNull DeclarationsChecker declarationsChecker) {
100            this.declarationsChecker = declarationsChecker;
101        }
102    
103        @Inject
104        public void setAnnotationResolver(@NotNull AnnotationResolver annotationResolver) {
105            this.annotationResolver = annotationResolver;
106        }
107    
108        @Inject
109        public void setDelegatedPropertyResolver(@NotNull DelegatedPropertyResolver delegatedPropertyResolver) {
110            this.delegatedPropertyResolver = delegatedPropertyResolver;
111        }
112    
113        @Inject
114        public void setFunctionAnalyzerExtension(@NotNull FunctionAnalyzerExtension functionAnalyzerExtension) {
115            this.functionAnalyzerExtension = functionAnalyzerExtension;
116        }
117    
118        private void resolveBehaviorDeclarationBodies(@NotNull BodiesResolveContext c) {
119            resolveDelegationSpecifierLists(c);
120    
121            resolvePropertyDeclarationBodies(c);
122    
123            if (!c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
124                resolveClassAnnotations(c);
125            }
126            resolveAnonymousInitializers(c);
127            resolvePrimaryConstructorParameters(c);
128    
129            resolveFunctionBodies(c);
130    
131            // SCRIPT: resolve script bodies
132            scriptBodyResolverResolver.resolveScriptBodies(c, trace);
133    
134            if (!c.getTopDownAnalysisParameters().isDeclaredLocally()) {
135                computeDeferredTypes();
136            }
137        }
138    
139        public void resolveBodies(@NotNull BodiesResolveContext c) {
140            resolveBehaviorDeclarationBodies(c);
141            controlFlowAnalyzer.process(c);
142            declarationsChecker.process(c);
143            functionAnalyzerExtension.process(c);
144        }
145    
146        private void resolveDelegationSpecifierLists(@NotNull BodiesResolveContext c) {
147            // TODO : Make sure the same thing is not initialized twice
148            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
149                JetClassOrObject classOrObject = entry.getKey();
150                ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
151    
152                resolveDelegationSpecifierList(c, classOrObject, descriptor,
153                                               descriptor.getUnsubstitutedPrimaryConstructor(),
154                                               descriptor.getScopeForClassHeaderResolution(),
155                                               descriptor.getScopeForMemberDeclarationResolution());
156            }
157        }
158    
159        public void resolveDelegationSpecifierList(
160                @NotNull final BodiesResolveContext c,
161                @NotNull JetClassOrObject jetClass,
162                @NotNull final ClassDescriptor descriptor,
163                @Nullable final ConstructorDescriptor primaryConstructor,
164                @NotNull JetScope scopeForSupertypeResolution,
165                @NotNull final JetScope scopeForMemberResolution) {
166            if (!c.completeAnalysisNeeded(jetClass)) return;
167            final JetScope scopeForConstructor = primaryConstructor == null
168                    ? null
169                    : FunctionDescriptorUtil.getFunctionInnerScope(scopeForSupertypeResolution, primaryConstructor, trace);
170            final ExpressionTypingServices typeInferrer = expressionTypingServices; // TODO : flow
171    
172            final Map<JetTypeReference, JetType> supertypes = Maps.newLinkedHashMap();
173            JetVisitorVoid visitor = new JetVisitorVoid() {
174                private void recordSupertype(JetTypeReference typeReference, JetType supertype) {
175                    if (supertype == null) return;
176                    supertypes.put(typeReference, supertype);
177                }
178    
179                @Override
180                public void visitDelegationByExpressionSpecifier(@NotNull JetDelegatorByExpressionSpecifier specifier) {
181                    if (descriptor.getKind() == ClassKind.TRAIT) {
182                        trace.report(DELEGATION_IN_TRAIT.on(specifier));
183                    }
184                    JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, specifier.getTypeReference());
185                    recordSupertype(specifier.getTypeReference(), supertype);
186                    if (supertype != null) {
187                        DeclarationDescriptor declarationDescriptor = supertype.getConstructor().getDeclarationDescriptor();
188                        if (declarationDescriptor instanceof ClassDescriptor) {
189                            ClassDescriptor classDescriptor = (ClassDescriptor) declarationDescriptor;
190                            if (classDescriptor.getKind() != ClassKind.TRAIT) {
191                                trace.report(DELEGATION_NOT_TO_TRAIT.on(specifier.getTypeReference()));
192                            }
193                        }
194                    }
195                    JetExpression delegateExpression = specifier.getDelegateExpression();
196                    if (delegateExpression != null) {
197                        JetScope scope = scopeForConstructor == null
198                                         ? scopeForMemberResolution
199                                         : scopeForConstructor;
200                        JetType type = typeInferrer.getType(scope, delegateExpression, NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), trace);
201                        if (type != null && supertype != null) {
202                            SimpleResolutionContext simpleResolutionContext = new SimpleResolutionContext(
203                                    trace, scope, supertype, c.getOuterDataFlowInfo(), ContextDependency.INDEPENDENT,
204                                    expressionTypingServices.createExtension(scope, false));
205                            DataFlowUtils.checkType(type, delegateExpression, simpleResolutionContext);
206                        }
207                    }
208                }
209    
210                @Override
211                public void visitDelegationToSuperCallSpecifier(@NotNull JetDelegatorToSuperCall call) {
212                    JetValueArgumentList valueArgumentList = call.getValueArgumentList();
213                    PsiElement elementToMark = valueArgumentList == null ? call : valueArgumentList;
214                    if (descriptor.getKind() == ClassKind.TRAIT) {
215                        trace.report(SUPERTYPE_INITIALIZED_IN_TRAIT.on(elementToMark));
216                    }
217                    JetTypeReference typeReference = call.getTypeReference();
218                    if (typeReference == null) return;
219                    if (primaryConstructor == null) {
220                        assert descriptor.getKind() == ClassKind.TRAIT;
221                        recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
222                        return;
223                    }
224                    OverloadResolutionResults<FunctionDescriptor> results = callResolver.resolveFunctionCall(
225                            trace, scopeForConstructor,
226                            CallMaker.makeCall(ReceiverValue.NO_RECEIVER, null, call), NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), false);
227                    if (results.isSuccess()) {
228                        JetType supertype = results.getResultingDescriptor().getReturnType();
229                        recordSupertype(typeReference, supertype);
230                        ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
231                        if (classDescriptor != null) {
232                            if (classDescriptor.getKind() == ClassKind.TRAIT) {
233                                trace.report(CONSTRUCTOR_IN_TRAIT.on(elementToMark));
234                            }
235                        }
236                    }
237                    else {
238                        recordSupertype(typeReference, trace.getBindingContext().get(BindingContext.TYPE, typeReference));
239                    }
240                }
241    
242                @Override
243                public void visitDelegationToSuperClassSpecifier(@NotNull JetDelegatorToSuperClass specifier) {
244                    JetTypeReference typeReference = specifier.getTypeReference();
245                    JetType supertype = trace.getBindingContext().get(BindingContext.TYPE, typeReference);
246                    recordSupertype(typeReference, supertype);
247                    if (supertype == null) return;
248                    ClassDescriptor superClass = TypeUtils.getClassDescriptor(supertype);
249                    if (superClass == null) return;
250                    if (superClass.getKind().isSingleton()) {
251                        // A "singleton in supertype" diagnostic will be reported later
252                        return;
253                    }
254                    if (descriptor.getKind() != ClassKind.TRAIT && !superClass.getConstructors().isEmpty() && !ErrorUtils.isError(superClass)) {
255                        trace.report(SUPERTYPE_NOT_INITIALIZED.on(specifier));
256                    }
257                }
258    
259                @Override
260                public void visitDelegationToThisCall(@NotNull JetDelegatorToThisCall thisCall) {
261                    throw new IllegalStateException("This-calls should be prohibited by the parser");
262                }
263    
264                @Override
265                public void visitJetElement(@NotNull JetElement element) {
266                    throw new UnsupportedOperationException(element.getText() + " : " + element);
267                }
268            };
269    
270            for (JetDelegationSpecifier delegationSpecifier : jetClass.getDelegationSpecifiers()) {
271                delegationSpecifier.accept(visitor);
272            }
273    
274            if (DescriptorUtils.isAnnotationClass(descriptor) && jetClass.getDelegationSpecifierList() != null) {
275                trace.report(SUPERTYPES_FOR_ANNOTATION_CLASS.on(jetClass.getDelegationSpecifierList()));
276            }
277    
278            Set<TypeConstructor> parentEnum =
279                    jetClass instanceof JetEnumEntry
280                    ? Collections.singleton(((ClassDescriptor) descriptor.getContainingDeclaration()).getTypeConstructor())
281                    : Collections.<TypeConstructor>emptySet();
282    
283            checkSupertypeList(descriptor, supertypes, parentEnum);
284        }
285    
286        // allowedFinalSupertypes typically contains a enum type of which supertypeOwner is an entry
287        private void checkSupertypeList(
288                @NotNull ClassDescriptor supertypeOwner,
289                @NotNull Map<JetTypeReference, JetType> supertypes,
290                @NotNull Set<TypeConstructor> allowedFinalSupertypes
291        ) {
292            Set<TypeConstructor> typeConstructors = Sets.newHashSet();
293            boolean classAppeared = false;
294            for (Map.Entry<JetTypeReference, JetType> entry : supertypes.entrySet()) {
295                JetTypeReference typeReference = entry.getKey();
296                JetType supertype = entry.getValue();
297    
298                ClassDescriptor classDescriptor = TypeUtils.getClassDescriptor(supertype);
299                if (classDescriptor != null) {
300                    if (classDescriptor.getKind() != ClassKind.TRAIT) {
301                        if (supertypeOwner.getKind() == ClassKind.ENUM_CLASS) {
302                            trace.report(CLASS_IN_SUPERTYPE_FOR_ENUM.on(typeReference));
303                        }
304                        if (classAppeared) {
305                            trace.report(MANY_CLASSES_IN_SUPERTYPE_LIST.on(typeReference));
306                        }
307                        else {
308                            classAppeared = true;
309                        }
310                    }
311                }
312                else {
313                    trace.report(SUPERTYPE_NOT_A_CLASS_OR_TRAIT.on(typeReference));
314                }
315    
316                TypeConstructor constructor = supertype.getConstructor();
317                if (!typeConstructors.add(constructor)) {
318                    trace.report(SUPERTYPE_APPEARS_TWICE.on(typeReference));
319                }
320    
321                if (DescriptorUtils.isSingleton(classDescriptor)) {
322                    trace.report(SINGLETON_IN_SUPERTYPE.on(typeReference));
323                }
324                else if (constructor.isFinal() && !allowedFinalSupertypes.contains(constructor)) {
325                    trace.report(FINAL_SUPERTYPE.on(typeReference));
326                }
327            }
328        }
329    
330        private void resolveClassAnnotations(@NotNull BodiesResolveContext c) {
331            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
332                resolveAnnotationArguments(entry.getValue().getScopeForClassHeaderResolution(), entry.getKey());
333            }
334        }
335    
336        private void resolveAnonymousInitializers(@NotNull BodiesResolveContext c) {
337            if (c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
338                for (Map.Entry<JetClassInitializer, ClassDescriptorWithResolutionScopes> entry : c.getAnonymousInitializers().entrySet()) {
339                    JetClassInitializer initializer = entry.getKey();
340                    ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
341                    resolveAnonymousInitializer(c, initializer, descriptor);
342                }
343            }
344            else {
345                for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
346                    JetClassOrObject classOrObject = entry.getKey();
347                    ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
348    
349                    if (!c.completeAnalysisNeeded(classOrObject)) return;
350                    for (JetClassInitializer initializer : classOrObject.getAnonymousInitializers()) {
351                        resolveAnonymousInitializer(c, initializer, descriptor);
352                    }
353                }
354            }
355    
356        }
357    
358        public void resolveAnonymousInitializer(
359                @NotNull BodiesResolveContext c,
360                @NotNull JetClassInitializer anonymousInitializer,
361                @NotNull ClassDescriptorWithResolutionScopes classDescriptor
362        ) {
363            if (!c.completeAnalysisNeeded(anonymousInitializer)) return;
364    
365            JetScope scopeForInitializers = classDescriptor.getScopeForInitializerResolution();
366            if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
367                expressionTypingServices.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), trace);
368                processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
369            }
370            else {
371                trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer));
372                processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
373            }
374        }
375    
376        private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) {
377            JetModifierList modifierList = owner.getModifierList();
378            if (modifierList == null) return;
379    
380            annotationResolver.resolveAnnotationsWithArguments(scope, modifierList, trace);
381    
382            for (ASTNode node : modifierList.getModifierNodes()) {
383                trace.report(ILLEGAL_MODIFIER.on(node.getPsi(), (JetModifierKeywordToken) node.getElementType()));
384            }
385        }
386    
387        private void resolvePrimaryConstructorParameters(@NotNull BodiesResolveContext c) {
388            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
389                if (!(entry.getKey() instanceof JetClass)) continue;
390                JetClass klass = (JetClass) entry.getKey();
391                ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
392                ConstructorDescriptor unsubstitutedPrimaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
393    
394                AnnotationResolver.resolveAnnotationsArguments(klass.getPrimaryConstructorModifierList(), trace);
395    
396                if (unsubstitutedPrimaryConstructor != null) {
397                    WritableScope parameterScope = getPrimaryConstructorParametersScope(classDescriptor.getScopeForClassHeaderResolution(), unsubstitutedPrimaryConstructor);
398                    expressionTypingServices.resolveValueParameters(klass.getPrimaryConstructorParameters(), unsubstitutedPrimaryConstructor.getValueParameters(),
399                                           parameterScope, c.getOuterDataFlowInfo(), trace, c.completeAnalysisNeeded(klass));
400                }
401            }
402        }
403    
404        private static WritableScope getPrimaryConstructorParametersScope(
405                JetScope originalScope,
406                ConstructorDescriptor unsubstitutedPrimaryConstructor
407        ) {
408            WritableScope parameterScope = new WritableScopeImpl(
409                    originalScope,
410                    unsubstitutedPrimaryConstructor,
411                    RedeclarationHandler.DO_NOTHING, "Scope with value parameters of a constructor"
412            );
413            for (ValueParameterDescriptor valueParameterDescriptor : unsubstitutedPrimaryConstructor.getValueParameters()) {
414                parameterScope.addVariableDescriptor(valueParameterDescriptor);
415            }
416            parameterScope.changeLockLevel(WritableScope.LockLevel.READING);
417            return parameterScope;
418        }
419    
420        private void resolvePropertyDeclarationBodies(@NotNull BodiesResolveContext c) {
421    
422            // Member properties
423            Set<JetProperty> processed = Sets.newHashSet();
424            for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
425                if (!(entry.getKey() instanceof JetClass)) continue;
426                JetClass jetClass = (JetClass) entry.getKey();
427                ClassDescriptorWithResolutionScopes classDescriptor = entry.getValue();
428    
429                for (JetProperty property : jetClass.getProperties()) {
430                    PropertyDescriptor propertyDescriptor = c.getProperties().get(property);
431                    assert propertyDescriptor != null;
432    
433                    computeDeferredType(propertyDescriptor.getReturnType());
434    
435                    JetExpression initializer = property.getInitializer();
436                    JetScope propertyScope = getScopeForProperty(c, property);
437                    if (initializer != null) {
438                        ConstructorDescriptor primaryConstructor = classDescriptor.getUnsubstitutedPrimaryConstructor();
439                        if (primaryConstructor != null) {
440                            resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
441                        }
442                    }
443    
444                    JetExpression delegateExpression = property.getDelegateExpression();
445                    if (delegateExpression != null) {
446                        assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
447                        resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, classDescriptor.getScopeForMemberDeclarationResolution(), propertyScope);
448                    }
449    
450                    resolveAnnotationArguments(propertyScope, property);
451    
452                    resolvePropertyAccessors(c, property, propertyDescriptor);
453                    processed.add(property);
454                }
455            }
456    
457            // Top-level properties & properties of objects
458            for (Map.Entry<JetProperty, PropertyDescriptor> entry : c.getProperties().entrySet()) {
459                JetProperty property = entry.getKey();
460                if (processed.contains(property)) continue;
461    
462                PropertyDescriptor propertyDescriptor = entry.getValue();
463    
464                computeDeferredType(propertyDescriptor.getReturnType());
465    
466                JetExpression initializer = property.getInitializer();
467                JetScope propertyScope = getScopeForProperty(c, property);
468                if (initializer != null) {
469                    resolvePropertyInitializer(c, property, propertyDescriptor, initializer, propertyScope);
470                }
471    
472                JetExpression delegateExpression = property.getDelegateExpression();
473                if (delegateExpression != null) {
474                    assert initializer == null : "Initializer should be null for delegated property : " + property.getText();
475                    resolvePropertyDelegate(c, property, propertyDescriptor, delegateExpression, propertyScope, propertyScope);
476                }
477    
478                resolveAnnotationArguments(propertyScope, property);
479    
480                resolvePropertyAccessors(c, property, propertyDescriptor);
481            }
482        }
483    
484        private JetScope makeScopeForPropertyAccessor(@NotNull BodiesResolveContext c, @NotNull JetPropertyAccessor accessor, @NotNull PropertyDescriptor descriptor) {
485            JetScope accessorDeclaringScope = c.getDeclaringScopes().apply(accessor);
486            assert accessorDeclaringScope != null : "Scope for accessor " + accessor.getText() + " should exists";
487            return JetScopeUtils.makeScopeForPropertyAccessor(descriptor, accessorDeclaringScope, trace);
488        }
489    
490        public void resolvePropertyAccessors(
491                @NotNull BodiesResolveContext c,
492                @NotNull JetProperty property,
493                @NotNull PropertyDescriptor propertyDescriptor
494        ) {
495            ObservableBindingTrace fieldAccessTrackingTrace = createFieldTrackingTrace(propertyDescriptor);
496    
497            JetPropertyAccessor getter = property.getGetter();
498            PropertyGetterDescriptor getterDescriptor = propertyDescriptor.getGetter();
499            if (getter != null && getterDescriptor != null) {
500                JetScope accessorScope = makeScopeForPropertyAccessor(c, getter, propertyDescriptor);
501                resolveAnnotationArguments(accessorScope, getter);
502                resolveFunctionBody(c, fieldAccessTrackingTrace, getter, getterDescriptor, accessorScope);
503            }
504    
505            JetPropertyAccessor setter = property.getSetter();
506            PropertySetterDescriptor setterDescriptor = propertyDescriptor.getSetter();
507            if (setter != null && setterDescriptor != null) {
508                JetScope accessorScope = makeScopeForPropertyAccessor(c, setter, propertyDescriptor);
509                resolveAnnotationArguments(accessorScope, setter);
510                resolveFunctionBody(c, fieldAccessTrackingTrace, setter, setterDescriptor, accessorScope);
511            }
512        }
513    
514        private ObservableBindingTrace createFieldTrackingTrace(final PropertyDescriptor propertyDescriptor) {
515            return new ObservableBindingTrace(trace).addHandler(BindingContext.REFERENCE_TARGET, new ObservableBindingTrace.RecordHandler<JetReferenceExpression, DeclarationDescriptor>() {
516                @Override
517                public void handleRecord(WritableSlice<JetReferenceExpression, DeclarationDescriptor> slice, JetReferenceExpression expression, DeclarationDescriptor descriptor) {
518                    if (expression instanceof JetSimpleNameExpression) {
519                        JetSimpleNameExpression simpleNameExpression = (JetSimpleNameExpression) expression;
520                        if (simpleNameExpression.getReferencedNameElementType() == JetTokens.FIELD_IDENTIFIER) {
521                            // This check may be considered redundant as long as $x is only accessible from accessors to $x
522                            if (descriptor == propertyDescriptor) { // TODO : original?
523                                trace.record(BindingContext.BACKING_FIELD_REQUIRED, propertyDescriptor); // TODO: this trace?
524                            }
525                        }
526                    }
527                }
528            });
529        }
530    
531        public void resolvePropertyDelegate(
532                @NotNull BodiesResolveContext c,
533                @NotNull JetProperty jetProperty,
534                @NotNull PropertyDescriptor propertyDescriptor,
535                @NotNull JetExpression delegateExpression,
536                @NotNull JetScope parentScopeForAccessor,
537                @NotNull JetScope propertyScope
538        ) {
539            JetPropertyAccessor getter = jetProperty.getGetter();
540            if (getter != null) {
541                trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(getter));
542            }
543    
544            JetPropertyAccessor setter = jetProperty.getSetter();
545            if (setter != null) {
546                trace.report(ACCESSOR_FOR_DELEGATED_PROPERTY.on(setter));
547            }
548    
549            JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
550                    propertyScope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
551            JetScope accessorScope = JetScopeUtils.makeScopeForPropertyAccessor(
552                    propertyDescriptor, parentScopeForAccessor, trace);
553    
554            JetType delegateType = delegatedPropertyResolver.resolveDelegateExpression(
555                    delegateExpression, jetProperty, propertyDescriptor, propertyDeclarationInnerScope, accessorScope, trace,
556                    c.getOuterDataFlowInfo());
557    
558            delegatedPropertyResolver.resolveDelegatedPropertyGetMethod(propertyDescriptor, delegateExpression, delegateType,
559                                                                        trace, accessorScope);
560    
561            if (jetProperty.isVar()) {
562                delegatedPropertyResolver.resolveDelegatedPropertySetMethod(propertyDescriptor, delegateExpression, delegateType,
563                                                                            trace, accessorScope);
564            }
565        }
566    
567        public void resolvePropertyInitializer(
568                @NotNull BodiesResolveContext c,
569                @NotNull JetProperty property,
570                @NotNull PropertyDescriptor propertyDescriptor,
571                @NotNull JetExpression initializer,
572                @NotNull JetScope scope
573        ) {
574            JetScope propertyDeclarationInnerScope = JetScopeUtils.getPropertyDeclarationInnerScopeForInitializer(
575                    scope, propertyDescriptor.getTypeParameters(), NO_RECEIVER_PARAMETER, trace);
576            JetType expectedTypeForInitializer = property.getTypeRef() != null ? propertyDescriptor.getType() : NO_EXPECTED_TYPE;
577            CompileTimeConstant<?> compileTimeInitializer = propertyDescriptor.getCompileTimeInitializer();
578            if (compileTimeInitializer == null) {
579                expressionTypingServices.getType(propertyDeclarationInnerScope, initializer, expectedTypeForInitializer, c.getOuterDataFlowInfo(), trace);
580            }
581        }
582    
583        @NotNull
584        private JetScope getScopeForProperty(@NotNull BodiesResolveContext c, @NotNull JetProperty property) {
585            JetScope scope = c.getDeclaringScopes().apply(property);
586            assert scope != null : "Scope for property " + property.getText() + " should exists";
587            return scope;
588        }
589    
590        private void resolveFunctionBodies(@NotNull BodiesResolveContext c) {
591            for (Map.Entry<JetNamedFunction, SimpleFunctionDescriptor> entry : c.getFunctions().entrySet()) {
592                JetNamedFunction declaration = entry.getKey();
593                SimpleFunctionDescriptor descriptor = entry.getValue();
594    
595                computeDeferredType(descriptor.getReturnType());
596    
597                JetScope declaringScope = c.getDeclaringScopes().apply(declaration);
598                assert declaringScope != null;
599    
600                if (!c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
601                    resolveAnnotationArguments(declaringScope, declaration);
602                }
603                resolveFunctionBody(c, trace, declaration, descriptor, declaringScope);
604    
605                assert descriptor.getReturnType() != null;
606            }
607        }
608    
609        public void resolveFunctionBody(
610                @NotNull BodiesResolveContext c,
611                @NotNull BindingTrace trace,
612                @NotNull JetDeclarationWithBody function,
613                @NotNull FunctionDescriptor functionDescriptor,
614                @NotNull JetScope declaringScope
615        ) {
616            JetScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(declaringScope, functionDescriptor, trace);
617    
618            List<JetParameter> valueParameters = function.getValueParameters();
619            List<ValueParameterDescriptor> valueParameterDescriptors = functionDescriptor.getValueParameters();
620    
621            boolean needCompleteAnalysis = c.completeAnalysisNeeded(function);
622    
623            expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, functionInnerScope,
624                                                            c.getOuterDataFlowInfo(), trace, needCompleteAnalysis);
625    
626            if (!needCompleteAnalysis) return;
627    
628            JetExpression bodyExpression = function.getBodyExpression();
629            if (bodyExpression != null) {
630                expressionTypingServices.checkFunctionReturnType(functionInnerScope, function, functionDescriptor, c.getOuterDataFlowInfo(), null, trace);
631            }
632    
633            assert functionDescriptor.getReturnType() != null;
634        }
635    
636        public void resolveConstructorParameterDefaultValuesAndAnnotations(
637                @NotNull BodiesResolveContext c,
638                @NotNull BindingTrace trace,
639                @NotNull JetClass klass,
640                @NotNull ConstructorDescriptor constructorDescriptor,
641                @NotNull JetScope declaringScope
642        ) {
643            if (!c.completeAnalysisNeeded(klass)) return;
644    
645            List<JetParameter> valueParameters = klass.getPrimaryConstructorParameters();
646            List<ValueParameterDescriptor> valueParameterDescriptors = constructorDescriptor.getValueParameters();
647    
648            JetScope scope = getPrimaryConstructorParametersScope(declaringScope, constructorDescriptor);
649    
650            expressionTypingServices.resolveValueParameters(valueParameters, valueParameterDescriptors, scope,
651                                                            c.getOuterDataFlowInfo(), trace, /* needCompleteAnalysis = */ true);
652        }
653    
654        private void resolveAnnotationArguments(@NotNull JetScope scope, @NotNull JetModifierListOwner owner) {
655            AnnotationResolver.resolveAnnotationsArguments(owner.getModifierList(), trace);
656        }
657    
658        private static void computeDeferredType(JetType type) {
659            // handle type inference loop: function or property body contains a reference to itself
660            // fun f() = { f() }
661            // val x = x
662            // type resolution must be started before body resolution
663            if (type instanceof DeferredType) {
664                DeferredType deferredType = (DeferredType) type;
665                if (!deferredType.isComputed()) {
666                    deferredType.getDelegate();
667                }
668            }
669        }
670    
671        private void computeDeferredTypes() {
672            Collection<Box<DeferredType>> deferredTypes = trace.getKeys(DEFERRED_TYPE);
673            if (deferredTypes != null) {
674                // +1 is a work around agains new Queue(0).addLast(...) bug // stepan.koltsov@ 2011-11-21
675                final Queue<DeferredType> queue = new Queue<DeferredType>(deferredTypes.size() + 1);
676                trace.addHandler(DEFERRED_TYPE, new ObservableBindingTrace.RecordHandler<Box<DeferredType>, Boolean>() {
677                    @Override
678                    public void handleRecord(WritableSlice<Box<DeferredType>, Boolean> deferredTypeKeyDeferredTypeWritableSlice, Box<DeferredType> key, Boolean value) {
679                        queue.addLast(key.getData());
680                    }
681                });
682                for (Box<DeferredType> deferredType : deferredTypes) {
683                    queue.addLast(deferredType.getData());
684                }
685                while (!queue.isEmpty()) {
686                    DeferredType deferredType = queue.pullFirst();
687                    if (!deferredType.isComputed()) {
688                        try {
689                            deferredType.getDelegate(); // to compute
690                        }
691                        catch (ReenteringLazyValueComputationException e) {
692                            // A problem should be reported while computing the type
693                        }
694                    }
695                }
696            }
697        }
698    
699    }