Skip to content

Commit

Permalink
feat(go): add support for go block call
Browse files Browse the repository at this point in the history
  • Loading branch information
phodal committed Nov 25, 2022
1 parent 6c6ed71 commit e672a5e
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package chapi.ast.goast

import chapi.ast.antlr.GoParser
import chapi.domain.core.*
import chapi.infra.Stack
import org.antlr.v4.runtime.tree.TerminalNodeImpl

/**
Expand Down Expand Up @@ -57,6 +58,28 @@ class GoFullIdentListener(var fileName: String) : GoAstListener() {
currentFunction = CodeFunction()
}


private var blockStack = Stack<CodeFunction>()
private var lastBlock = CodeFunction(Type = FunctionType.Block, Name = "chapi_block")

override fun enterBlock(ctx: GoParser.BlockContext?) {
if (ctx?.parent is GoParser.StatementContext) {
lastBlock = CodeFunction(Type = FunctionType.Block, Name = "chapi_block" + "${blockStack.count()}")
blockStack.push(lastBlock)
}
}

override fun exitBlock(ctx: GoParser.BlockContext?) {
if (ctx?.parent is GoParser.StatementContext) {
val popBlock = blockStack.pop()!!
if (blockStack.count() > 0) {
blockStack.peek()!!.InnerFunctions += popBlock
} else {
currentFunction.InnerFunctions += popBlock
}
}
}

override fun enterTypeDecl(ctx: GoParser.TypeDeclContext?) {
ctx?.typeSpec()?.forEach {
buildTypeSpec(it)
Expand Down Expand Up @@ -126,7 +149,7 @@ class GoFullIdentListener(var fileName: String) : GoAstListener() {
}

private fun buildTypeSpec(typeSpec: GoParser.TypeSpecContext) {
val identifyName = typeSpec.IDENTIFIER().text
val identifyName = typeSpec.IDENTIFIER()?.text ?: ""
typeSpec.type_().typeLit()?.let {
when (val typeChild = it.getChild(0)) {
is GoParser.StructTypeContext -> {
Expand Down Expand Up @@ -190,7 +213,11 @@ class GoFullIdentListener(var fileName: String) : GoAstListener() {
codeCall.Parameters = parseArguments(child)
codeCall.Package = wrapTarget(codeCall.NodeName)

currentFunction.FunctionCalls += codeCall
if (blockStack.count() > 0) {
lastBlock.FunctionCalls += codeCall
} else {
currentFunction.FunctionCalls += codeCall
}
}

else -> {
Expand Down
27 changes: 18 additions & 9 deletions chapi-ast-go/src/test/kotlin/chapi/ast/goast/GoAnalyserTest.kt
Original file line number Diff line number Diff line change
Expand Up @@ -99,19 +99,28 @@ func installController(g *gin.Engine) *gin.Engine {
}"""

val codeContainer = GoAnalyser().analysis(code, "")
val value = codeContainer.DataStructures[0]
val secondCall = value.Functions[0].FunctionCalls[1]
val container = codeContainer.DataStructures[0]

val mainCall = container.Functions[0].FunctionCalls[1]

assertEquals(container.Functions.size, 1)
assertEquals(mainCall.FunctionName, "Group")
assertEquals(mainCall.Parameters[0].TypeValue, "/v1")

val firstBlock = container.Functions[0].InnerFunctions[0]
val innelCall = firstBlock.FunctionCalls[0]

assertEquals(secondCall.FunctionName, "Group")
assertEquals(secondCall.Parameters[0].TypeValue, "/v1")
assertEquals(innelCall.FunctionName, "Group")
assertEquals(innelCall.NodeName, "*gin.Engine")
assertEquals(innelCall.Parameters[0].TypeValue, "/users")

val thirdCall = value.Functions[0].FunctionCalls[2]
val secondBlock = container.Functions[0].InnerFunctions[0].InnerFunctions[0]
val innerInnerCall = secondBlock.FunctionCalls[0]

assertEquals(thirdCall.FunctionName, "Group")
assertEquals(thirdCall.NodeName, "*gin.Engine")
assertEquals(thirdCall.Parameters[0].TypeValue, "/users")
assertEquals(innerInnerCall.FunctionName, "NewUserController")

println(Json.encodeToString(value))
val innerInnerSecondCall = secondBlock.FunctionCalls[1]
assertEquals(innerInnerSecondCall.FunctionName, "GET")
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,12 @@ import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.jsonObject

enum class FunctionType {
Function,
// for Golang block
Block,
}

@Serializable
open class CodeFunction(
var Name: String = "",
Expand All @@ -29,6 +35,7 @@ open class CodeFunction(
var IsConstructor: Boolean = false, // todo: move to extension
var IsReturnHtml: Boolean = false,
var BodyHash: Int = 0,
var Type: FunctionType = FunctionType.Function,
// a experimental api for code analysis, please carefully use it.
// @property:ExperimentalStdlibApi val expression: Expression? = null,
) {
Expand Down

0 comments on commit e672a5e

Please sign in to comment.