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