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