Skip to content

Commit fb12ea8

Browse files
dimonchik0036Space Team
authored andcommitted
[psi] add test on API dump consistency
^KT-78613
1 parent c2ad9ae commit fb12ea8

File tree

8 files changed

+84
-38
lines changed

8 files changed

+84
-38
lines changed

analysis/analysis-api/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ dependencies {
2828
testApi(platform(libs.junit.bom))
2929
testImplementation(libs.junit.jupiter.api)
3030
testRuntimeOnly(libs.junit.jupiter.engine)
31+
testImplementation(projectTests(":compiler:psi:psi-api"))
3132
}
3233

3334
kotlin {
Lines changed: 5 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,19 @@
11
/*
2-
* Copyright 2010-2024 JetBrains s.r.o. and Kotlin Programming Language contributors.
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
33
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
44
*/
55

66
package org.jetbrains.kotlin.analysis.api.test
77

8+
import org.jetbrains.kotlin.AbstractSurfaceTest
89
import org.junit.jupiter.api.Test
9-
import org.junit.jupiter.api.fail
1010
import java.nio.file.Paths
11-
import java.util.function.Consumer
12-
import kotlin.io.path.readText
1311

14-
class AnalysisApiSurfaceTest {
12+
class AnalysisApiSurfaceTest : AbstractSurfaceTest() {
1513
private companion object {
1614
private val API_SURFACE_PATH = Paths.get("analysis/analysis-api/api/analysis-api.api")
1715
}
1816

1917
@Test
20-
fun testNestedClassCoverage() = runTest {
21-
val text = API_SURFACE_PATH.readText()
22-
val classNames = Regex("class ([\\w/$]+)\\s*[{:]")
23-
.findAll(text)
24-
.map { it.groupValues[1] }
25-
.toSet()
26-
27-
for (className in classNames) {
28-
val containingClassNames = generateSequence(className) {
29-
it.substringBeforeLast('$', missingDelimiterValue = "").takeUnless { it.isEmpty() }
30-
}
31-
32-
for (containingClassName in containingClassNames) {
33-
if (containingClassName !in classNames) {
34-
accept("Containing class $containingClassName for $className is missing")
35-
}
36-
}
37-
}
38-
}
39-
40-
private fun runTest(block: Consumer<String>.() -> Unit) {
41-
val result = mutableListOf<String>()
42-
block(result::add)
43-
if (result.isNotEmpty()) {
44-
fail("Problems are found:\n" + result.joinToString("\n"))
45-
}
46-
}
47-
}
18+
fun testNestedClassCoverage() = validateApiDump(API_SURFACE_PATH)
19+
}

analysis/build.gradle.kts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ tasks.register("analysisAllTests") {
1919
":analysis:symbol-light-classes:test",
2020
":analysis:analysis-tools:analysis-api-kdoc-coverage-test:test",
2121
":compiler:psi:psi-api:apiCheck",
22+
":compiler:psi:psi-api:test",
2223
)
2324

2425
if (kotlinBuildProperties.isKotlinNativeEnabled) {

compiler/psi/psi-api/api/psi-api.api

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,3 @@
1-
public final class org/jetbrains/kotlin/KotlinElementTypeProvider$Companion {
2-
public final fun getInstance ()Lorg/jetbrains/kotlin/KotlinElementTypeProvider;
3-
}
4-
51
public class org/jetbrains/kotlin/KtNodeType : com/intellij/psi/tree/IElementType {
62
public fun <init> (Ljava/lang/String;Ljava/lang/Class;)V
73
public fun createPsi (Lcom/intellij/lang/ASTNode;)Lorg/jetbrains/kotlin/psi/KtElement;

compiler/psi/psi-api/build.gradle.kts

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,26 @@ dependencies {
1313
compileOnly(intellijCore())
1414
compileOnly(libs.guava)
1515
compileOnly(libs.intellij.fastutil)
16+
17+
testApi(platform(libs.junit.bom))
18+
testImplementation(libs.junit.jupiter.api)
19+
testRuntimeOnly(libs.junit.jupiter.engine)
1620
}
1721

1822
sourceSets {
1923
"main" { projectDefault() }
20-
"test" {}
24+
"test" { projectDefault() }
2125
}
2226

2327
apiValidation {
2428
nonPublicMarkers += listOf(
2529
"org.jetbrains.kotlin.psi.KtImplementationDetail",
2630
)
2731
}
32+
33+
testsJar()
34+
35+
projectTest(jUnitMode = JUnitMode.JUnit5) {
36+
workingDir = rootDir
37+
useJUnitPlatform()
38+
}

compiler/psi/psi-api/src/org/jetbrains/kotlin/KotlinElementTypeProvider.kt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import org.jetbrains.kotlin.psi.stubs.elements.KtStubElementType
1515

1616
@KtImplementationDetail
1717
interface KotlinElementTypeProvider {
18+
@KtImplementationDetail
1819
companion object {
1920
private const val IMPL = "org.jetbrains.kotlin.psi.impl.KotlinElementTypeProviderImpl"
2021

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin
7+
8+
import org.junit.jupiter.api.fail
9+
import java.nio.file.Path
10+
import java.util.function.Consumer
11+
import kotlin.io.path.readText
12+
13+
abstract class AbstractSurfaceTest {
14+
private companion object {
15+
private val CLASS_NAME_REGEX = Regex("class ([\\w/$]+)\\s*[{:]")
16+
}
17+
18+
protected fun validateApiDump(apiDumpPath: Path): Unit = runTest {
19+
val text = apiDumpPath.readText()
20+
val classNames = CLASS_NAME_REGEX
21+
.findAll(text)
22+
.map { it.groupValues[1] }
23+
.toSet()
24+
25+
for (className in classNames) {
26+
val containingClassNames = generateSequence(className) {
27+
it.substringBeforeLast('$', missingDelimiterValue = "").takeUnless { it.isEmpty() }
28+
}
29+
30+
for (containingClassName in containingClassNames) {
31+
if (containingClassName !in classNames) {
32+
accept("Containing class $containingClassName for $className is missing")
33+
}
34+
}
35+
}
36+
}
37+
38+
private fun runTest(block: Consumer<String>.() -> Unit) {
39+
val result = mutableListOf<String>()
40+
block(result::add)
41+
if (result.isNotEmpty()) {
42+
fail("Problems are found:\n" + result.joinToString("\n"))
43+
}
44+
}
45+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Copyright 2010-2025 JetBrains s.r.o. and Kotlin Programming Language contributors.
3+
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
4+
*/
5+
6+
package org.jetbrains.kotlin.psi
7+
8+
import org.jetbrains.kotlin.AbstractSurfaceTest
9+
import org.junit.jupiter.api.Test
10+
import java.nio.file.Paths
11+
12+
class PsiSurfaceTest : AbstractSurfaceTest() {
13+
private companion object {
14+
private val API_SURFACE_PATH = Paths.get("compiler/psi/psi-api/api/psi-api.api")
15+
}
16+
17+
@Test
18+
fun testNestedClassCoverage() = validateApiDump(API_SURFACE_PATH)
19+
}

0 commit comments

Comments
 (0)