001    /*
002     * Copyright 2010-2013 JetBrains s.r.o.
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    
017    package org.jetbrains.jet.lang.resolve;
018    
019    import com.google.common.collect.Maps;
020    import com.google.common.collect.Sets;
021    import com.intellij.psi.PsiElement;
022    import com.intellij.util.containers.Queue;
023    import org.jetbrains.annotations.NotNull;
024    import org.jetbrains.annotations.Nullable;
025    import org.jetbrains.jet.lang.descriptors.*;
026    import org.jetbrains.jet.lang.descriptors.impl.FunctionDescriptorUtil;
027    import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
028    import org.jetbrains.jet.lang.psi.*;
029    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintPosition;
030    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystem;
031    import org.jetbrains.jet.lang.resolve.calls.inference.ConstraintSystemCompleter;
032    import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
033    import org.jetbrains.jet.lang.resolve.calls.util.CallMaker;
034    import org.jetbrains.jet.lang.resolve.calls.CallResolver;
035    import org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults;
036    import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
037    import org.jetbrains.jet.lang.resolve.scopes.*;
038    import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverValue;
039    import org.jetbrains.jet.lang.types.*;
040    import org.jetbrains.jet.lang.types.checker.JetTypeChecker;
041    import org.jetbrains.jet.lang.types.expressions.DelegatedPropertyUtils;
042    import org.jetbrains.jet.lang.types.expressions.ExpressionTypingServices;
043    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
044    import org.jetbrains.jet.lexer.JetTokens;
045    import org.jetbrains.jet.util.Box;
046    import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
047    import org.jetbrains.jet.util.slicedmap.WritableSlice;
048    
049    import javax.inject.Inject;
050    import java.util.*;
051    
052    import static org.jetbrains.jet.lang.descriptors.ReceiverParameterDescriptor.NO_RECEIVER_PARAMETER;
053    import static org.jetbrains.jet.lang.diagnostics.Errors.*;
054    import static org.jetbrains.jet.lang.resolve.BindingContext.*;
055    import static org.jetbrains.jet.lang.resolve.calls.results.OverloadResolutionResults.Code;
056    import static org.jetbrains.jet.lang.types.TypeUtils.NO_EXPECTED_TYPE;
057    
058    public 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    }