mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
add tests for syntax tree with java
GitOrigin-RevId: 1f347798e068d7dc8db136613eeb685badbc7fab
This commit is contained in:
committed by
intellij-monorepo-bot
parent
0755892c18
commit
467abf483d
@@ -37,6 +37,7 @@ jvm_library(
|
||||
"//java/testFramework/shared",
|
||||
"//platform/syntax/syntax-psi:psi",
|
||||
"//java/java-syntax:syntax",
|
||||
"//platform/syntax/syntax-tree:tree",
|
||||
],
|
||||
exports = [
|
||||
"@lib//:easymock",
|
||||
|
||||
@@ -28,5 +28,6 @@
|
||||
<orderEntry type="module" module-name="intellij.java.testFramework.shared" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.syntax.psi" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.java.syntax" scope="TEST" />
|
||||
<orderEntry type="module" module-name="intellij.platform.syntax.tree" scope="TEST" />
|
||||
</component>
|
||||
</module>
|
||||
+44
-1
@@ -8,8 +8,11 @@ import com.intellij.lang.LanguageExtension;
|
||||
import com.intellij.lang.java.JavaLanguage;
|
||||
import com.intellij.lang.java.JavaParserDefinition;
|
||||
import com.intellij.lang.java.parser.BasicJavaParserUtil;
|
||||
import com.intellij.openapi.extensions.ExtensionPointName;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.platform.backend.workspace.WorkspaceModelTopics;
|
||||
import com.intellij.platform.syntax.psi.LanguageSyntaxDefinitions;
|
||||
import com.intellij.platform.syntax.tree.SyntaxNode;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.impl.DebugUtil;
|
||||
@@ -17,11 +20,14 @@ import com.intellij.testFramework.ParsingTestCase;
|
||||
import com.intellij.testFramework.TestDataFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
||||
public abstract class AbstractBasicJavaParsingTestCase extends ParsingTestCase {
|
||||
|
||||
private final AbstractBasicJavaParsingTestConfigurator myConfigurator;
|
||||
private SyntaxNode myKmpTree;
|
||||
|
||||
@SuppressWarnings("JUnitTestCaseWithNonTrivialConstructors")
|
||||
public AbstractBasicJavaParsingTestCase(String dataPath, AbstractBasicJavaParsingTestConfigurator configurator) {
|
||||
@@ -50,6 +56,14 @@ public abstract class AbstractBasicJavaParsingTestCase extends ParsingTestCase {
|
||||
addExplicitExtension(collector, language, object);
|
||||
}
|
||||
|
||||
public final <T> void addExplicit(@NotNull ExtensionPointName<T> extensionPointName, @NotNull T extension) {
|
||||
registerExtension(extensionPointName, extension);
|
||||
}
|
||||
|
||||
public final <T> void addExtensionPoint(@NotNull ExtensionPointName<T> extensionPointName, @NotNull Class<T> extensionClass) {
|
||||
super.registerExtensionPoint(extensionPointName, extensionClass);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PsiFile createFile(@NotNull String name, @NotNull String text) {
|
||||
PsiFile file = super.createFile(name, text);
|
||||
@@ -81,13 +95,42 @@ public abstract class AbstractBasicJavaParsingTestCase extends ParsingTestCase {
|
||||
}
|
||||
|
||||
String treeDump = DebugUtil.nodeTreeAsElementTypeToString(file.getNode(), !skipSpaces()).trim();
|
||||
doCheckResult(myFullDataPath, targetDataName + "_node.txt", treeDump);
|
||||
assertSameLinesWithFile(getExpectedFileName(targetDataName), treeDump);
|
||||
|
||||
checkKmpTree(targetDataName);
|
||||
}
|
||||
|
||||
private void checkKmpTree(@NotNull String targetDataName) {
|
||||
String kmpTreeDump = JavaTestSyntaxParsingUtil.dumpTree(myKmpTree);
|
||||
|
||||
String expectedFileName = getExpectedFileName(targetDataName);
|
||||
String expectedText;
|
||||
try {
|
||||
expectedText = FileUtil.loadFile(new File(expectedFileName), StandardCharsets.UTF_8);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
String normalizedExpected = JavaTestSyntaxParsingUtil.removeEmptyListLines(expectedText);
|
||||
assertSameLines(normalizedExpected, kmpTreeDump);
|
||||
}
|
||||
|
||||
private @NotNull String getExpectedFileName(@NotNull String targetDataName) {
|
||||
return myFullDataPath + File.separatorChar + targetDataName + "_node.txt";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @NotNull PsiFile parseFile(@NotNull String name, @NotNull String text) {
|
||||
myKmpTree = myConfigurator.createFileSyntaxNode(text, null);
|
||||
return super.parseFile(name, text);
|
||||
}
|
||||
|
||||
protected void doParserTest(@NotNull String text,
|
||||
BasicJavaParserUtil.@NotNull ParserWrapper parser) {
|
||||
String name = getTestName(false);
|
||||
myFile = myConfigurator.createPsiFile(this, name, text, parser);
|
||||
myKmpTree = myConfigurator.createFileSyntaxNode(text, parser);
|
||||
try {
|
||||
checkResult(name, myFile);
|
||||
}
|
||||
|
||||
+10
@@ -2,9 +2,11 @@
|
||||
package com.intellij.java.parser;
|
||||
|
||||
import com.intellij.lang.java.parser.BasicJavaParserUtil;
|
||||
import com.intellij.platform.syntax.tree.SyntaxNode;
|
||||
import com.intellij.pom.java.LanguageLevel;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public interface AbstractBasicJavaParsingTestConfigurator {
|
||||
void setUp(@NotNull AbstractBasicJavaParsingTestCase thinJavaParsingTestCase);
|
||||
@@ -17,6 +19,14 @@ public interface AbstractBasicJavaParsingTestConfigurator {
|
||||
@NotNull String text,
|
||||
@NotNull BasicJavaParserUtil.ParserWrapper parser);
|
||||
|
||||
/**
|
||||
* @param text text to parse
|
||||
* @param parserWrapper parser to use or `null` if we want to parse the whole file
|
||||
* @return SyntaxNode node representing the parsed content
|
||||
*/
|
||||
@NotNull
|
||||
SyntaxNode createFileSyntaxNode(@NotNull String text, @Nullable BasicJavaParserUtil.ParserWrapper parserWrapper);
|
||||
|
||||
boolean checkPsi();
|
||||
|
||||
void setLanguageLevel(@NotNull LanguageLevel level);
|
||||
|
||||
+21
-1
@@ -2,15 +2,19 @@
|
||||
package com.intellij.java.parser
|
||||
|
||||
import com.intellij.ide.highlighter.JavaFileType
|
||||
import com.intellij.java.syntax.JavaSyntaxDefinition
|
||||
import com.intellij.java.syntax.element.JavaLanguageLevelProvider
|
||||
import com.intellij.lang.ASTNode
|
||||
import com.intellij.lang.LanguageASTFactory
|
||||
import com.intellij.lang.java.JavaLanguage
|
||||
import com.intellij.lang.java.parser.BasicJavaParserUtil
|
||||
import com.intellij.lang.java.parser.JavaParserUtil
|
||||
import com.intellij.lang.java.syntax.JavaElementTypeConverterExtension
|
||||
import com.intellij.openapi.extensions.ExtensionPointName
|
||||
import com.intellij.platform.syntax.SyntaxElementType
|
||||
import com.intellij.platform.syntax.parser.SyntaxTreeBuilder
|
||||
import com.intellij.platform.syntax.psi.*
|
||||
import com.intellij.platform.syntax.tree.SyntaxNode
|
||||
import com.intellij.pom.java.LanguageLevel
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.impl.source.PsiJavaFileImpl
|
||||
@@ -36,8 +40,12 @@ abstract class JavaParsingTestConfiguratorBase(
|
||||
testCase.addExplicit(languageASTFactory, java, JavaASTFactory())
|
||||
testCase.clearCachesOfLanguageExtension(java, languageASTFactory)
|
||||
}
|
||||
}
|
||||
|
||||
ExtensionPointName<JavaLanguageLevelProvider>("com.intellij.java.syntax.languageLevelProvider").let { ep ->
|
||||
testCase.addExtensionPoint(ep, JavaLanguageLevelProvider::class.java)
|
||||
testCase.addExplicit(ep, JavaLanguageLevelProvider { this.languageLevel })
|
||||
}
|
||||
}
|
||||
|
||||
override fun setLanguageLevel(level: LanguageLevel) {
|
||||
this.level = level
|
||||
@@ -52,6 +60,18 @@ abstract class JavaParsingTestConfiguratorBase(
|
||||
ourLanguageLevel = languageLevel
|
||||
}
|
||||
|
||||
override fun createFileSyntaxNode(text: String, parserWrapper: BasicJavaParserUtil.ParserWrapper?): SyntaxNode {
|
||||
ourLanguageLevel = languageLevel
|
||||
return parseForSyntaxTree(text) { builder ->
|
||||
if (parserWrapper != null) {
|
||||
parseWithWrapper(builder, parserWrapper)
|
||||
}
|
||||
else {
|
||||
JavaSyntaxDefinition.parse(ourLanguageLevel, builder)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun createPsiFile(
|
||||
thinJavaParsingTestCase: AbstractBasicJavaParsingTestCase,
|
||||
name: String,
|
||||
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
|
||||
@file:JvmName("JavaTestSyntaxParsingUtil")
|
||||
|
||||
package com.intellij.java.parser
|
||||
|
||||
import com.intellij.java.syntax.JavaSyntaxDefinition
|
||||
import com.intellij.platform.syntax.parser.SyntaxTreeBuilder
|
||||
import com.intellij.platform.syntax.tree.KmpSyntaxNode
|
||||
|
||||
import com.intellij.platform.syntax.tree.SyntaxNode
|
||||
import com.intellij.platform.syntax.tree.children
|
||||
import com.intellij.platform.syntax.tree.parse
|
||||
import com.intellij.platform.syntax.util.language.SyntaxElementLanguageProvider
|
||||
|
||||
internal fun parseForSyntaxTree(
|
||||
text: String,
|
||||
parser: ((SyntaxTreeBuilder) -> Unit),
|
||||
): KmpSyntaxNode {
|
||||
val mapper = SyntaxElementLanguageProvider {
|
||||
sequenceOf(JavaSyntaxDefinition.language)
|
||||
}
|
||||
|
||||
val tree = parse(
|
||||
text = text,
|
||||
lexerFactory = JavaSyntaxDefinition::createLexer,
|
||||
parser = parser,
|
||||
whitespaces = JavaSyntaxDefinition.whitespaces,
|
||||
comments = JavaSyntaxDefinition.comments,
|
||||
languageMapper = mapper,
|
||||
cancellationProvider = null,
|
||||
logger = null,
|
||||
whitespaceOrCommentBindingPolicy = JavaSyntaxDefinition.whitespaceOrCommentBindingPolicy,
|
||||
)
|
||||
|
||||
return tree
|
||||
}
|
||||
|
||||
internal fun dumpTree(node: SyntaxNode): String {
|
||||
val all = mutableListOf<SyntaxNode>()
|
||||
|
||||
fun append(node: SyntaxNode) {
|
||||
all.add(node)
|
||||
for (child in node.children()) {
|
||||
append(child)
|
||||
}
|
||||
}
|
||||
append(node)
|
||||
|
||||
val parsing = all.joinToString("\n") { node ->
|
||||
val type = node.type
|
||||
val prefix = " ".repeat((node.level()) * 2)
|
||||
"$prefix$type"
|
||||
}
|
||||
return parsing
|
||||
}
|
||||
|
||||
private fun SyntaxNode.level(): Int = generateSequence(this) { it.parent() }.count() - 1
|
||||
|
||||
/**
|
||||
* remove `<empty list>` lines from the expected tree
|
||||
* kmp tree cannot have them because "composite/non-composite" node information is missing in the KMP tree
|
||||
*/
|
||||
internal fun String.removeEmptyListLines(): String =
|
||||
lines()
|
||||
.filterNot { it.trim() == "<empty list>" }
|
||||
.joinToString("\n")
|
||||
Reference in New Issue
Block a user