diff --git a/idea/src/org/jetbrains/jet/JetNodeTypes.java b/idea/src/org/jetbrains/jet/JetNodeTypes.java index a45b5bdb187..f49633f2c05 100644 --- a/idea/src/org/jetbrains/jet/JetNodeTypes.java +++ b/idea/src/org/jetbrains/jet/JetNodeTypes.java @@ -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); diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java index 3168d1b3be8..a7cbbb246ef 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBlockExpression.java @@ -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 getStatements() { + return Arrays.asList(findChildrenByClass(JetExpression.class)); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetCatchSection.java b/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java similarity index 90% rename from idea/src/org/jetbrains/jet/lang/psi/JetCatchSection.java rename to idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java index f4de230cdc3..e5111042758 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetCatchSection.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetCatchClause.java @@ -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); } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java b/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java index 833c1d69500..dba15d21eaa 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetTryExpression.java @@ -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 getCatchClauses() { + return findChildrenByType(JetNodeTypes.CATCH); + } + + @Nullable + public JetFinallySection getFinallyBlock() { + return (JetFinallySection) findChildByType(JetNodeTypes.FINALLY); + } } diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java index 5dc3e611369..48a3d46695d 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetVisitor.java @@ -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) { diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index 4d2fac687a8..05309938192 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -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 expressions = new ArrayList(); collectAllReturnTypes(expression, scope, expressions); result[0] = commonSupertype(expressions); } + @Override + public void visitTryExpression(JetTryExpression expression) { + JetExpression tryBlock = expression.getTryBlock(); + List catchClauses = expression.getCatchClauses(); + JetFinallySection finallyBlock = expression.getFinallyBlock(); + List types = new ArrayList(); + 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 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 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 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) { diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index e8fd6fb279f..ff5e8972264 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -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");