Typing for try-expression
This commit is contained in:
@@ -82,7 +82,7 @@ public interface JetNodeTypes {
|
||||
JetNodeType THEN = new JetNodeType("THEN", JetContainerNode.class);
|
||||
JetNodeType ELSE = new JetNodeType("ELSE", JetContainerNode.class);
|
||||
JetNodeType TRY = new JetNodeType("TRY", JetTryExpression.class);
|
||||
JetNodeType CATCH = new JetNodeType("CATCH", JetCatchSection.class);
|
||||
JetNodeType CATCH = new JetNodeType("CATCH", JetCatchClause.class);
|
||||
JetNodeType FINALLY = new JetNodeType("FINALLY", JetFinallySection.class);
|
||||
JetNodeType FOR = new JetNodeType("FOR", JetForExpression.class);
|
||||
JetNodeType WHILE = new JetNodeType("WHILE", JetWhileExpression.class);
|
||||
|
||||
@@ -3,6 +3,9 @@ package org.jetbrains.jet.lang.psi;
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
@@ -15,4 +18,8 @@ public class JetBlockExpression extends JetExpression {
|
||||
public void accept(JetVisitor visitor) {
|
||||
visitor.visitBlockExpression(this);
|
||||
}
|
||||
|
||||
public List<JetExpression> getStatements() {
|
||||
return Arrays.asList(findChildrenByClass(JetExpression.class));
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -10,8 +10,8 @@ import java.util.List;
|
||||
/**
|
||||
* @author max
|
||||
*/
|
||||
public class JetCatchSection extends JetElement {
|
||||
public JetCatchSection(@NotNull ASTNode node) {
|
||||
public class JetCatchClause extends JetElement {
|
||||
public JetCatchClause(@NotNull ASTNode node) {
|
||||
super(node);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,10 @@ package org.jetbrains.jet.lang.psi;
|
||||
|
||||
import com.intellij.lang.ASTNode;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.JetNodeTypes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author max
|
||||
@@ -16,9 +20,19 @@ public class JetTryExpression extends JetExpression {
|
||||
visitor.visitTryExpression(this);
|
||||
}
|
||||
|
||||
public JetExpression getBody() {
|
||||
return findChildByClass(JetExpression.class);
|
||||
@NotNull
|
||||
public JetExpression getTryBlock() {
|
||||
return (JetExpression) findChildByType(JetNodeTypes.BLOCK);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public List<JetCatchClause> getCatchClauses() {
|
||||
return findChildrenByType(JetNodeTypes.CATCH);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetFinallySection getFinallyBlock() {
|
||||
return (JetFinallySection) findChildByType(JetNodeTypes.FINALLY);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -250,8 +250,8 @@ public class JetVisitor extends PsiElementVisitor {
|
||||
visitExpression(expression);
|
||||
}
|
||||
|
||||
public void visitCatchSection(JetCatchSection catchSection) {
|
||||
visitJetElement(catchSection);
|
||||
public void visitCatchSection(JetCatchClause catchClause) {
|
||||
visitJetElement(catchClause);
|
||||
}
|
||||
|
||||
public void visitFinallySection(JetFinallySection finallySection) {
|
||||
|
||||
@@ -18,8 +18,6 @@ public class JetTypeChecker {
|
||||
public static final JetTypeChecker INSTANCE = new JetTypeChecker();
|
||||
|
||||
/*
|
||||
: if
|
||||
: when
|
||||
: try
|
||||
|
||||
: SimpleName
|
||||
@@ -133,13 +131,30 @@ public class JetTypeChecker {
|
||||
|
||||
@Override
|
||||
public void visitWhenExpression(JetWhenExpression expression) {
|
||||
// TODO : what if there're sub-whens?
|
||||
// TODO : what if there's "else continue"?
|
||||
// TODO :change scope according to the bound value in the when header
|
||||
List<Type> expressions = new ArrayList<Type>();
|
||||
collectAllReturnTypes(expression, scope, expressions);
|
||||
result[0] = commonSupertype(expressions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTryExpression(JetTryExpression expression) {
|
||||
JetExpression tryBlock = expression.getTryBlock();
|
||||
List<JetCatchClause> catchClauses = expression.getCatchClauses();
|
||||
JetFinallySection finallyBlock = expression.getFinallyBlock();
|
||||
List<Type> types = new ArrayList<Type>();
|
||||
if (finallyBlock == null) {
|
||||
for (JetCatchClause catchClause : catchClauses) {
|
||||
// TODO: change scope here
|
||||
types.add(getType(scope, catchClause.getCatchBody()));
|
||||
}
|
||||
} else {
|
||||
types.add(getType(scope, finallyBlock.getFinalExpression()));
|
||||
}
|
||||
types.add(getType(scope, tryBlock));
|
||||
result[0] = commonSupertype(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTupleExpression(JetTupleExpression expression) {
|
||||
List<JetExpression> entries = expression.getEntries();
|
||||
@@ -151,6 +166,17 @@ public class JetTypeChecker {
|
||||
result[0] = JetStandardClasses.getTupleType(types);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBlockExpression(JetBlockExpression expression) {
|
||||
// TODO : this is a stub, consider function literals
|
||||
List<JetExpression> statements = expression.getStatements();
|
||||
if (statements.isEmpty()) {
|
||||
result[0] = JetStandardClasses.getUnitType();
|
||||
} else {
|
||||
result[0] = getType(scope, statements.get(statements.size() - 1));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitJetElement(JetElement elem) {
|
||||
throw new IllegalArgumentException("Unsupported element: " + elem);
|
||||
@@ -161,8 +187,9 @@ public class JetTypeChecker {
|
||||
|
||||
private void collectAllReturnTypes(JetWhenExpression whenExpression, JetScope scope, List<Type> result) {
|
||||
for (JetWhenEntry entry : whenExpression.getEntries()) {
|
||||
if (entry.getSubWhen() != null) {
|
||||
collectAllReturnTypes(entry.getSubWhen(), scope, result);
|
||||
JetWhenExpression subWhen = entry.getSubWhen();
|
||||
if (subWhen != null) {
|
||||
collectAllReturnTypes(subWhen, scope, result);
|
||||
} else {
|
||||
JetExpression resultExpression = entry.getExpression();
|
||||
if (resultExpression != null) {
|
||||
|
||||
@@ -99,6 +99,15 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
|
||||
assertType("when (1) { is 1 => 2; is 1 => '2'; is 1 => when(e) {is 1 => null}} ", "Any?");
|
||||
}
|
||||
|
||||
public void testTry() throws Exception {
|
||||
assertType("try {1} finally{2}", "Int");
|
||||
assertType("try {1} catch (e : e) {'a'} finally{2}", "Int");
|
||||
assertType("try {1} catch (e : e) {'a'} finally{'2'}", "Any");
|
||||
assertType("try {1} catch (e : e) {'a'}", "Any");
|
||||
assertType("try {1} catch (e : e) {'a'} catch (e : e) {null}", "Any?");
|
||||
assertType("try {} catch (e : e) {}", "Unit");
|
||||
}
|
||||
|
||||
public void testCommonSupertypes() throws Exception {
|
||||
assertCommonSupertype("Int", "Int", "Int");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user