diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index 9f6affc057d..cf288bc56de 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -1425,9 +1425,29 @@ public class JetExpressionParsing extends AbstractJetParsing { PsiBuilder.Marker catchBlock = mark(); advance(); // CATCH_KEYWORD - myJetParsing.parseValueParameterList(false, TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD)); + TokenSet recoverySet = TokenSet.create(LBRACE, FINALLY_KEYWORD, CATCH_KEYWORD); + if (atSet(recoverySet)) { + error("Expecting exception variable declaration"); + } + else { + PsiBuilder.Marker parameters = mark(); + expect(LPAR, "Expecting '('", recoverySet); + if (!atSet(recoverySet)) { + myJetParsing.parseValueParameter(); + expect(RPAR, "Expecting ')'", recoverySet); + } + else { + error("Expecting exception variable declaration"); + } + parameters.done(VALUE_PARAMETER_LIST); + } - myJetParsing.parseBlock(); + if (at(LBRACE)) { + myJetParsing.parseBlock(); + } + else { + error("Expecting a block: { ... }"); + } catchBlock.done(CATCH); } diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java index d63f9dc663d..7ad2cd9ced8 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -1702,7 +1702,7 @@ public class JetParsing extends AbstractJetParsing { return parseValueParameter(true); } - private void parseValueParameter() { + public void parseValueParameter() { parseValueParameter(false); } diff --git a/compiler/testData/psi/TryRecovery.jet b/compiler/testData/psi/TryRecovery.jet new file mode 100644 index 00000000000..0bde1af86fb --- /dev/null +++ b/compiler/testData/psi/TryRecovery.jet @@ -0,0 +1,61 @@ +fun testOpenParens() { + try { + } catch { + } + + try { + } catch ( { + } + + try { + } catch (e: { + } + + try { + } catch (e: Exception { + } +} + +fun testClosedParens() { + try { + } catch () { + } + + try { + } catch (e) { + } + + try { + } catch (e:) { + } + + try { + } catch (e: Exception) { + } + + try { + } catch (: Exception) { + } + + try { + } catch (:) { + } + +} + +fun testFinally() { + try { + } catch + finally { + } + + try { + } catch () + finally { + } + + try { + } catch (e : Exception) + finally { + } +} \ No newline at end of file diff --git a/compiler/testData/psi/TryRecovery.txt b/compiler/testData/psi/TryRecovery.txt new file mode 100644 index 00000000000..7c09b2ad61e --- /dev/null +++ b/compiler/testData/psi/TryRecovery.txt @@ -0,0 +1,374 @@ +JetFile: TryRecovery.jet + NAMESPACE_HEADER + + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('testOpenParens') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiErrorElement:Expecting exception variable declaration + + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiErrorElement:Expecting exception variable declaration + + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + PsiErrorElement:Type expected + + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Exception') + PsiErrorElement:Expecting ')' + + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('testClosedParens') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Parameter name expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiErrorElement:Parameters must have type annotation + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiElement(COLON)(':') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Exception') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Parameter name expected + + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Exception') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Parameter name expected + + PsiElement(COLON)(':') + TYPE_REFERENCE + PsiErrorElement:Type expected + + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n') + FUN + PsiElement(fun)('fun') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('testFinally') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiErrorElement:Expecting exception variable declaration + + PsiWhiteSpace('\n ') + FINALLY + PsiElement(finally)('finally') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiErrorElement:Parameter name expected + + PsiElement(RPAR)(')') + PsiErrorElement:Expecting a block: { ... } + + PsiWhiteSpace('\n ') + FINALLY + PsiElement(finally)('finally') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n\n ') + TRY + PsiElement(try)('try') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace(' ') + CATCH + PsiElement(catch)('catch') + PsiWhiteSpace(' ') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + VALUE_PARAMETER + PsiElement(IDENTIFIER)('e') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + REFERENCE_EXPRESSION + PsiElement(IDENTIFIER)('Exception') + PsiElement(RPAR)(')') + PsiErrorElement:Expecting a block: { ... } + + PsiWhiteSpace('\n ') + FINALLY + PsiElement(finally)('finally') + PsiWhiteSpace(' ') + BLOCK + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PsiElement(RBRACE)('}') \ No newline at end of file