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