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