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.types.expressions;
018
019 import org.jetbrains.annotations.NotNull;
020 import org.jetbrains.annotations.Nullable;
021 import org.jetbrains.jet.lang.PlatformToKotlinClassMap;
022 import org.jetbrains.jet.lang.psi.*;
023 import org.jetbrains.jet.lang.resolve.BindingContext;
024 import org.jetbrains.jet.lang.resolve.BindingContextUtils;
025 import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
026 import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
027 import org.jetbrains.jet.lang.types.DeferredType;
028 import org.jetbrains.jet.lang.types.ErrorUtils;
029 import org.jetbrains.jet.lang.types.JetTypeInfo;
030 import org.jetbrains.jet.util.lazy.ReenteringLazyValueComputationException;
031
032 import static org.jetbrains.jet.lang.diagnostics.Errors.TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM;
033
034 public class ExpressionTypingVisitorDispatcher extends JetVisitor<JetTypeInfo, ExpressionTypingContext> implements ExpressionTypingInternals {
035
036 @Override
037 public JetTypeInfo visitIdeTemplate(JetIdeTemplate expression, ExpressionTypingContext data) {
038 return basic.visitIdeTemplate(expression, data);
039 }
040
041 @NotNull
042 public static ExpressionTypingFacade create(@NotNull PlatformToKotlinClassMap platformToKotlinClassMap) {
043 return new ExpressionTypingVisitorDispatcher(platformToKotlinClassMap, null);
044 }
045
046 @NotNull
047 public static ExpressionTypingInternals createForBlock(
048 @NotNull PlatformToKotlinClassMap platformToKotlinClassMap,
049 @NotNull WritableScope writableScope
050 ) {
051 return new ExpressionTypingVisitorDispatcher(platformToKotlinClassMap, writableScope);
052 }
053
054 private final BasicExpressionTypingVisitor basic;
055 private final ExpressionTypingVisitorForStatements statements;
056 private final ClosureExpressionsTypingVisitor closures = new ClosureExpressionsTypingVisitor(this);
057 private final ControlStructureTypingVisitor controlStructures = new ControlStructureTypingVisitor(this);
058 private final PatternMatchingTypingVisitor patterns = new PatternMatchingTypingVisitor(this);
059
060 private ExpressionTypingVisitorDispatcher(PlatformToKotlinClassMap platformToKotlinClassMap, WritableScope writableScope) {
061 this.basic = new BasicExpressionTypingVisitor(this, platformToKotlinClassMap);
062 if (writableScope != null) {
063 this.statements = new ExpressionTypingVisitorForStatements(this, writableScope, basic, controlStructures, patterns);
064 }
065 else {
066 this.statements = null;
067 }
068 }
069
070 @NotNull
071 @Override
072 public JetTypeInfo checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @Nullable JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
073 return basic.checkInExpression(callElement, operationSign, left, right, context);
074 }
075
076 @Override
077 @NotNull
078 public final JetTypeInfo safeGetTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
079 JetTypeInfo typeInfo = getTypeInfo(expression, context);
080 if (typeInfo.getType() != null) {
081 return typeInfo;
082 }
083 return JetTypeInfo.create(ErrorUtils.createErrorType("Type for " + expression.getText()), context.dataFlowInfo);
084 }
085
086 @Override
087 @NotNull
088 public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context) {
089 return getTypeInfo(expression, context, this);
090 }
091
092 @Override
093 @NotNull
094 public final JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, boolean isStatement) {
095 if (!isStatement) return getTypeInfo(expression, context);
096 if (statements != null) {
097 return getTypeInfo(expression, context, statements);
098 }
099 return getTypeInfo(expression, context, createStatementVisitor(context));
100 }
101
102 private ExpressionTypingVisitorForStatements createStatementVisitor(ExpressionTypingContext context) {
103 return new ExpressionTypingVisitorForStatements(this, ExpressionTypingUtils.newWritableScopeImpl(context, "statement scope"), basic, controlStructures, patterns);
104 }
105
106 @Override
107 public void checkStatementType(@NotNull JetExpression expression, ExpressionTypingContext context) {
108 expression.accept(createStatementVisitor(context), context);
109 }
110
111 @NotNull
112 private JetTypeInfo getTypeInfo(@NotNull JetExpression expression, ExpressionTypingContext context, JetVisitor<JetTypeInfo, ExpressionTypingContext> visitor) {
113 JetTypeInfo recordedTypeInfo = BindingContextUtils.getRecordedTypeInfo(expression, context.trace.getBindingContext());
114 if (recordedTypeInfo != null) {
115 return recordedTypeInfo;
116 }
117 JetTypeInfo result;
118 try {
119 result = expression.accept(visitor, context);
120 // Some recursive definitions (object expressions) must put their types in the cache manually:
121 if (context.trace.get(BindingContext.PROCESSED, expression)) {
122 return JetTypeInfo.create(context.trace.getBindingContext().get(BindingContext.EXPRESSION_TYPE, expression),
123 result.getDataFlowInfo());
124 }
125
126 if (result.getType() instanceof DeferredType) {
127 result = JetTypeInfo.create(((DeferredType) result.getType()).getActualType(), result.getDataFlowInfo());
128 }
129 if (result.getType() != null) {
130 context.trace.record(BindingContext.EXPRESSION_TYPE, expression, result.getType());
131 }
132
133 }
134 catch (ReenteringLazyValueComputationException e) {
135 context.trace.report(TYPECHECKER_HAS_RUN_INTO_RECURSIVE_PROBLEM.on(expression));
136 result = JetTypeInfo.create(null, context.dataFlowInfo);
137 }
138
139 if (!context.trace.get(BindingContext.PROCESSED, expression) && !BindingContextUtils.isExpressionWithValidReference(expression, context.trace.getBindingContext())) {
140 context.trace.record(BindingContext.RESOLUTION_SCOPE, expression, context.scope);
141 }
142 context.trace.record(BindingContext.PROCESSED, expression);
143 if (result.getDataFlowInfo() != DataFlowInfo.EMPTY) {
144 context.trace.record(BindingContext.EXPRESSION_DATA_FLOW_INFO, expression, result.getDataFlowInfo());
145 }
146 return result;
147 }
148
149 //////////////////////////////////////////////////////////////////////////////////////////////
150
151 @Override
152 public JetTypeInfo visitFunctionLiteralExpression(JetFunctionLiteralExpression expression, ExpressionTypingContext data) {
153 return expression.accept(closures, data);
154 }
155
156 @Override
157 public JetTypeInfo visitObjectLiteralExpression(JetObjectLiteralExpression expression, ExpressionTypingContext data) {
158 return expression.accept(closures, data);
159 }
160
161 //////////////////////////////////////////////////////////////////////////////////////////////
162
163 @Override
164 public JetTypeInfo visitThrowExpression(JetThrowExpression expression, ExpressionTypingContext data) {
165 return expression.accept(controlStructures, data);
166 }
167
168 @Override
169 public JetTypeInfo visitReturnExpression(JetReturnExpression expression, ExpressionTypingContext data) {
170 return expression.accept(controlStructures, data);
171 }
172
173 @Override
174 public JetTypeInfo visitContinueExpression(JetContinueExpression expression, ExpressionTypingContext data) {
175 return expression.accept(controlStructures, data);
176 }
177
178 @Override
179 public JetTypeInfo visitIfExpression(JetIfExpression expression, ExpressionTypingContext data) {
180 return expression.accept(controlStructures, data);
181 }
182
183 @Override
184 public JetTypeInfo visitTryExpression(JetTryExpression expression, ExpressionTypingContext data) {
185 return expression.accept(controlStructures, data);
186 }
187
188 @Override
189 public JetTypeInfo visitForExpression(JetForExpression expression, ExpressionTypingContext data) {
190 return expression.accept(controlStructures, data);
191 }
192
193 @Override
194 public JetTypeInfo visitWhileExpression(JetWhileExpression expression, ExpressionTypingContext data) {
195 return expression.accept(controlStructures, data);
196 }
197
198 @Override
199 public JetTypeInfo visitDoWhileExpression(JetDoWhileExpression expression, ExpressionTypingContext data) {
200 return expression.accept(controlStructures, data);
201 }
202
203 @Override
204 public JetTypeInfo visitBreakExpression(JetBreakExpression expression, ExpressionTypingContext data) {
205 return expression.accept(controlStructures, data);
206 }
207
208 //////////////////////////////////////////////////////////////////////////////////////////////
209
210 @Override
211 public JetTypeInfo visitIsExpression(JetIsExpression expression, ExpressionTypingContext data) {
212 return expression.accept(patterns, data);
213 }
214
215 @Override
216 public JetTypeInfo visitWhenExpression(JetWhenExpression expression, ExpressionTypingContext data) {
217 return expression.accept(patterns, data);
218 }
219
220 //////////////////////////////////////////////////////////////////////////////////////////////
221
222 @Override
223 public JetTypeInfo visitJetElement(JetElement element, ExpressionTypingContext data) {
224 return element.accept(basic, data);
225 }
226 }