[textmate] reimplement lexer tests in kotlin and drop parameterize tests as they are not supported in KMP

GitOrigin-RevId: 7f90ebfe80d989b43da77ed563f6be5f7ec9f491
This commit is contained in:
Alexander Zolotov
2025-04-29 13:56:11 +02:00
committed by intellij-monorepo-bot
parent bdb57fa6d7
commit bf56aa7372
35 changed files with 486 additions and 552 deletions

View File

@@ -3,10 +3,12 @@ package org.jetbrains.plugins.textmate
import org.jetbrains.annotations.NonNls
import org.jetbrains.plugins.textmate.bundles.*
import org.jetbrains.plugins.textmate.bundles.BundleType.Companion.detectBundleType
import org.jetbrains.plugins.textmate.language.syntax.TextMateSyntaxTableBuilder
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
import org.jetbrains.plugins.textmate.plist.JsonOrXmlPlistReader
import org.jetbrains.plugins.textmate.plist.JsonPlistReader
import org.jetbrains.plugins.textmate.plist.PlistReaderCore
import org.jetbrains.plugins.textmate.plist.XmlPlistReaderForTests
object TestUtil {
const val BAT: @NonNls String = "bat"
@@ -58,4 +60,42 @@ object TestUtil {
fun scopeFromString(scopeString: String): TextMateScope {
return scopeString.split(' ').dropLastWhile { it.isEmpty() }.fold(TextMateScope.EMPTY) { acc, i -> acc.add(i) }
}
fun TextMateSyntaxTableBuilder.loadBundle(bundleName: String): Map<TextMateFileNameMatcher, CharSequence> {
val matchers = mutableMapOf<TextMateFileNameMatcher, CharSequence>()
val grammars = readBundle(bundleName, XmlPlistReaderForTests()).readGrammars().iterator()
while (grammars.hasNext()) {
val grammar = grammars.next()
addSyntax(grammar.plist.value)?.let { rootScope ->
grammar.fileNameMatchers.forEach { matcher ->
matchers[matcher] = rootScope
}
}
}
return matchers
}
fun findScopeByFileName(
matchers: Map<TextMateFileNameMatcher, CharSequence>,
fileName: String,
): CharSequence {
return matchers[TextMateFileNameMatcher.Name(fileName)] ?: run {
fileNameExtensions(fileName).firstNotNullOf { extension ->
matchers[TextMateFileNameMatcher.Extension(extension.toString())]
}
}
}
private fun fileNameExtensions(fileName: CharSequence): Sequence<CharSequence> {
return generateSequence(fileNameExtension(fileName)) { s ->
fileNameExtension(s)
}
}
private fun fileNameExtension(fileName: CharSequence): CharSequence? {
return when(val i = fileName.indexOf('.')) {
-1 -> null
else -> fileName.subSequence(i + 1, fileName.length).ifEmpty { null }
}
}
}

View File

@@ -0,0 +1,29 @@
text.blog.markdown;meta.header.blog;keyword.other.blog: [0, 5], {Title}
text.blog.markdown;meta.header.blog;punctuation.separator.key-value.blog: [5, 6], {:}
text.blog.markdown;meta.header.blog: [6, 7], { }
text.blog.markdown;meta.header.blog;string.unquoted.blog: [7, 15], {untitled}
text.blog.markdown;meta.header.blog: [15, 16], {
}
text.blog.markdown;text.html.markdown: [16, 17], {
}
text.blog.markdown;text.html.markdown;meta.paragraph.markdown: [17, 22], {Main }
text.blog.markdown;text.html.markdown;meta.paragraph.markdown;markup.italic.markdown;punctuation.definition.italic.markdown: [22, 23], {_}
text.blog.markdown;text.html.markdown;meta.paragraph.markdown;markup.italic.markdown: [23, 28], {entry}
text.blog.markdown;text.html.markdown;meta.paragraph.markdown;markup.italic.markdown;punctuation.definition.italic.markdown: [28, 29], {_}
text.blog.markdown;text.html.markdown;meta.paragraph.markdown: [29, 35], { text
}
text.blog.markdown;text.html.markdown: [35, 36], {
}
text.blog.markdown;text.html.markdown;meta.separator.blog: [36, 107], {✂------✂------✂------✂------✂------✂------✂------✂------✂------✂------
}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;punctuation.definition.list.markdown: [107, 108], {*}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown: [108, 109], { }
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;meta.paragraph.markdown: [109, 122], {Первый пункт
}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;punctuation.definition.list.markdown: [122, 123], {*}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown: [123, 124], { }
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;meta.paragraph.markdown: [124, 137], {Второй пункт
}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;punctuation.definition.list.markdown: [137, 138], {*}
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown: [138, 139], { }
text.blog.markdown;text.html.markdown;markup.list.unnumbered.markdown;meta.paragraph.markdown: [139, 151], {Третий пункт}

View File

@@ -1,44 +0,0 @@
package org.jetbrains.plugins.textmate
import org.jetbrains.plugins.textmate.bundles.TextMateFileNameMatcher
import org.jetbrains.plugins.textmate.language.syntax.TextMateSyntaxTableBuilder
import org.jetbrains.plugins.textmate.plist.XmlPlistReader
fun TextMateSyntaxTableBuilder.loadBundle(bundleName: String): Map<TextMateFileNameMatcher, CharSequence> {
val matchers = HashMap<TextMateFileNameMatcher, CharSequence>()
val grammars = TestUtil.readBundle(bundleName, XmlPlistReader()).readGrammars().iterator()
while (grammars.hasNext()) {
val grammar = grammars.next()
addSyntax(grammar.plist.value)?.let { rootScope ->
grammar.fileNameMatchers.forEach { matcher ->
matchers[matcher] = rootScope
}
}
}
return matchers
}
fun findScopeByFileName(
matchers: Map<TextMateFileNameMatcher, CharSequence>,
fileName: String,
): CharSequence {
return matchers[TextMateFileNameMatcher.Name(fileName)] ?: run {
fileNameExtensions(fileName).firstNotNullOf { extension ->
matchers[TextMateFileNameMatcher.Extension(extension.toString())]
}
}
}
private fun fileNameExtensions(fileName: CharSequence): Sequence<CharSequence> {
return generateSequence(fileNameExtension(fileName)) { s ->
fileNameExtension(s)
}
}
private fun fileNameExtension(fileName: CharSequence): CharSequence? {
return when(val i = fileName.indexOf('.')) {
-1 -> null
else -> fileName.subSequence(i + 1, fileName.length).ifEmpty { null }
}
}

View File

@@ -1,4 +1,4 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer
package org.jetbrains.plugins.textmate.language.syntax
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
@@ -7,13 +7,15 @@ import com.intellij.testFramework.UsefulTestCase
import com.intellij.textmate.joni.JoniRegexFactory
import com.intellij.tools.ide.metrics.benchmark.Benchmark
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.findScopeByFileName
import org.jetbrains.plugins.textmate.TestUtil.findScopeByFileName
import org.jetbrains.plugins.textmate.TestUtil.loadBundle
import org.jetbrains.plugins.textmate.language.TextMateConcurrentMapInterner
import org.jetbrains.plugins.textmate.language.TextMateLanguageDescriptor
import org.jetbrains.plugins.textmate.language.syntax.TextMateSyntaxTableBuilder
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateCachingSyntaxMatcher
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateHighlightingLexer
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateSyntaxMatcherImpl
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorCachingWeigher
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorWeigherImpl
import org.jetbrains.plugins.textmate.loadBundle
import org.jetbrains.plugins.textmate.regex.CachingRegexFactory
import org.jetbrains.plugins.textmate.regex.RememberingLastMatchRegexFactory
import java.io.File

View File

@@ -0,0 +1,101 @@
package org.jetbrains.plugins.textmate.language.syntax
import com.intellij.lexer.Lexer
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.tree.IElementType
import com.intellij.testFramework.PlatformTestUtil
import com.intellij.testFramework.UsefulTestCase
import com.intellij.textmate.joni.JoniRegexFactory
import junit.framework.TestCase.assertNotNull
import org.jetbrains.plugins.textmate.TestUtil.findScopeByFileName
import org.jetbrains.plugins.textmate.TestUtil.loadBundle
import org.jetbrains.plugins.textmate.language.TextMateConcurrentMapInterner
import org.jetbrains.plugins.textmate.language.TextMateLanguageDescriptor
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateCachingSyntaxMatcher
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateElementType
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateHighlightingLexer
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateScope
import org.jetbrains.plugins.textmate.language.syntax.lexer.TextMateSyntaxMatcherImpl
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorCachingWeigher
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorWeigherImpl
import org.jetbrains.plugins.textmate.regex.CachingRegexFactory
import org.jetbrains.plugins.textmate.regex.RegexFactory
import org.jetbrains.plugins.textmate.regex.RememberingLastMatchRegexFactory
import java.io.File
import java.nio.charset.StandardCharsets
abstract class TextMateLexerTestCase {
private val TEST_DATA_BASE_DIR: String = "${PlatformTestUtil.getCommunityPath()}/plugins/textmate/testData/lexer"
fun doTest(beforePath: String, afterPath: String) {
val beforeFile = File(TEST_DATA_BASE_DIR, "$testDirRelativePath/$beforePath")
val afterFile = File(TEST_DATA_BASE_DIR, "$testDirRelativePath/$afterPath")
val syntaxTableBuilder = TextMateSyntaxTableBuilder(TextMateConcurrentMapInterner())
val matchers = syntaxTableBuilder.loadBundle(bundleName)
for (bundleName in extraBundleNames) {
syntaxTableBuilder.loadBundle(bundleName)
}
val syntaxTable = syntaxTableBuilder.build()
val rootScope = findScopeByFileName(matchers, beforeFile.name)
assertNotNull("scope is empty for file name: " + beforeFile.name, rootScope)
val sourceData = StringUtil.convertLineSeparators(FileUtil.loadFile(beforeFile, StandardCharsets.UTF_8))
val text = sourceData.replace("$(\\n+)".toRegex(), "")
val regexFactory: RegexFactory = CachingRegexFactory(RememberingLastMatchRegexFactory(JoniRegexFactory()))
val weigher = TextMateSelectorCachingWeigher(TextMateSelectorWeigherImpl())
val syntaxMatcher = TextMateCachingSyntaxMatcher(TextMateSyntaxMatcherImpl(regexFactory, weigher))
val lexer: Lexer = TextMateHighlightingLexer(TextMateLanguageDescriptor(rootScope, syntaxTable.getSyntax(rootScope)),
syntaxMatcher,
-1)
val output = buildString {
lexer.start(text)
while (lexer.getTokenType() != null) {
val startIndex = lexer.getTokenStart()
val endIndex = lexer.getTokenEnd()
val tokenType: IElementType = lexer.getTokenType()!!
val str = "${getTokenTypePresentation(tokenType)}: [$startIndex, $endIndex], {${text.substring(startIndex, endIndex)}}\n"
append(str)
lexer.advance()
}
}.trim { it <= ' ' }
UsefulTestCase.assertSameLinesWithFile(afterFile.path, output)
}
private fun getTokenTypePresentation(tokenType: IElementType): String? {
return if (tokenType is TextMateElementType) {
val scope = tokenType.scope
buildString {
val scopeName: CharSequence? = scope.scopeName
if (scopeName != null) {
append(scopeName)
}
var parent: TextMateScope? = scope.parent
while (parent != null) {
val parentScopeName: CharSequence? = parent.scopeName
if (parentScopeName != null) {
if (!isEmpty()) {
insert(0, ";")
}
insert(0, parentScopeName)
}
parent = parent.parent
}
}.trim { it <= ' ' }
}
else {
tokenType.toString()
}
}
abstract val testDirRelativePath: String
abstract val bundleName: String
open val extraBundleNames: List<String> = emptyList()
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class BatLexerTest extends LexerTestCase {
class BatLexerTest : TextMateLexerTestCase() {
@Test
fun bat() = doTest("bat.bat_hack", "bat_after.bat_hack")
@Override
protected String getTestDirRelativePath() {
return "bat";
}
@Override
protected String getBundleName() {
return TestUtil.BAT;
}
override val testDirRelativePath = "bat"
override val bundleName = TestUtil.BAT
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class ColdFusionLexerTest extends LexerTestCase {
class ColdFusionLexerTest : TextMateLexerTestCase() {
@Test
fun coldfusion() = doTest("coldfusion.cfm", "coldfusion_after.cfm")
@Override
protected String getTestDirRelativePath() {
return "coldfusion";
}
@Override
protected String getBundleName() {
return TestUtil.COLD_FUSION;
}
override val testDirRelativePath = "coldfusion"
override val bundleName = TestUtil.COLD_FUSION
}

View File

@@ -1,14 +1,12 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
public class CppLexerTest extends LexerTestCase {
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
@Override
protected String getTestDirRelativePath() {
return "cpp";
}
class CppLexerTest : TextMateLexerTestCase() {
@Test
fun test() = doTest("test.cc", "test_after.cc")
@Override
protected String getBundleName() {
return "cpp";
}
override val testDirRelativePath = "cpp"
override val bundleName = "cpp"
}

View File

@@ -1,15 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class DockerLexerTest extends LexerTestCase {
@Override
protected String getBundleName() {
return TestUtil.DOCKER;
}
class DockerLexerTest : TextMateLexerTestCase() {
@Test
fun dockerfile() = doTest("Dockerfile", "Dockerfile_after")
@Override
protected String getTestDirRelativePath() {
return "docker_vsc";
}
override val testDirRelativePath = "docker_vsc"
override val bundleName = TestUtil.DOCKER
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class ElixirLexerTest extends LexerTestCase {
class ElixirLexerTest : TextMateLexerTestCase() {
@Test
fun simpletest() = doTest("simpleTest.ex", "simpleTest_after.ex")
@Override
protected String getTestDirRelativePath() {
return "elixir";
}
@Override
protected String getBundleName() {
return TestUtil.ELIXIR;
}
override val testDirRelativePath = TestUtil.ELIXIR
override val bundleName = "elixir"
}

View File

@@ -1,23 +1,14 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Arrays;
import java.util.List;
class FSharpLexerTest : TextMateLexerTestCase() {
@Test
fun test() = doTest("test.fs", "test_after.fs")
public class FSharpLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "fsharp";
}
@Override
protected String getBundleName() {
return TestUtil.FSHARP;
}
@Override
protected List<String> getExtraBundleNames() {
return Arrays.asList(TestUtil.HTML_VSC, TestUtil.MARKDOWN_VSC);
}
override val testDirRelativePath = "fsharp"
override val bundleName = TestUtil.FSHARP
override val extraBundleNames = listOf(TestUtil.HTML_VSC, TestUtil.MARKDOWN_VSC)
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.junit.jupiter.api.Test
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
public class GitLexerTest extends LexerTestCase {
class GitLexerTest : TextMateLexerTestCase() {
@Test
fun commitEDITMSG() = doTest("COMMIT_EDITMSG", "COMMIT_EDITMSG_after")
@Override
protected String getTestDirRelativePath() {
return "git";
}
@Override
protected String getBundleName() {
return TestUtil.GIT;
}
override val testDirRelativePath = "git"
override val bundleName = TestUtil.GIT
}

View File

@@ -1,13 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
class GoLexerTest : LexerTestCase() {
override fun getTestDirRelativePath(): String {
return "go"
}
class GoLexerTest : TextMateLexerTestCase() {
@Test
fun test() = doTest("test.go", "test_after.go")
override fun getBundleName(): String {
return TestUtil.GO
}
override val testDirRelativePath = "go"
override val bundleName = TestUtil.GO
}

View File

@@ -1,23 +1,17 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Collections;
import java.util.List;
class HtmlVscLexerTest : TextMateLexerTestCase() {
@Test
fun doctype() = doTest("doctype.html", "doctype_after.html")
public class HtmlVscLexerTest extends LexerTestCase {
@Override
protected String getBundleName() {
return TestUtil.HTML_VSC;
}
@Test
fun htmlCss() = doTest("html_css.html", "html_css_after.html")
@Override
protected List<String> getExtraBundleNames() {
return Collections.singletonList(TestUtil.CSS_VSC);
}
@Override
protected String getTestDirRelativePath() {
return "html_vsc";
}
override val testDirRelativePath = "html_vsc"
override val bundleName = TestUtil.HTML_VSC
override val extraBundleNames = listOf(TestUtil.CSS_VSC)
}

View File

@@ -1,16 +1,16 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.junit.jupiter.api.Test
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
public class JavaLexerTest extends LexerTestCase {
class JavaLexerTest : TextMateLexerTestCase() {
@Test
fun javaUnicodeLiteral() = doTest("java_unicode_literal.java", "java_unicode_literal_after.java")
@Override
protected String getTestDirRelativePath() {
return "java";
}
@Test
fun java() = doTest("java.java", "java_after.java")
@Override
protected String getBundleName() {
return TestUtil.JAVA;
}
override val testDirRelativePath = "java"
override val bundleName = TestUtil.JAVA
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class LatexLexerTest extends LexerTestCase {
class LatexLexerTest : TextMateLexerTestCase() {
@Test
fun text() = doTest("text.tex", "text_after.tex")
@Override
protected String getTestDirRelativePath() {
return "latex";
}
@Override
protected String getBundleName() {
return TestUtil.LATEX;
}
override val testDirRelativePath = "latex"
override val bundleName = TestUtil.LATEX
}

View File

@@ -1,145 +0,0 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
import com.intellij.lexer.Lexer;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.tree.IElementType;
import com.intellij.testFramework.PlatformTestUtil;
import com.intellij.testFramework.UsefulTestCase;
import com.intellij.textmate.joni.JoniRegexFactory;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.textmate.TestUtilKt;
import org.jetbrains.plugins.textmate.language.TextMateConcurrentMapInterner;
import org.jetbrains.plugins.textmate.language.TextMateLanguageDescriptor;
import org.jetbrains.plugins.textmate.language.syntax.TextMateSyntaxTableCore;
import org.jetbrains.plugins.textmate.language.syntax.TextMateSyntaxTableBuilder;
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorCachingWeigher;
import org.jetbrains.plugins.textmate.language.syntax.selector.TextMateSelectorWeigherImpl;
import org.jetbrains.plugins.textmate.regex.CachingRegexFactory;
import org.jetbrains.plugins.textmate.regex.RegexFactory;
import org.jetbrains.plugins.textmate.regex.RememberingLastMatchRegexFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import java.io.File;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Collections;
import java.util.List;
import static com.intellij.openapi.util.io.FileUtilRt.getExtension;
@RunWith(com.intellij.testFramework.Parameterized.class)
abstract public class LexerTestCase extends UsefulTestCase {
private static final String TEST_DATA_BASE_DIR =
PlatformTestUtil.getCommunityPath() + "/plugins/textmate/testData/lexer";
private CharSequence myRootScope;
private @NotNull TextMateSyntaxTableCore mySyntaxTable;
@Parameterized.Parameter
public String myFileName;
@Parameterized.Parameter(1)
public File myFile;
@Parameterized.Parameters(name = "{0}")
public static List<Object[]> params() {
return Collections.emptyList();
}
@com.intellij.testFramework.Parameterized.Parameters(name = "{0}")
public static Iterable<Object[]> createData(Class<?> klass) throws Throwable {
LexerTestCase testCase = (LexerTestCase)klass.getDeclaredConstructor().newInstance();
File testDir = new File(FileUtil.join(TEST_DATA_BASE_DIR, testCase.getTestDirRelativePath()));
File[] files = testDir.listFiles();
if (files == null) return Collections.emptyList();
return ContainerUtil.mapNotNull(files, file -> {
String fileName = PathUtil.getFileName(file.getPath());
return !fileName.contains("_after.") && !fileName.endsWith("_after") ? new Object[]{fileName, file} : null;
});
}
@Before
public void before() {
TextMateSyntaxTableBuilder syntaxTableBuilder = new TextMateSyntaxTableBuilder(new TextMateConcurrentMapInterner());
var matchers = TestUtilKt.loadBundle(syntaxTableBuilder, getBundleName());
List<String> extraBundleNames = getExtraBundleNames();
for (String bundleName : extraBundleNames) {
TestUtilKt.loadBundle(syntaxTableBuilder, bundleName);
}
mySyntaxTable = syntaxTableBuilder.build();
myRootScope = TestUtilKt.findScopeByFileName(matchers, myFileName);
assertNotNull("scope is empty for file name: " + myFileName, myRootScope);
}
@Test
public void lexerTest() throws IOException {
String sourceData = StringUtil.convertLineSeparators(FileUtil.loadFile(myFile, StandardCharsets.UTF_8));
StringBuilder output = new StringBuilder();
String text = sourceData.replaceAll("$(\\n+)", "");
RegexFactory regexFactory = new CachingRegexFactory(new RememberingLastMatchRegexFactory(new JoniRegexFactory()));
TextMateSelectorCachingWeigher weigher = new TextMateSelectorCachingWeigher(new TextMateSelectorWeigherImpl());
TextMateCachingSyntaxMatcher syntaxMatcher = new TextMateCachingSyntaxMatcher(new TextMateSyntaxMatcherImpl(regexFactory, weigher));
Lexer lexer = new TextMateHighlightingLexer(new TextMateLanguageDescriptor(myRootScope, mySyntaxTable.getSyntax(myRootScope)),
syntaxMatcher,
-1);
lexer.start(text);
while (lexer.getTokenType() != null) {
final int s = lexer.getTokenStart();
final int e = lexer.getTokenEnd();
final IElementType tokenType = lexer.getTokenType();
final String tokenTypePresentation = getTokenTypePresentation(tokenType);
final String str = tokenTypePresentation + ": [" + s + ", " + e + "], {" + text.substring(s, e) + "}\n";
output.append(str);
lexer.advance();
}
String extension = getExtension(myFileName);
String suffix = extension.isEmpty() ? "" : "." + extension;
String expectedFilePath = myFile.getParent() + "/" + FileUtilRt.getNameWithoutExtension(myFileName) + "_after" + suffix;
assertSameLinesWithFile(expectedFilePath, output.toString().trim());
}
@Nullable
private static String getTokenTypePresentation(IElementType tokenType) {
if (tokenType instanceof TextMateElementType) {
TextMateScope scope = ((TextMateElementType)tokenType).getScope();
StringBuilder builder = new StringBuilder();
CharSequence scopeName = scope.getScopeName();
if (scopeName != null) {
builder.append(scopeName);
}
TextMateScope parent = scope.getParent();
while (parent != null) {
CharSequence parentScopeName = parent.getScopeName();
if (parentScopeName != null) {
if (!builder.isEmpty()) {
builder.insert(0, ";");
}
builder.insert(0, parentScopeName);
}
parent = parent.getParent();
}
return builder.toString().trim();
}
return tokenType.toString();
}
protected abstract String getTestDirRelativePath();
protected abstract String getBundleName();
protected List<String> getExtraBundleNames() {
return Collections.emptyList();
}
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class LogLexerTest extends LexerTestCase {
class LogLexerTest : TextMateLexerTestCase() {
@Test
fun log() = doTest("log.log", "log_after.log")
@Override
protected String getTestDirRelativePath() {
return "log";
}
@Override
protected String getBundleName() {
return TestUtil.LOG;
}
override val testDirRelativePath = "log"
override val bundleName = TestUtil.LOG
}

View File

@@ -1,16 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.junit.jupiter.api.Test
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
public class MakefileLexerTest extends LexerTestCase {
class MakefileLexerTest : TextMateLexerTestCase() {
@Test
fun test() = doTest("test.mk", "test_after.mk")
@Override
protected String getTestDirRelativePath() {
return "make";
}
@Override
protected String getBundleName() {
return TestUtil.MAKE;
}
override val testDirRelativePath = "make"
override val bundleName = TestUtil.MAKE
}

View File

@@ -1,24 +1,14 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.List;
class MarkdownBloggingLexerTest : TextMateLexerTestCase() {
@Test
fun ruby12703() = doTest("ruby12703.blog.md", "ruby12703_after.blog.md")
import static java.util.Arrays.asList;
public class MarkdownBloggingLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "markdown_blogging";
}
@Override
protected String getBundleName() {
return TestUtil.MARKDOWN_BLOGGING;
}
@Override
protected List<String> getExtraBundleNames() {
return asList(TestUtil.MARKDOWN_TEXTMATE);
}
override val testDirRelativePath = "markdown_blogging"
override val bundleName = TestUtil.MARKDOWN_BLOGGING
override val extraBundleNames = listOf(TestUtil.MARKDOWN_TEXTMATE)
}

View File

@@ -1,24 +1,14 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Collections;
import java.util.List;
class MarkdownHtmlLexerTest : TextMateLexerTestCase() {
@Test
fun heading() = doTest("heading.md", "heading_after.md")
public class MarkdownHtmlLexerTest extends LexerTestCase {
@Override
protected String getBundleName() {
return TestUtil.MARKDOWN_TEXTMATE;
}
@Override
protected List<String> getExtraBundleNames() {
return Collections.singletonList(TestUtil.HTML);
}
@Override
protected String getTestDirRelativePath() {
return "markdown_html";
}
override val testDirRelativePath = "markdown_html"
override val bundleName = TestUtil.MARKDOWN_TEXTMATE
override val extraBundleNames = listOf(TestUtil.HTML)
}

View File

@@ -1,15 +1,40 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class MarkdownLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "markdown";
}
class MarkdownLexerTest : TextMateLexerTestCase() {
@Test
fun headerAfterParagraph() = doTest("header_after_paragraph.md", "header_after_paragraph_after.md")
@Override
protected String getBundleName() {
return TestUtil.MARKDOWN_TEXTMATE;
}
@Test
fun paragraph() = doTest("paragraph.md", "paragraph_after.md")
@Test
fun headers() = doTest("headers.md", "headers_after.md")
@Test
fun newLineRequiredBug() = doTest("new_line_required_bug.md", "new_line_required_bug_after.md")
@Test
fun numberedList() = doTest("numbered_list.md", "numbered_list_after.md")
@Test
fun link() = doTest("link.md", "link_after.md")
@Test
fun code() = doTest("code.md", "code_after.md")
@Test
fun unknownUtf() = doTest("unknown_utf.md", "unknown_utf_after.md")
@Test
fun inlineBold() = doTest("inline_bold.md", "inline_bold_after.md")
@Test
fun cyrillic() = doTest("cyrillic.md", "cyrillic_after.md")
override val testDirRelativePath = "markdown"
override val bundleName = TestUtil.MARKDOWN_TEXTMATE
}

View File

@@ -1,15 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class MarkdownSublimeLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "markdown_sublime";
}
class MarkdownSublimeLexerTest : TextMateLexerTestCase() {
@Test
fun infinityLoopBundleBug() = doTest("infinity_loop_bundle_bug.md", "infinity_loop_bundle_bug_after.md")
@Override
protected String getBundleName() {
return TestUtil.MARKDOWN_SUBLIME;
}
override val testDirRelativePath = "markdown_sublime"
override val bundleName = TestUtil.MARKDOWN_SUBLIME
}

View File

@@ -1,15 +1,19 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class MarkdownVscLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "markdown_vsc";
}
class MarkdownVscLexerTest : TextMateLexerTestCase() {
@Test
fun heading() = doTest("heading.md", "heading_after.md")
@Override
protected String getBundleName() {
return TestUtil.MARKDOWN_VSC;
}
@Test
fun unknownUtf() = doTest("unknown_utf.md", "unknown_utf_after.md")
@Test
fun inlineBold() = doTest("inline_bold.md", "inline_bold_after.md")
override val testDirRelativePath = "markdown_vsc"
override val bundleName = TestUtil.MARKDOWN_VSC
}

View File

@@ -1,16 +1,16 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class PerlLexerTest extends LexerTestCase {
class PerlLexerTest : TextMateLexerTestCase() {
@Test
fun perl() = doTest("perl.pl", "perl_after.pl")
@Override
protected String getTestDirRelativePath() {
return "perl";
}
@Test
fun regex() = doTest("regex.pl", "regex_after.pl")
@Override
protected String getBundleName() {
return TestUtil.PERL;
}
override val testDirRelativePath = "perl"
override val bundleName = TestUtil.PERL
}

View File

@@ -1,24 +1,14 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Collections;
import java.util.List;
class PhpHtmlLexerTest : TextMateLexerTestCase() {
@Test
fun injection() = doTest("injection.php_hack", "injection_after.php_hack")
public class PhpHtmlLexerTest extends LexerTestCase {
@Override
protected String getBundleName() {
return TestUtil.PHP;
}
@Override
protected List<String> getExtraBundleNames() {
return Collections.singletonList(TestUtil.HTML);
}
@Override
protected String getTestDirRelativePath() {
return "php";
}
override val testDirRelativePath = "php"
override val bundleName = TestUtil.PHP
override val extraBundleNames = listOf(TestUtil.HTML)
}

View File

@@ -1,24 +1,23 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Arrays;
import java.util.List;
class PhpVscLexerTest : TextMateLexerTestCase() {
@Test
fun htmlCss() = doTest("html_css.php_vsc", "html_css_after.php_vsc")
public class PhpVscLexerTest extends LexerTestCase {
@Test
fun escapeSymbol() = doTest("escape_symbol.php_vsc", "escape_symbol_after.php_vsc")
@Override
protected String getBundleName() {
return TestUtil.PHP_VSC;
}
@Test
fun slow() = doTest("slow.php_vsc", "slow_after.php_vsc")
@Override
protected List<String> getExtraBundleNames() {
return Arrays.asList(TestUtil.HTML_VSC, TestUtil.CSS_VSC);
}
@Test
fun empty() = doTest("empty.php_vsc", "empty_after.php_vsc")
@Override
protected String getTestDirRelativePath() {
return "php_vsc";
}
override val testDirRelativePath = "php_vsc"
override val bundleName = TestUtil.PHP_VSC
override val extraBundleNames = listOf(TestUtil.HTML_VSC, TestUtil.CSS_VSC)
}

View File

@@ -1,15 +1,16 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class PythonLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "python";
}
class PythonLexerTest : TextMateLexerTestCase() {
@Test
fun selfpointer() = doTest("selfpointer.py", "selfpointer_after.py")
@Override
protected String getBundleName() {
return TestUtil.PYTHON;
}
@Test
fun dictionary() = doTest("dictionary.py", "dictionary_after.py")
override val testDirRelativePath = "python"
override val bundleName = TestUtil.PYTHON
}

View File

@@ -1,7 +1,12 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer
class RstLexerTest: LexerTestCase() {
override fun getTestDirRelativePath(): String = "rst"
import org.junit.jupiter.api.Test
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
override fun getBundleName(): String = "restructuredtext"
class RstLexerTest : TextMateLexerTestCase() {
@Test
fun nested() = doTest("nested.rst", "nested_after.rst")
override val testDirRelativePath = "rst"
override val bundleName = "restructuredtext"
}

View File

@@ -1,15 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class RubyLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "ruby";
}
class RubyLexerTest : TextMateLexerTestCase() {
@Test
fun commentAtLineStart() = doTest("comment_at_line_start.rb", "comment_at_line_start_after.rb")
@Override
protected String getBundleName() {
return TestUtil.RUBY;
}
override val testDirRelativePath = "ruby"
override val bundleName = TestUtil.RUBY
}

View File

@@ -1,16 +1,19 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class ShellscriptLexerTest extends LexerTestCase {
class ShellscriptLexerTest : TextMateLexerTestCase() {
@Test
fun case() = doTest("case.sh", "case_after.sh")
@Override
protected String getTestDirRelativePath() {
return "shellscript";
}
@Test
fun comment() = doTest("comment.sh", "comment_after.sh")
@Override
protected String getBundleName() {
return TestUtil.SHELLSCRIPT;
}
@Test
fun heredoc() = doTest("heredoc.sh", "heredoc_after.sh")
override val testDirRelativePath = "shellscript"
override val bundleName = TestUtil.SHELLSCRIPT
}

View File

@@ -1,24 +1,14 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
import java.util.Collections;
import java.util.List;
class SmartyPhpLexerTest : TextMateLexerTestCase() {
@Test
fun injection() = doTest("injection.tpl_hack", "injection_after.tpl_hack")
public class SmartyPhpLexerTest extends LexerTestCase {
@Override
protected String getBundleName() {
return TestUtil.SMARTY;
}
@Override
protected List<String> getExtraBundleNames() {
return Collections.singletonList(TestUtil.PHP);
}
@Override
protected String getTestDirRelativePath() {
return "smarty";
}
override val testDirRelativePath = "smarty"
override val bundleName = TestUtil.SMARTY
override val extraBundleNames = listOf(TestUtil.PHP)
}

View File

@@ -1,16 +1,16 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class TerraformLexerTest extends LexerTestCase {
class TerraformLexerTest : TextMateLexerTestCase() {
@Test
fun module() = doTest("module.tf", "module_after.tf")
@Override
protected String getTestDirRelativePath() {
return "terraform";
}
@Test
fun splitScopeBySpace() = doTest("split_scope_by_space.tf", "split_scope_by_space_after.tf")
@Override
protected String getBundleName() {
return TestUtil.TERRAFORM;
}
override val testDirRelativePath = "terraform"
override val bundleName = TestUtil.TERRAFORM
}

View File

@@ -1,15 +1,13 @@
package org.jetbrains.plugins.textmate.language.syntax.lexer;
package org.jetbrains.plugins.textmate.language.syntax.lexer
import org.jetbrains.plugins.textmate.TestUtil;
import org.jetbrains.plugins.textmate.TestUtil
import org.jetbrains.plugins.textmate.language.syntax.TextMateLexerTestCase
import org.junit.jupiter.api.Test
public class TurtleLexerTest extends LexerTestCase {
@Override
protected String getTestDirRelativePath() {
return "turtle";
}
class TurtleLexerTest : TextMateLexerTestCase() {
@Test
fun localInifinityLoopProtection() = doTest("local_inifinity_loop_protection.ttl", "local_inifinity_loop_protection_after.ttl")
@Override
protected String getBundleName() {
return TestUtil.TURTLE;
}
override val testDirRelativePath = "turtle"
override val bundleName = TestUtil.TURTLE
}