Skip to content

Commit daee922

Browse files
committed
refactor(kotlin): try to add handle for test package issue
1 parent 7337188 commit daee922

File tree

2 files changed

+57
-15
lines changed

2 files changed

+57
-15
lines changed

chapi-ast-kotlin/src/main/kotlin/chapi/ast/kotlinast/KotlinFullIdentListener.kt

+25-15
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,31 @@ import chapi.domain.core.CodeDataStruct
77
import chapi.domain.core.CodeField
88
import chapi.domain.core.CodeImport
99
import chapi.domain.core.CodeProperty
10+
import java.io.File
11+
12+
private const val PRIMARY_CONSTRUCTOR = "PrimaryConstructor"
1013

1114
/**
12-
* listen to full identifier with complex type and sceneries, such as:
15+
* listen to full identifier with a complex type and sceneries, such as:
1316
* - call relationship
1417
* - lambda expression
1518
* - coroutine
1619
*/
17-
open class KotlinFullIdentListener(fileName: String) : KotlinBasicIdentListener(fileName) {
20+
open class KotlinFullIdentListener(val fileName: String) : KotlinBasicIdentListener(fileName) {
1821

1922
private val postClassHandler = mutableListOf<(CodeDataStruct) -> Unit>()
20-
private var VARIABLE_POOL: MutableMap<String, String> = mutableMapOf()
23+
private var variablePool: MutableMap<String, String> = mutableMapOf()
2124

2225
override fun enterPropertyDeclaration(ctx: KotlinParser.PropertyDeclarationContext?) {
2326
if (ctx!!.variableDeclaration() != null) {
2427
val varDecl = ctx.variableDeclaration()
2528
val key = varDecl.simpleIdentifier().text
2629
if (ctx.ASSIGNMENT() != null) {
2730
if (ctx.propertyDelegate() != null) {
28-
VARIABLE_POOL[key] = ctx.propertyDelegate().text
31+
variablePool[key] = ctx.propertyDelegate().text
2932
}
3033
if (ctx.expression() != null) {
31-
VARIABLE_POOL[key] = ctx.expression().text
34+
variablePool[key] = ctx.expression().text
3235
}
3336
}
3437

@@ -58,16 +61,16 @@ open class KotlinFullIdentListener(fileName: String) : KotlinBasicIdentListener(
5861
// if a argument/parameter type is not a string and not a number, it could be a variable
5962
// so, try to load value from VARIABLE_POOL
6063
if (typeType == "") {
61-
if (VARIABLE_POOL[value] != null) {
62-
value = VARIABLE_POOL[value].toString()
64+
if (variablePool[value] != null) {
65+
value = variablePool[value].toString()
6366

6467
// value contains with String
6568
val matches = VAR_IN_STRING.find(value)
6669
matches?.groups?.forEach {
6770
if (it?.value != null) {
6871
val variable = it.value
6972
val withoutVariable = variable.removePrefix("$")
70-
val pool = VARIABLE_POOL[withoutVariable]
73+
val pool = variablePool[withoutVariable]
7174
if (pool != null) {
7275
var poolText = pool
7376
if (poolText.startsWith("\"") && poolText.endsWith("\"")) {
@@ -85,6 +88,8 @@ open class KotlinFullIdentListener(fileName: String) : KotlinBasicIdentListener(
8588
return CodeProperty(TypeType = typeType, TypeValue = value)
8689
}
8790

91+
val testDir = listOf("src", "test", "kotlin").joinToString(File.separator)
92+
8893
// correct the function info
8994
private fun CodeCall.refineIfExistsCreator(): CodeCall {
9095
// search the node in declared classes (for individual function)
@@ -109,12 +114,14 @@ open class KotlinFullIdentListener(fileName: String) : KotlinBasicIdentListener(
109114

110115
// return null to quick exit
111116
private fun CodeCall.refineWithClass(it: CodeDataStruct): CodeCall? {
112-
if (FunctionName.isNotEmpty() && it.NodeName == FunctionName && FunctionName.first().isUpperCase()) {
113-
Type = CallType.CREATOR
114-
Package = it.Package
115-
NodeName = it.NodeName
116-
this.FunctionName = "PrimaryConstructor"
117-
return null
117+
if (FunctionName[0].isUpperCase()) {
118+
if (it.NodeName == FunctionName) {
119+
Type = CallType.CREATOR
120+
Package = it.Package
121+
NodeName = it.NodeName
122+
this.FunctionName = PRIMARY_CONSTRUCTOR
123+
return null
124+
}
118125
}
119126

120127
return this
@@ -126,10 +133,13 @@ open class KotlinFullIdentListener(fileName: String) : KotlinBasicIdentListener(
126133
return null
127134
}
128135

136+
// for Kotlin, if the function name is same as the import name, it's a creator
129137
if (it.AsName == FunctionName && FunctionName[0].isUpperCase()) {
130138
Package = it.Source
131139
NodeName = FunctionName
132-
return null;
140+
FunctionName = PRIMARY_CONSTRUCTOR
141+
Type = CallType.CREATOR
142+
return null
133143
}
134144

135145
if (it.AsName == FunctionName) {

chapi-ast-kotlin/src/test/kotlin/chapi/ast/kotlinast/KotlinFunctionCallTest.kt

+32
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,36 @@ class KotlinFunctionCallTest {
2323
assert(functionCall.FunctionName == "PrimaryConstructor")
2424
assert(functionCall.NodeName == "A")
2525
}
26+
27+
@Test
28+
fun should_success_parse_test_usecase() {
29+
val code = """
30+
package cc.unitmesh.pick
31+
32+
class SingleProjectCodePickerTest {
33+
@Test
34+
fun shouldCheckoutTestCode() {
35+
val picker = SingleProjectCodePicker(
36+
InsPickerOption(
37+
url = "https://github.com/unit-mesh/unit-eval-testing",
38+
completionTypeSize = 10,
39+
maxCharInCode = 100,
40+
)
41+
)
42+
43+
val outputFile = File("test.jsonl")
44+
runBlocking {
45+
val output: MutableList<Instruction> = picker.execute()
46+
outputFile.writeText(output.joinToString("\n") {
47+
Json.encodeToString(it)
48+
})
49+
}
50+
}
51+
}""".trimIndent()
52+
53+
val codeContainer = KotlinAnalyser().analysis(code, "Test.kt", ParseMode.Full)
54+
val dataStructures = codeContainer.DataStructures.filter { it.NodeName == "SingleProjectCodePickerTest" }
55+
val functionCall = dataStructures[0].Functions[0].FunctionCalls[0]
56+
println(functionCall)
57+
}
2658
}

0 commit comments

Comments
 (0)