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