diff --git a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java index 2c51919f8a1..7069b8651d4 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/AbstractJetParsing.java @@ -107,7 +107,8 @@ import static org.jetbrains.jet.lexer.JetTokens.*; } protected void skipUntil(TokenSet tokenSet) { - while (!eof() && !tokenSet.contains(tt())) { + boolean stopAtEolOrSemi = tokenSet.contains(EOL_OR_SEMICOLON); + while (!eof() && !tokenSet.contains(tt()) && !(stopAtEolOrSemi && at(EOL_OR_SEMICOLON))) { advance(); } } diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java index 653b9522a4b..061098d9098 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetParsing.java @@ -484,18 +484,19 @@ public class JetParsing extends AbstractJetParsing { parseAttributeList(); TokenSet propertyNameFollow = TokenSet.create(COLON, EQ, LBRACE, EOL_OR_SEMICOLON); - if (at(IDENTIFIER) && propertyNameFollow.contains(lookahead(1))) { + if (at(IDENTIFIER) && propertyNameFollow.contains(lookahead(1))) { // There's no explicit receiver specified // val [a] name = foo receiverTypeAttributes.done(RECEIVER_TYPE_ATTRIBUTES); advance(); // IDENTIFIER } - else { - receiverTypeAttributes.rollbackTo(); + else { // There must be an explicit receiver + receiverTypeAttributes.rollbackTo(); // Attributes are a part of the receiver type if (!TYPE_REF_FIRST.contains(tt())) { - errorAndAdvance("Expecting receiver type or property name"); + errorUntil("Expecting receiver type or property name", propertyNameFollow); } else { - // TODO: if this type is annotated with an attribute, and it is a single identifier, it is a error (fun [a] foo()) + // TODO: if this type is annotated with an attribute, and it is a single identifier, + // TODO: it is NOT an error (fun [a] foo()) -- annotation on receiver parseTypeRef(); // The property name may appear as the last section of the type if (at(DOT)) { @@ -520,7 +521,12 @@ public class JetParsing extends AbstractJetParsing { // TODO: review // TODO: $field = foo or something like this - parsePropertyGetterOrSetter(); + if (at(RBRACE)) { + error("Expecting a getter and/or setter"); + } + else { + parsePropertyGetterOrSetter(); + } if (!at(RBRACE)) parsePropertyGetterOrSetter(); if (!at(RBRACE)) { @@ -591,7 +597,7 @@ public class JetParsing extends AbstractJetParsing { myExpressionParsing.parseExpression(); } else { - error("Expecting function body"); + errorAndAdvance("Expecting function body"); } } @@ -812,6 +818,7 @@ public class JetParsing extends AbstractJetParsing { parseAttributeList(); + TokenSet simpleTypeFirst = TokenSet.create(IDENTIFIER, LBRACE, LPAR); while (true) { if (at(IDENTIFIER)) { parseSimpleUserType(); @@ -826,7 +833,12 @@ public class JetParsing extends AbstractJetParsing { } if (!at(DOT)) break; - advance(); // DOT + if (simpleTypeFirst.contains(lookahead(1))) { + advance(); // DOT + } else { + break; + // TODO: ERROR here? + } } type.done(TYPE_REFERENCE); } diff --git a/idea/testData/psi/Decomposers_ERR.jet b/idea/testData/psi/Decomposers_ERR.jet index 317cb3908a6..8454e8d9f5c 100644 --- a/idea/testData/psi/Decomposers_ERR.jet +++ b/idea/testData/psi/Decomposers_ERR.jet @@ -8,3 +8,6 @@ decomposer foobar([a]) decomposer (a, a). decomposer (). decomposer foo.{() : ()}.bar(a, a). + + +decomposer foo.bar.-() \ No newline at end of file diff --git a/idea/testData/psi/Decomposers_ERR.txt b/idea/testData/psi/Decomposers_ERR.txt index 83777aa0d96..eb17f6dcc53 100644 --- a/idea/testData/psi/Decomposers_ERR.txt +++ b/idea/testData/psi/Decomposers_ERR.txt @@ -174,4 +174,20 @@ JetFile: Decomposers_ERR.jet PsiElement(IDENTIFIER)('a') PsiElement(RPAR)(')') PsiErrorElement:Expecting namespace or top level declaration - PsiElement(DOT)('.') \ No newline at end of file + PsiElement(DOT)('.') + PsiWhiteSpace('\n\n\n') + DECOMPOSER + PsiElement(decomposer)('decomposer') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('foo') + PsiElement(DOT)('.') + USER_TYPE + PsiElement(IDENTIFIER)('bar') + PsiElement(DOT)('.') + PsiErrorElement:Expecting decomposer name + PsiElement(MINUS)('-') + DECOMPOSER_PROPERTY_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') \ No newline at end of file diff --git a/idea/testData/psi/Properties_ERR.jet b/idea/testData/psi/Properties_ERR.jet index 5065b4aab7e..89253464d48 100644 --- a/idea/testData/psi/Properties_ERR.jet +++ b/idea/testData/psi/Properties_ERR.jet @@ -1,3 +1,6 @@ +var - f = s +var - f {} +var - f : val foo : val [a foo = foo val foo.bar. @@ -15,3 +18,8 @@ val foo.bar.{() : ()}.foo = foo { set() {} set() {} } +val f.d.- = f + +val foo { + get() - +} \ No newline at end of file diff --git a/idea/testData/psi/Properties_ERR.txt b/idea/testData/psi/Properties_ERR.txt index 39c04171280..26db2f39ed4 100644 --- a/idea/testData/psi/Properties_ERR.txt +++ b/idea/testData/psi/Properties_ERR.txt @@ -1,5 +1,43 @@ JetFile: Properties_ERR.jet NAMESPACE + PROPERTY + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting receiver type or property name + PsiElement(MINUS)('-') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('s') + PsiWhiteSpace('\n') + PROPERTY + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting receiver type or property name + PsiElement(MINUS)('-') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') + PsiWhiteSpace(' ') + PsiElement(LBRACE)('{') + PsiErrorElement:Expecting a getter and/or setter + + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PROPERTY + PsiElement(var)('var') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting receiver type or property name + PsiElement(MINUS)('-') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') + PsiWhiteSpace(' ') + PsiElement(COLON)(':') + PsiWhiteSpace('\n') + TYPE_REFERENCE + PsiErrorElement:Type expected + PROPERTY PsiElement(val)('val') PsiWhiteSpace(' ') @@ -40,9 +78,9 @@ JetFile: Properties_ERR.jet PsiElement(DOT)('.') USER_TYPE PsiElement(IDENTIFIER)('bar') - PsiElement(DOT)('.') - PsiErrorElement:Type expected - + PsiElement(DOT)('.') + PsiErrorElement:Expecting property name + PsiWhiteSpace('\n') PROPERTY PsiElement(val)('val') @@ -222,4 +260,41 @@ JetFile: Properties_ERR.jet PsiElement(RBRACE)('}') PsiWhiteSpace('\n') PsiErrorElement:Expecting namespace or top level declaration + PsiElement(RBRACE)('}') + PsiWhiteSpace('\n') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + TYPE_REFERENCE + USER_TYPE + PsiElement(IDENTIFIER)('f') + PsiElement(DOT)('.') + USER_TYPE + PsiElement(IDENTIFIER)('d') + PsiElement(DOT)('.') + PsiErrorElement:Expecting property name + PsiElement(MINUS)('-') + PsiWhiteSpace(' ') + PsiElement(EQ)('=') + PsiWhiteSpace(' ') + PsiElement(IDENTIFIER)('f') + PsiWhiteSpace('\n\n') + PROPERTY + PsiElement(val)('val') + PsiWhiteSpace(' ') + RECEIVER_TYPE_ATTRIBUTES + + PsiElement(IDENTIFIER)('foo') + PsiWhiteSpace(' ') + PsiElement(LBRACE)('{') + PsiWhiteSpace('\n ') + PROPERTY_GETTER + PsiElement(get)('get') + VALUE_PARAMETER_LIST + PsiElement(LPAR)('(') + PsiElement(RPAR)(')') + PsiWhiteSpace(' ') + PsiErrorElement:Expecting function body + PsiElement(MINUS)('-') + PsiWhiteSpace('\n') PsiElement(RBRACE)('}') \ No newline at end of file