mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
fix stub-ast mismatch caused by broken import list
plus add a test for mismatch in IDEA-169118
This commit is contained in:
@@ -147,37 +147,41 @@ public class FileParser {
|
||||
private Pair<PsiBuilder.Marker, Boolean> parseImportList(PsiBuilder builder, Predicate<PsiBuilder> stopper) {
|
||||
PsiBuilder.Marker list = builder.mark();
|
||||
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
boolean isEmpty = tokenType != JavaTokenType.IMPORT_KEYWORD && tokenType != JavaTokenType.SEMICOLON;
|
||||
if (!isEmpty) {
|
||||
PsiBuilder.Marker invalidElements = null;
|
||||
while (!builder.eof()) {
|
||||
if (stopper.test(builder)) {
|
||||
break;
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.SEMICOLON) {
|
||||
builder.advanceLexer();
|
||||
continue;
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker statement = parseImportStatement(builder);
|
||||
if (statement != null) {
|
||||
if (invalidElements != null) {
|
||||
invalidElements.errorBefore(JavaErrorMessages.message("unexpected.token"), statement);
|
||||
invalidElements = null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invalidElements == null) {
|
||||
invalidElements = builder.mark();
|
||||
}
|
||||
boolean isEmpty = true;
|
||||
PsiBuilder.Marker invalidElements = null;
|
||||
while (!builder.eof()) {
|
||||
if (stopper.test(builder)) {
|
||||
break;
|
||||
}
|
||||
else if (builder.getTokenType() == JavaTokenType.SEMICOLON) {
|
||||
builder.advanceLexer();
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(JavaErrorMessages.message("unexpected.token"));
|
||||
final PsiBuilder.Marker statement = parseImportStatement(builder);
|
||||
if (statement != null) {
|
||||
isEmpty = false;
|
||||
if (invalidElements != null) {
|
||||
invalidElements.errorBefore(JavaErrorMessages.message("unexpected.token"), statement);
|
||||
invalidElements = null;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (invalidElements == null) {
|
||||
invalidElements = builder.mark();
|
||||
}
|
||||
builder.advanceLexer();
|
||||
}
|
||||
|
||||
if (invalidElements != null) {
|
||||
invalidElements.error(JavaErrorMessages.message("unexpected.token"));
|
||||
}
|
||||
|
||||
if (isEmpty) {
|
||||
PsiBuilder.Marker precede = list.precede();
|
||||
list.rollbackTo();
|
||||
list = precede;
|
||||
}
|
||||
|
||||
done(list, JavaElementType.IMPORT_LIST);
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:ImportBrokenFromBeginning.java
|
||||
PsiImportList
|
||||
PsiErrorElement:Unexpected token
|
||||
PsiIdentifier:xx('xx')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiImportStatement
|
||||
PsiKeyword:import('import')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:a
|
||||
PsiIdentifier:a('a')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
@@ -38,6 +38,7 @@ public class FileParserTest extends JavaParsingTestCase {
|
||||
public void testUnclosedImport1() { doParserTest("import java.awt.*"); }
|
||||
public void testUnclosedImport2() { doParserTest("import java.awt."); }
|
||||
public void testUnclosedImport3() { doParserTest("import static a"); }
|
||||
public void testImportBrokenFromBeginning() { doParserTest("xx import a;"); }
|
||||
|
||||
public void testExtraSemicolons() {
|
||||
doParserTest(
|
||||
|
||||
@@ -19,15 +19,21 @@ import com.intellij.codeInsight.AnnotationTargetUtil
|
||||
import com.intellij.codeInspection.dataFlow.ControlFlowAnalyzer
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.application.ReadAction
|
||||
import com.intellij.openapi.command.WriteCommandAction
|
||||
import com.intellij.psi.PsiAnnotationMethod
|
||||
import com.intellij.psi.PsiClassType
|
||||
import com.intellij.psi.PsiDocumentManager
|
||||
import com.intellij.psi.PsiJavaFile
|
||||
import com.intellij.psi.PsiReferenceExpression
|
||||
import com.intellij.psi.SyntaxTraverser
|
||||
import com.intellij.psi.impl.source.PsiClassImpl
|
||||
import com.intellij.psi.impl.source.PsiFileImpl
|
||||
import com.intellij.psi.impl.source.tree.TreeUtil
|
||||
import com.intellij.psi.search.GlobalSearchScope
|
||||
import com.intellij.psi.search.searches.AnnotatedElementsSearch
|
||||
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||
import com.intellij.psi.util.PsiUtil
|
||||
import com.intellij.testFramework.PsiTestUtil
|
||||
import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase
|
||||
|
||||
import java.util.concurrent.Callable
|
||||
@@ -173,4 +179,29 @@ import java.lang.annotation.*;
|
||||
assert !((PsiFileImpl) cls.containingFile).contentsLoaded
|
||||
}
|
||||
|
||||
void "test breaking and adding import does not cause stub AST mismatch"() {
|
||||
def file = myFixture.addFileToProject("a.java", "import foo.*; import bar.*; class Foo {}") as PsiJavaFile
|
||||
def another = myFixture.addClass("package zoo; public class Another {}")
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
file.viewProvider.document.insertString(file.text.indexOf('import'), 'x')
|
||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||
file.importClass(another)
|
||||
}
|
||||
PsiTestUtil.checkStubsMatchText(file)
|
||||
}
|
||||
|
||||
void "test adding type before method call does not cause stub AST mismatch"() {
|
||||
def file = myFixture.addFileToProject("a.java", """
|
||||
class Foo {
|
||||
void foo() {
|
||||
something();
|
||||
call();
|
||||
}
|
||||
}
|
||||
""") as PsiJavaFile
|
||||
WriteCommandAction.runWriteCommandAction(project) {
|
||||
file.viewProvider.document.insertString(file.text.indexOf('call'), 'char ')
|
||||
PsiTestUtil.checkStubsMatchText(file)
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user