Parser: Do not produce JetQualifiedExpression without receiver

#KT-7122 Fixed
This commit is contained in:
Alexey Sedunov
2015-03-26 13:21:05 +03:00
parent cbcd2c3cce
commit 4ec1b9971f
14 changed files with 428 additions and 12 deletions
@@ -423,9 +423,13 @@ public class JetExpressionParsing extends AbstractJetParsing {
private void parsePostfixExpression() {
PsiBuilder.Marker expression = mark();
boolean firstExpressionParsed;
boolean doubleColonExpression = parseDoubleColonExpression();
if (!doubleColonExpression) {
parseAtomicExpression();
firstExpressionParsed = parseAtomicExpression();
}
else {
firstExpressionParsed = true;
}
while (true) {
@@ -439,19 +443,24 @@ public class JetExpressionParsing extends AbstractJetParsing {
else if (!doubleColonExpression && parseCallSuffix()) {
expression.done(CALL_EXPRESSION);
}
else if (at(DOT)) {
advance(); // DOT
else if (at(DOT) || at(SAFE_ACCESS)) {
IElementType expressionType = at(DOT) ? DOT_QUALIFIED_EXPRESSION : SAFE_ACCESS_EXPRESSION;
advance(); // DOT or SAFE_ACCESS
if (!firstExpressionParsed) {
expression.drop();
expression = mark();
}
parseCallExpression();
expression.done(DOT_QUALIFIED_EXPRESSION);
}
else if (at(SAFE_ACCESS)) {
advance(); // SAFE_ACCESS
parseCallExpression();
expression.done(SAFE_ACCESS_EXPRESSION);
if (firstExpressionParsed) {
expression.done(expressionType);
}
else {
firstExpressionParsed = true;
continue;
}
}
else if (atSet(Precedence.POSTFIX.getOperations())) {
parseOperationReference();
@@ -557,9 +566,11 @@ public class JetExpressionParsing extends AbstractJetParsing {
* : "package" // for the root package
* ;
*/
private void parseAtomicExpression() {
private boolean parseAtomicExpression() {
// System.out.println("atom at " + myBuilder.getTokenText());
boolean ok = true;
if (at(LPAR)) {
parseParenthesizedExpression();
}
@@ -625,9 +636,12 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseStringTemplate();
}
else if (!parseLiteralConstant()) {
ok = false;
// TODO: better recovery if FIRST(element) did not match
errorWithRecovery("Expecting an element", EXPRESSION_FOLLOW);
}
return ok;
}
/*
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>.test
}
@@ -0,0 +1,52 @@
JetFile: noQualifiedExpression.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>?.test
}
@@ -0,0 +1,52 @@
JetFile: noSafeQualifiedExpression.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(SAFE_ACCESS)('?.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>.test.test
}
@@ -0,0 +1,56 @@
JetFile: qualifiedExpressionWithSelector.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(DOT)('.')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>.test.<ff>
}
@@ -0,0 +1,61 @@
JetFile: qualifiedExpressionWithoutSelector.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(DOT)('.')
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('ff')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>?.test?.test
}
@@ -0,0 +1,56 @@
JetFile: safeQualifiedExpressionWithSelector.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(SAFE_ACCESS)('?.')
SAFE_ACCESS_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiElement(SAFE_ACCESS)('?.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -0,0 +1,3 @@
fun test() {
MyClass.<warning descr="">Companion</warning>?.test?.<ff>
}
@@ -0,0 +1,61 @@
JetFile: safeQualifiedExpressionWithoutSelector.kt
PACKAGE_DIRECTIVE
<empty list>
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
PsiElement(IDENTIFIER)('test')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
BLOCK
PsiElement(LBRACE)('{')
PsiWhiteSpace('\n ')
BINARY_EXPRESSION
BINARY_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('MyClass')
PsiElement(DOT)('.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('descr')
OPERATION_REFERENCE
PsiElement(EQ)('=')
BINARY_EXPRESSION
BINARY_EXPRESSION
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
OPERATION_REFERENCE
PsiElement(GT)('>')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Companion')
OPERATION_REFERENCE
PsiElement(LT)('<')
BINARY_EXPRESSION
BINARY_EXPRESSION
PsiErrorElement:Expecting an element
PsiElement(DIV)('/')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('warning')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiElement(SAFE_ACCESS)('?.')
SAFE_ACCESS_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('test')
PsiElement(SAFE_ACCESS)('?.')
PsiErrorElement:Expecting an element
PsiElement(LT)('<')
OPERATION_REFERENCE
PsiElement(IDENTIFIER)('ff')
PsiErrorElement:Expecting an element
PsiElement(GT)('>')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -1455,6 +1455,7 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
@TestDataPath("$PROJECT_ROOT")
@InnerTestClasses({
Recovery.Objects.class,
Recovery.QualifiedExpression.class,
})
@RunWith(JUnit3RunnerWithInners.class)
public static class Recovery extends AbstractJetParsingTest {
@@ -1798,6 +1799,51 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
}
}
}
@TestMetadata("compiler/testData/psi/recovery/qualifiedExpression")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class QualifiedExpression extends AbstractJetParsingTest {
public void testAllFilesPresentInQualifiedExpression() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/recovery/qualifiedExpression"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("noQualifiedExpression.kt")
public void testNoQualifiedExpression() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/noQualifiedExpression.kt");
doParsingTest(fileName);
}
@TestMetadata("noSafeQualifiedExpression.kt")
public void testNoSafeQualifiedExpression() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/noSafeQualifiedExpression.kt");
doParsingTest(fileName);
}
@TestMetadata("qualifiedExpressionWithSelector.kt")
public void testQualifiedExpressionWithSelector() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/qualifiedExpressionWithSelector.kt");
doParsingTest(fileName);
}
@TestMetadata("qualifiedExpressionWithoutSelector.kt")
public void testQualifiedExpressionWithoutSelector() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/qualifiedExpressionWithoutSelector.kt");
doParsingTest(fileName);
}
@TestMetadata("safeQualifiedExpressionWithSelector.kt")
public void testSafeQualifiedExpressionWithSelector() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/safeQualifiedExpressionWithSelector.kt");
doParsingTest(fileName);
}
@TestMetadata("safeQualifiedExpressionWithoutSelector.kt")
public void testSafeQualifiedExpressionWithoutSelector() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/recovery/qualifiedExpression/safeQualifiedExpressionWithoutSelector.kt");
doParsingTest(fileName);
}
}
}
@TestMetadata("compiler/testData/psi/script")