Skip to content

Commit

Permalink
feat(chapi-ast-c): add override to addSource method #24
Browse files Browse the repository at this point in the history
This commit adds the `override` keyword to the `addSource` method in the `CAnalyser` class. This ensures that the method is properly overridden from the parent class.
  • Loading branch information
phodal committed Feb 1, 2024
1 parent 023fabe commit ce431e4
Show file tree
Hide file tree
Showing 5 changed files with 59 additions and 11 deletions.
1 change: 1 addition & 0 deletions chapi-ast-c/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
result.json
5 changes: 1 addition & 4 deletions chapi-ast-c/src/main/kotlin/chapi/ast/cast/CAnalyser.kt
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,7 @@ open class CAnalyser : Analyser {
pp.listener = DefaultPreprocessorListener()
}

/**
* Adds a source code to the program, for example, C header files.
*/
fun addSource(code: String) {
override fun addSource(code: String) {
pp.addInput(LexerSource(InputStreamReader(code.byteInputStream()), true))
}

Expand Down
13 changes: 10 additions & 3 deletions chapi-ast-c/src/main/kotlin/chapi/ast/cast/CFullIdentListener.kt
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,18 @@ open class CFullIdentListener(fileName: String, includes: MutableList<String>) :
ctx?.structDeclarationList()?.structDeclaration()?.forEach { structDeclCtx ->
/// for forward struct declaration
structDeclCtx.structDeclaratorList()?.let {
val type = structDeclCtx.specifierQualifierList()?.typeSpecifier()?.let {
val specifier = it.structOrUnionSpecifier()
var type = structDeclCtx.specifierQualifierList()?.typeSpecifier()?.let { typeSpec ->
val specifier = typeSpec.structOrUnionSpecifier()
specifier?.structOrUnion()?.text + " " + specifier?.Identifier()?.text
}
val value = structDeclCtx.specifierQualifierList()?.specifierQualifierList()?.text ?: ""
var value: String? = null

if (type == null || type == "null null") {
type = structDeclCtx.specifierQualifierList()?.typeSpecifier()?.text ?: ""
value = it.structDeclarator()?.firstOrNull()?.declarator()?.text ?: ""
} else {
value = structDeclCtx.specifierQualifierList()?.specifierQualifierList()?.text ?: ""
}

val field = CodeField(
TypeType = type ?: "",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
package chapi.ast.cast

import chapi.domain.core.CodeContainer
import kotlinx.coroutines.flow.asFlow
import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.mapNotNull
import kotlinx.coroutines.runBlocking
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import org.junit.jupiter.api.Test
import java.io.File
import kotlin.test.assertEquals
Expand All @@ -14,21 +17,33 @@ internal class CFullIdentListenerTest {
@Test
fun allGrammarUnderResources() {
val content = this::class.java.getResource("/grammar")!!.toURI()
// val content = "/Users/phodal/Downloads/redis-unstable"
// val content = "/Users/phodal/Downloads/redis-unstable/deps/lua"
val totalStart = System.currentTimeMillis()
runBlocking {
File(content).walkTopDown().asFlow().mapNotNull {
val analyser = CAnalyser()
val fileFlow = File(content).walkTopDown().asFlow()
fileFlow.mapNotNull {
if (it.isFile && (it.extension == "c" || it.extension == "h")) {
analyser.addSource(it.readText())
}
}

val result: MutableList<CodeContainer> = mutableListOf()
fileFlow.mapNotNull {
if (it.isFile && (it.extension == "c" || it.extension == "h")) {
val start = System.currentTimeMillis()
println("Analyse ${it.path}")
val analysis = CAnalyser().analysis(it.readText(), it.name)
val analysis = analyser.analysis(it.readText(), it.name)
val end = System.currentTimeMillis()
println("cost ${end - start}ms")
analysis
result += analysis
} else {
null
}
}.collect()

// log to file
File("result.json").writeText(Json.encodeToString(result))
}

val totalEnd = System.currentTimeMillis()
Expand Down Expand Up @@ -78,6 +93,24 @@ struct list_el {
assertEquals(codeFile.DataStructures[0].Fields[0].TypeValue, "val")
}

@Test
internal fun shouldIdentifyStructWithPointer() {
val code = """
typedef struct Mbuffer {
char *buffer;
size_t n;
size_t buffsize;
} Mbuffer;
"""
val codeFile = CAnalyser().analysis(code, "helloworld.c")

assertEquals(codeFile.DataStructures.size, 1)
assertEquals(codeFile.DataStructures[0].Fields.size, 3)
assertEquals(codeFile.DataStructures[0].Fields[0].TypeType, "char")
assertEquals(codeFile.DataStructures[0].Fields[0].TypeValue, "*buffer")
}

@Test
internal fun shouldIdentifyStructFunction() {
val code = """
Expand Down
10 changes: 10 additions & 0 deletions chapi-domain/src/main/kotlin/chapi/parser/Analyser.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,23 @@
package chapi.parser

import chapi.domain.core.CodeContainer
import chapi.domain.core.Since

enum class ParseMode {
Basic, Full
}

// todo: add support for kotlin & java
interface Analyser {

/**
* Adds a source code to the program, for example, C header files.
*/
@Since("2.3.4")
fun addSource(code: String) {

}

fun analysis(code: String, filePath: String): CodeContainer
}

Expand Down

0 comments on commit ce431e4

Please sign in to comment.