Parser: Do not produce qualified expressions without receiver in package directives. Add assertion on JetQualifiedExpression
#KT-6907 Fixed
This commit is contained in:
@@ -228,8 +228,16 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (at(DOT)) {
|
||||||
|
advance(); // DOT
|
||||||
|
qualifiedExpression.error("Package name must be a '.'-separated identifier list");
|
||||||
|
qualifiedExpression = mark();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
PsiBuilder.Marker nsName = mark();
|
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);
|
nsName.done(REFERENCE_EXPRESSION);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -243,8 +251,15 @@ public class JetParsing extends AbstractJetParsing {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (at(DOT)) {
|
if (at(DOT)) {
|
||||||
simpleName = false;
|
|
||||||
advance(); // DOT
|
advance(); // DOT
|
||||||
|
|
||||||
|
if (simpleName && !simpleNameFound) {
|
||||||
|
qualifiedExpression.drop();
|
||||||
|
qualifiedExpression = mark();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
simpleName = false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import com.intellij.lang.ASTNode
|
|||||||
import org.jetbrains.kotlin.lexer.JetToken
|
import org.jetbrains.kotlin.lexer.JetToken
|
||||||
import org.jetbrains.kotlin.lexer.JetTokens
|
import org.jetbrains.kotlin.lexer.JetTokens
|
||||||
import com.intellij.psi.util.PsiTreeUtil
|
import com.intellij.psi.util.PsiTreeUtil
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
|
|
||||||
object JetQualifiedExpressionImpl {
|
object JetQualifiedExpressionImpl {
|
||||||
public fun JetQualifiedExpression.getOperationTokenNode(): ASTNode {
|
public fun JetQualifiedExpression.getOperationTokenNode(): ASTNode {
|
||||||
@@ -31,20 +32,15 @@ object JetQualifiedExpressionImpl {
|
|||||||
return this.getOperationTokenNode().getElementType() as JetToken
|
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 {
|
public fun JetQualifiedExpression.getReceiverExpression(): JetExpression {
|
||||||
val left = PsiTreeUtil.findChildOfType(this, javaClass<JetExpression>())
|
return getExpression(false) ?: throw AssertionError("No receiver found: ${JetPsiUtil.getElementTextWithContext(this)}")
|
||||||
return left!!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public fun JetQualifiedExpression.getSelectorExpression(): JetExpression? {
|
public fun JetQualifiedExpression.getSelectorExpression(): JetExpression? {
|
||||||
var node: ASTNode? = getOperationTokenNode()
|
return getExpression(true)
|
||||||
while (node != null) {
|
|
||||||
val psi = node!!.getPsi()
|
|
||||||
if (psi is JetExpression) {
|
|
||||||
return (psi as JetExpression)
|
|
||||||
}
|
|
||||||
node = node!!.getTreeNext()
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.FunctionReceivers.class,
|
||||||
Psi.GreatSyntacticShift.class,
|
Psi.GreatSyntacticShift.class,
|
||||||
Psi.Kdoc.class,
|
Psi.Kdoc.class,
|
||||||
|
Psi.Packages.class,
|
||||||
Psi.PlatformTypesRecovery.class,
|
Psi.PlatformTypesRecovery.class,
|
||||||
Psi.PropertyDelegate.class,
|
Psi.PropertyDelegate.class,
|
||||||
Psi.Recovery.class,
|
Psi.Recovery.class,
|
||||||
@@ -433,18 +434,6 @@ public class JetParsingTestGenerated extends AbstractJetParsingTest {
|
|||||||
doParsingTest(fileName);
|
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")
|
@TestMetadata("ParameterNameMising.kt")
|
||||||
public void testParameterNameMising() throws Exception {
|
public void testParameterNameMising() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/psi/ParameterNameMising.kt");
|
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")
|
@TestMetadata("compiler/testData/psi/platformTypesRecovery")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
|
|||||||
Reference in New Issue
Block a user