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