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