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.types.expressions;
018    
019    import com.intellij.psi.tree.IElementType;
020    import org.jetbrains.annotations.NotNull;
021    import org.jetbrains.annotations.Nullable;
022    import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
023    import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
024    import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
025    import org.jetbrains.kotlin.descriptors.ScriptDescriptor;
026    import org.jetbrains.kotlin.lexer.KtTokens;
027    import org.jetbrains.kotlin.psi.*;
028    import org.jetbrains.kotlin.resolve.*;
029    import org.jetbrains.kotlin.resolve.calls.context.ContextDependency;
030    import org.jetbrains.kotlin.resolve.calls.context.ResolutionContext;
031    import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
032    import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
033    import org.jetbrains.kotlin.resolve.scopes.LexicalScopeKind;
034    import org.jetbrains.kotlin.resolve.scopes.LexicalWritableScope;
035    import org.jetbrains.kotlin.types.ErrorUtils;
036    import org.jetbrains.kotlin.types.KotlinType;
037    import org.jetbrains.kotlin.types.expressions.typeInfoFactory.TypeInfoFactoryKt;
038    
039    import java.util.Iterator;
040    import java.util.List;
041    
042    import static org.jetbrains.kotlin.types.TypeUtils.NO_EXPECTED_TYPE;
043    import static org.jetbrains.kotlin.types.TypeUtils.UNIT_EXPECTED_TYPE;
044    import static org.jetbrains.kotlin.types.expressions.CoercionStrategy.COERCION_TO_UNIT;
045    
046    public class ExpressionTypingServices {
047    
048        private final ExpressionTypingFacade expressionTypingFacade;
049        private final ExpressionTypingComponents expressionTypingComponents;
050    
051        @NotNull private final AnnotationChecker annotationChecker;
052        @NotNull private final StatementFilter statementFilter;
053    
054        public ExpressionTypingServices(
055                @NotNull ExpressionTypingComponents components,
056                @NotNull AnnotationChecker annotationChecker,
057                @NotNull StatementFilter statementFilter,
058                @NotNull ExpressionTypingVisitorDispatcher.ForDeclarations facade
059        ) {
060            this.expressionTypingComponents = components;
061            this.annotationChecker = annotationChecker;
062            this.statementFilter = statementFilter;
063            this.expressionTypingFacade = facade;
064        }
065    
066        @NotNull public StatementFilter getStatementFilter() {
067            return statementFilter;
068        }
069    
070        @NotNull
071        public KotlinType safeGetType(
072                @NotNull LexicalScope scope,
073                @NotNull KtExpression expression,
074                @NotNull KotlinType expectedType,
075                @NotNull DataFlowInfo dataFlowInfo,
076                @NotNull BindingTrace trace
077        ) {
078            KotlinType type = getType(scope, expression, expectedType, dataFlowInfo, trace);
079    
080            return type != null ? type : ErrorUtils.createErrorType("Type for " + expression.getText());
081        }
082    
083        @NotNull
084        public KotlinTypeInfo getTypeInfo(
085                @NotNull LexicalScope scope,
086                @NotNull KtExpression expression,
087                @NotNull KotlinType expectedType,
088                @NotNull DataFlowInfo dataFlowInfo,
089                @NotNull BindingTrace trace,
090                boolean isStatement
091        ) {
092            ExpressionTypingContext context = ExpressionTypingContext.newContext(
093                    trace, scope, dataFlowInfo, expectedType
094            );
095            return expressionTypingFacade.getTypeInfo(expression, context, isStatement);
096        }
097    
098        @NotNull
099        public KotlinTypeInfo getTypeInfo(@NotNull KtExpression expression, @NotNull ResolutionContext resolutionContext) {
100            return expressionTypingFacade.getTypeInfo(expression, ExpressionTypingContext.newContext(resolutionContext));
101        }
102    
103        @Nullable
104        public KotlinType getType(
105                @NotNull LexicalScope scope,
106                @NotNull KtExpression expression,
107                @NotNull KotlinType expectedType,
108                @NotNull DataFlowInfo dataFlowInfo,
109                @NotNull BindingTrace trace
110        ) {
111            return getTypeInfo(scope, expression, expectedType, dataFlowInfo, trace, false).getType();
112        }
113    
114        /////////////////////////////////////////////////////////
115    
116        public void checkFunctionReturnType(
117                @NotNull LexicalScope functionInnerScope,
118                @NotNull KtDeclarationWithBody function,
119                @NotNull FunctionDescriptor functionDescriptor,
120                @NotNull DataFlowInfo dataFlowInfo,
121                @Nullable KotlinType expectedReturnType,
122                BindingTrace trace
123        ) {
124            if (expectedReturnType == null) {
125                expectedReturnType = functionDescriptor.getReturnType();
126                if (!function.hasBlockBody() && !function.hasDeclaredReturnType()) {
127                    expectedReturnType = NO_EXPECTED_TYPE;
128                }
129            }
130            checkFunctionReturnType(function, ExpressionTypingContext.newContext(
131                    trace,
132                    functionInnerScope, dataFlowInfo, expectedReturnType != null ? expectedReturnType : NO_EXPECTED_TYPE
133            ));
134        }
135    
136        /*package*/ void checkFunctionReturnType(KtDeclarationWithBody function, ExpressionTypingContext context) {
137            KtExpression bodyExpression = function.getBodyExpression();
138            if (bodyExpression == null) return;
139    
140            boolean blockBody = function.hasBlockBody();
141            ExpressionTypingContext newContext =
142                    blockBody
143                    ? context.replaceExpectedType(NO_EXPECTED_TYPE)
144                    : context;
145    
146            expressionTypingFacade.getTypeInfo(bodyExpression, newContext, blockBody);
147        }
148    
149        @NotNull
150        public KotlinTypeInfo getBlockReturnedType(KtBlockExpression expression, ExpressionTypingContext context, boolean isStatement) {
151            return getBlockReturnedType(expression, isStatement ? CoercionStrategy.COERCION_TO_UNIT : CoercionStrategy.NO_COERCION, context);
152        }
153    
154        @NotNull
155        public KotlinTypeInfo getBlockReturnedType(
156                @NotNull KtBlockExpression expression,
157                @NotNull CoercionStrategy coercionStrategyForLastExpression,
158                @NotNull ExpressionTypingContext context
159        ) {
160            List<KtExpression> block = StatementFilterKt.filterStatements(statementFilter, expression);
161    
162            DeclarationDescriptor containingDescriptor = context.scope.getOwnerDescriptor();
163            LexicalWritableScope scope = new LexicalWritableScope(context.scope, containingDescriptor, false, null,
164                                                                  new TraceBasedRedeclarationHandler(context.trace), LexicalScopeKind.CODE_BLOCK);
165            scope.changeLockLevel(LexicalWritableScope.LockLevel.BOTH);
166    
167            KotlinTypeInfo r;
168            if (block.isEmpty()) {
169                r = expressionTypingComponents.dataFlowAnalyzer
170                        .createCheckedTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context, expression);
171            }
172            else {
173                r = getBlockReturnedTypeWithWritableScope(scope, block, coercionStrategyForLastExpression,
174                                                          context.replaceStatementFilter(statementFilter));
175            }
176            scope.changeLockLevel(LexicalWritableScope.LockLevel.READING);
177    
178            if (containingDescriptor instanceof ScriptDescriptor) {
179                context.trace.record(BindingContext.SCRIPT_SCOPE, (ScriptDescriptor) containingDescriptor, scope);
180            }
181    
182            return r;
183        }
184    
185        @NotNull
186        public KotlinType getBodyExpressionType(
187                @NotNull BindingTrace trace,
188                @NotNull LexicalScope outerScope,
189                @NotNull DataFlowInfo dataFlowInfo,
190                @NotNull KtDeclarationWithBody function,
191                @NotNull FunctionDescriptor functionDescriptor
192        ) {
193            KtExpression bodyExpression = function.getBodyExpression();
194            assert bodyExpression != null;
195            LexicalScope functionInnerScope = FunctionDescriptorUtil.getFunctionInnerScope(outerScope, functionDescriptor, trace);
196    
197            ExpressionTypingContext context = ExpressionTypingContext.newContext(
198                    trace, functionInnerScope, dataFlowInfo, NO_EXPECTED_TYPE
199            );
200            KotlinTypeInfo typeInfo = expressionTypingFacade.getTypeInfo(bodyExpression, context, function.hasBlockBody());
201    
202            KotlinType type = typeInfo.getType();
203            if (type != null) {
204                return type;
205            }
206            else {
207                return ErrorUtils.createErrorType("Error function type");
208            }
209        }
210    
211        /**
212         * Visits block statements propagating data flow information from the first to the last.
213         * Determines block returned type and data flow information at the end of the block AND
214         * at the nearest jump point from the block beginning.
215         */
216        /*package*/ KotlinTypeInfo getBlockReturnedTypeWithWritableScope(
217                @NotNull LexicalWritableScope scope,
218                @NotNull List<? extends KtElement> block,
219                @NotNull CoercionStrategy coercionStrategyForLastExpression,
220                @NotNull ExpressionTypingContext context
221        ) {
222            if (block.isEmpty()) {
223                return TypeInfoFactoryKt.createTypeInfo(expressionTypingComponents.builtIns.getUnitType(), context);
224            }
225    
226            ExpressionTypingInternals blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(
227                    expressionTypingComponents, annotationChecker, scope);
228            ExpressionTypingContext newContext = context.replaceScope(scope).replaceExpectedType(NO_EXPECTED_TYPE);
229    
230            KotlinTypeInfo result = TypeInfoFactoryKt.noTypeInfo(context);
231            // Jump point data flow info
232            DataFlowInfo beforeJumpInfo = newContext.dataFlowInfo;
233            boolean jumpOutPossible = false;
234            for (Iterator<? extends KtElement> iterator = block.iterator(); iterator.hasNext(); ) {
235                KtElement statement = iterator.next();
236                if (!(statement instanceof KtExpression)) {
237                    continue;
238                }
239                KtExpression statementExpression = (KtExpression) statement;
240                if (!iterator.hasNext()) {
241                    result = getTypeOfLastExpressionInBlock(
242                            statementExpression, newContext.replaceExpectedType(context.expectedType), coercionStrategyForLastExpression,
243                            blockLevelVisitor);
244                }
245                else {
246                    result = blockLevelVisitor
247                            .getTypeInfo(statementExpression, newContext.replaceContextDependency(ContextDependency.INDEPENDENT), true);
248                }
249    
250                DataFlowInfo newDataFlowInfo = result.getDataFlowInfo();
251                // If jump is not possible, we take new data flow info before jump
252                if (!jumpOutPossible) {
253                    beforeJumpInfo = result.getJumpFlowInfo();
254                    jumpOutPossible = result.getJumpOutPossible();
255                }
256                if (newDataFlowInfo != context.dataFlowInfo) {
257                    newContext = newContext.replaceDataFlowInfo(newDataFlowInfo);
258                    // We take current data flow info if jump there is not possible
259                }
260                blockLevelVisitor = new ExpressionTypingVisitorDispatcher.ForBlock(expressionTypingComponents, annotationChecker, scope);
261            }
262            return result.replaceJumpOutPossible(jumpOutPossible).replaceJumpFlowInfo(beforeJumpInfo);
263        }
264    
265        private KotlinTypeInfo getTypeOfLastExpressionInBlock(
266                @NotNull KtExpression statementExpression,
267                @NotNull ExpressionTypingContext context,
268                @NotNull CoercionStrategy coercionStrategyForLastExpression,
269                @NotNull ExpressionTypingInternals blockLevelVisitor
270        ) {
271            if (context.expectedType != NO_EXPECTED_TYPE) {
272                KotlinType expectedType;
273                if (context.expectedType == UNIT_EXPECTED_TYPE ||//the first check is necessary to avoid invocation 'isUnit(UNIT_EXPECTED_TYPE)'
274                    (coercionStrategyForLastExpression == COERCION_TO_UNIT && KotlinBuiltIns.isUnit(context.expectedType))) {
275                    expectedType = UNIT_EXPECTED_TYPE;
276                }
277                else {
278                    expectedType = context.expectedType;
279                }
280    
281                return blockLevelVisitor.getTypeInfo(statementExpression, context.replaceExpectedType(expectedType), true);
282            }
283            KotlinTypeInfo result = blockLevelVisitor.getTypeInfo(statementExpression, context, true);
284            if (coercionStrategyForLastExpression == COERCION_TO_UNIT) {
285                boolean mightBeUnit = false;
286                if (statementExpression instanceof KtDeclaration) {
287                    mightBeUnit = true;
288                }
289                if (statementExpression instanceof KtBinaryExpression) {
290                    KtBinaryExpression binaryExpression = (KtBinaryExpression) statementExpression;
291                    IElementType operationType = binaryExpression.getOperationToken();
292                    //noinspection SuspiciousMethodCalls
293                    if (operationType == KtTokens.EQ || OperatorConventions.ASSIGNMENT_OPERATIONS.containsKey(operationType)) {
294                        mightBeUnit = true;
295                    }
296                }
297                if (mightBeUnit) {
298                    // ExpressionTypingVisitorForStatements should return only null or Unit for declarations and assignments,
299                    // but (for correct assignment / initialization analysis) data flow info must be preserved
300                    assert result.getType() == null || KotlinBuiltIns.isUnit(result.getType());
301                    result = result.replaceType(expressionTypingComponents.builtIns.getUnitType());
302                }
303            }
304            return result;
305        }
306    
307    }