001    /*
002     * Copyright 2010-2015 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.kotlin.resolve;
018    
019    import org.jetbrains.annotations.NotNull;
020    import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor;
021    import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
022    import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor;
023    import org.jetbrains.kotlin.descriptors.impl.PropertyDescriptorImpl;
024    import org.jetbrains.kotlin.descriptors.impl.ScriptDescriptorImpl;
025    import org.jetbrains.kotlin.psi.JetDeclaration;
026    import org.jetbrains.kotlin.psi.JetNamedFunction;
027    import org.jetbrains.kotlin.psi.JetProperty;
028    import org.jetbrains.kotlin.psi.JetScript;
029    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
030    import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
031    import org.jetbrains.kotlin.resolve.lazy.data.DataPackage;
032    import org.jetbrains.kotlin.resolve.scopes.WritableScope;
033    import org.jetbrains.kotlin.types.ErrorUtils;
034    import org.jetbrains.kotlin.types.JetType;
035    import org.jetbrains.kotlin.types.expressions.CoercionStrategy;
036    import org.jetbrains.kotlin.types.expressions.ExpressionTypingContext;
037    import org.jetbrains.kotlin.types.expressions.ExpressionTypingServices;
038    
039    import javax.inject.Inject;
040    import java.util.ArrayList;
041    import java.util.List;
042    import java.util.Map;
043    
044    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
045    
046    
047    // SCRIPT: resolve symbols in scripts
048    public class ScriptBodyResolver {
049    
050        @NotNull
051        private ExpressionTypingServices expressionTypingServices;
052    
053        @Inject
054        public void setExpressionTypingServices(@NotNull ExpressionTypingServices expressionTypingServices) {
055            this.expressionTypingServices = expressionTypingServices;
056        }
057    
058    
059    
060        public void resolveScriptBodies(@NotNull BodiesResolveContext c, @NotNull BindingTrace trace) {
061            for (Map.Entry<JetScript, ScriptDescriptor> e : c.getScripts().entrySet()) {
062                JetScript declaration = e.getKey();
063                ScriptDescriptor descriptor = e.getValue();
064    
065                if (c.getTopDownAnalysisParameters().isLazy()) {
066                    ForceResolveUtil.forceResolveAllContents(descriptor);
067                    continue;
068                }
069    
070                ScriptDescriptorImpl descriptorImpl = (ScriptDescriptorImpl) descriptor;
071    
072                // TODO: lock in resolveScriptDeclarations
073                descriptorImpl.getScopeForBodyResolution().changeLockLevel(WritableScope.LockLevel.READING);
074    
075                JetType returnType = resolveScriptReturnType(declaration, descriptor, trace);
076    
077                List<PropertyDescriptorImpl> properties = new ArrayList<PropertyDescriptorImpl>();
078                List<SimpleFunctionDescriptor> functions = new ArrayList<SimpleFunctionDescriptor>();
079    
080                BindingContext bindingContext = trace.getBindingContext();
081                for (JetDeclaration jetDeclaration : declaration.getDeclarations()) {
082                    if (jetDeclaration instanceof JetProperty) {
083                        if (!DataPackage.shouldBeScriptClassMember(jetDeclaration)) continue;
084    
085                        PropertyDescriptorImpl propertyDescriptor = (PropertyDescriptorImpl) bindingContext.get(BindingContext.VARIABLE, jetDeclaration);
086                        properties.add(propertyDescriptor);
087                    }
088                    else if (jetDeclaration instanceof JetNamedFunction) {
089                        if (!DataPackage.shouldBeScriptClassMember(jetDeclaration)) continue;
090    
091                        SimpleFunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, jetDeclaration);
092                        assert function != null;
093                        functions.add(function.copy(descriptor.getClassDescriptor(), function.getModality(), function.getVisibility(),
094                                                    CallableMemberDescriptor.Kind.DECLARATION, false));
095                    }
096                }
097    
098                descriptorImpl.initialize(returnType, properties, functions);
099            }
100        }
101    
102        @NotNull
103        public JetType resolveScriptReturnType(
104                @NotNull JetScript script,
105                @NotNull ScriptDescriptor scriptDescriptor,
106                @NotNull BindingTrace trace
107        ) {
108            // Resolve all contents of the script
109            ExpressionTypingContext context = ExpressionTypingContext.newContext(
110                    expressionTypingServices,
111                    trace,
112                    scriptDescriptor.getScopeForBodyResolution(),
113                    DataFlowInfo.EMPTY,
114                    NO_EXPECTED_TYPE
115            );
116            JetType returnType = expressionTypingServices.getBlockReturnedType(script.getBlockExpression(), CoercionStrategy.NO_COERCION, context).getType();
117            if (returnType == null) {
118                returnType = ErrorUtils.createErrorType("getBlockReturnedType returned null");
119            }
120            return returnType;
121        }
122    }