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