Parser: Do not produce qualified expressions without receiver in package directives. Add assertion on JetQualifiedExpression

#KT-6907 Fixed
This commit is contained in:
Alexey Sedunov
2015-03-05 14:49:29 +03:00
parent cab301e8e2
commit 2684ce20d4
25 changed files with 235 additions and 25 deletions
@@ -228,8 +228,16 @@ public class JetParsing extends AbstractJetParsing {
break;
}
if (at(DOT)) {
advance(); // DOT
qualifiedExpression.error("Package name must be a '.'-separated identifier list");
qualifiedExpression = mark();
continue;
}
PsiBuilder.Marker nsName = mark();
if (expect(IDENTIFIER, "Package name must be a '.'-separated identifier list", PACKAGE_NAME_RECOVERY_SET)) {
boolean simpleNameFound = expect(IDENTIFIER, "Package name must be a '.'-separated identifier list", PACKAGE_NAME_RECOVERY_SET);
if (simpleNameFound) {
nsName.done(REFERENCE_EXPRESSION);
}
else {
@@ -243,8 +251,15 @@ public class JetParsing extends AbstractJetParsing {
}
if (at(DOT)) {
simpleName = false;
advance(); // DOT
if (simpleName && !simpleNameFound) {
qualifiedExpression.drop();
qualifiedExpression = mark();
}
else {
simpleName = false;
}
}
else {
break;
@@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode
import org.jetbrains.kotlin.lexer.JetToken
import org.jetbrains.kotlin.lexer.JetTokens
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.psi.psiUtil.*
object JetQualifiedExpressionImpl {
public fun JetQualifiedExpression.getOperationTokenNode(): ASTNode {
@@ -31,20 +32,15 @@ object JetQualifiedExpressionImpl {
return this.getOperationTokenNode().getElementType() as JetToken
}
private fun JetQualifiedExpression.getExpression(afterOperation: Boolean): JetExpression? {
return getOperationTokenNode()?.getPsi()?.siblings(afterOperation, false)?.firstOrNull { it is JetExpression } as? JetExpression
}
public fun JetQualifiedExpression.getReceiverExpression(): JetExpression {
val left = PsiTreeUtil.findChildOfType(this, javaClass<JetExpression>())
return left!!
return getExpression(false) ?: throw AssertionError("No receiver found: ${JetPsiUtil.getElementTextWithContext(this)}")
}
public fun JetQualifiedExpression.getSelectorExpression(): JetExpression? {
var node: ASTNode? = getOperationTokenNode()
while (node != null) {
val psi = node!!.getPsi()
if (psi is JetExpression) {
return (psi as JetExpression)
}
node = node!!.getTreeNext()
}
return null
return getExpression(true)
}
}
@@ -0,0 +1 @@
package .a b
@@ -0,0 +1,18 @@
JetFile: PackageLeadingDotDoubleID.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiErrorElement:Expecting a top level declaration
<empty list>
@@ -0,0 +1 @@
package .a.b.c.
@@ -0,0 +1,19 @@
JetFile: PackageLongNameBetweenDots.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
DOT_QUALIFIED_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('c')
PsiElement(DOT)('.')
PsiErrorElement:Package name must be a '.'-separated identifier list placed on a single line
<empty list>
@@ -0,0 +1 @@
package a b
@@ -0,0 +1,16 @@
JetFile: PackageLongNameDoubleID.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiWhiteSpace(' ')
MODIFIER_LIST
ANNOTATION_ENTRY
CONSTRUCTOR_CALLEE
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiErrorElement:Expecting a top level declaration
<empty list>
@@ -0,0 +1 @@
package .a.b.c
@@ -0,0 +1,16 @@
JetFile: PackageLongNameLeadingDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
DOT_QUALIFIED_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('c')
@@ -0,0 +1 @@
package . .a.b.c
@@ -0,0 +1,19 @@
JetFile: PackageLongNameLeadingDoubleDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
DOT_QUALIFIED_EXPRESSION
DOT_QUALIFIED_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('c')
@@ -0,0 +1 @@
package . .
@@ -0,0 +1,11 @@
JetFile: PackageNameDoubleDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
PsiErrorElement:Package name must be a '.'-separated identifier list placed on a single line
<empty list>
@@ -0,0 +1 @@
package .
@@ -0,0 +1,8 @@
JetFile: PackageNameJustDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
PsiErrorElement:Package name must be a '.'-separated identifier list placed on a single line
<empty list>
@@ -0,0 +1 @@
package .a
@@ -0,0 +1,8 @@
JetFile: PackageSimpleNameLeadingDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
@@ -0,0 +1 @@
package . .a
@@ -0,0 +1,11 @@
JetFile: PackageSimpleNameLeadingDoubleDot.kt
PACKAGE_DIRECTIVE
PsiElement(package)('package')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
PsiWhiteSpace(' ')
PsiErrorElement:Package name must be a '.'-separated identifier list
PsiElement(DOT)('.')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
@@ -43,6 +43,7 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
Psi.FunctionReceivers.class,
Psi.GreatSyntacticShift.class,
Psi.Kdoc.class,
Psi.Packages.class,
Psi.PlatformTypesRecovery.class,
Psi.PropertyDelegate.class,
Psi.Recovery.class,
@@ -433,18 +434,6 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
doParsingTest(fileName);
}
@TestMetadata("PackageBlockFirst.kt")
public void testPackageBlockFirst() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/PackageBlockFirst.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageModifiers.kt")
public void testPackageModifiers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/PackageModifiers.kt");
doParsingTest(fileName);
}
@TestMetadata("ParameterNameMising.kt")
public void testParameterNameMising() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/ParameterNameMising.kt");
@@ -1200,6 +1189,81 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
}
}
@TestMetadata("compiler/testData/psi/packages")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Packages extends AbstractJetParsingTest {
public void testAllFilesPresentInPackages() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/psi/packages"), Pattern.compile("^(.*)\\.kts?$"), true);
}
@TestMetadata("PackageBlockFirst.kt")
public void testPackageBlockFirst() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageBlockFirst.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageLeadingDotDoubleID.kt")
public void testPackageLeadingDotDoubleID() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageLeadingDotDoubleID.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageLongNameBetweenDots.kt")
public void testPackageLongNameBetweenDots() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageLongNameBetweenDots.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageLongNameDoubleID.kt")
public void testPackageLongNameDoubleID() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageLongNameDoubleID.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageLongNameLeadingDot.kt")
public void testPackageLongNameLeadingDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageLongNameLeadingDot.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageLongNameLeadingDoubleDot.kt")
public void testPackageLongNameLeadingDoubleDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageLongNameLeadingDoubleDot.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageModifiers.kt")
public void testPackageModifiers() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageModifiers.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageNameDoubleDot.kt")
public void testPackageNameDoubleDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageNameDoubleDot.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageNameJustDot.kt")
public void testPackageNameJustDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageNameJustDot.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageSimpleNameLeadingDot.kt")
public void testPackageSimpleNameLeadingDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageSimpleNameLeadingDot.kt");
doParsingTest(fileName);
}
@TestMetadata("PackageSimpleNameLeadingDoubleDot.kt")
public void testPackageSimpleNameLeadingDoubleDot() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/packages/PackageSimpleNameLeadingDoubleDot.kt");
doParsingTest(fileName);
}
}
@TestMetadata("compiler/testData/psi/platformTypesRecovery")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)