Skip to content

Commit

Permalink
feat(goast): enhance handling of fmt.print series functions and tests
Browse files Browse the repository at this point in the history
This commit adds the capability to process `fmt.print` series functions in Go code, capturing the content and arguments. It includes updates to the `GoFullIdentListener` to identify and parse such function calls, along with an extension to the `CodeProperty` data structure to store the extracted parameters. Additionally, a new test case is introduced to validate the identification of function calls within other calls.
  • Loading branch information
phodal committed Nov 9, 2024
1 parent fa914fe commit cbb9134
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package chapi.ast.goast

import chapi.ast.antlr.GoParser
import chapi.ast.antlr.GoParser.PrimaryExprContext
import chapi.domain.core.*
import chapi.infra.Stack
import org.antlr.v4.runtime.RuleContext
Expand Down Expand Up @@ -273,6 +274,20 @@ class GoFullIdentListener(var fileName: String) : GoAstListener() {
return@map CodeProperty(TypeValue = localVars[value]!!, TypeType = typetype)
}

/// handle for fmt.print series function, if it.s a fmt.print series function, should return the value
val isPrintFunc = goPrintFuncs.any { value.split("(").firstOrNull() == it }
if (it.getChild(0) is PrimaryExprContext && isPrintFunc) {
val content = value.split("(").lastOrNull()?.removeSuffix(")")
val params = it.getChild(0).getChild(1) as? GoParser.ArgumentsContext
if (params != null) {
val childElements = parseArguments(params)
val elementContent = childElements.joinToString(", ") { it.TypeValue }
return@map CodeProperty(TypeValue = elementContent, TypeType = typetype, Parameters = childElements)
}

return@map CodeProperty(TypeValue = content ?: "", TypeType = typetype)
}

CodeProperty(TypeValue = value, TypeType = typetype)
} ?: listOf()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -427,4 +427,45 @@ func (d *Dao) MobileMachineLendCount() (mobileMachinesUsageCount []*model.Mobile
assertEquals(functionCalls[1].Parameters.size, 1)
assertEquals(functionCalls[1].Parameters[0].TypeValue, "\"select b.id,b.name,count(b.name) as count from mobile_machine_logs as a \"+\"left join mobile_machines as b on a.machine_id = b.id \"+\"where a.operation_type='%s' and a.operation_result = '%s' \"+\"group by b.id,b.`name` order by count desc\"")
}

@Test
fun shouldIdentCallInSideCall() {
@Language("Go")
val code= """
package dao
const _chArcAddSQL = "INSERT INTO member_channel_video%d (mid,cid,aid,order_num,modify_time) VALUES %s"
func (d *Dao) AddChannelArc(c context.Context, mid, cid int64, ts time.Time, chs []*model.ChannelArcSort) (lastID int64, err error) {
var (
res sql.Result
values []string
)
for _, v := range chs {
values = append(values, fmt.Sprintf("(%d,%d,%d,%d,'%s')", mid, cid, v.Aid, v.OrderNum, ts.Format("2006-01-02 15:04:05")))
}
if res, err = d.db.Exec(c, fmt.Sprintf(_chArcAddSQL, channelHit(mid), strings.Join(values, ","))); err != nil {
log.Error("AddChannelArc: db.Exec(%d,%d) error(%v)", mid, cid, err)
return
}
return res.LastInsertId()
}
"""

val codeFile = GoAnalyser().analysis(code, "")
val functionCalls = codeFile.DataStructures[0].Functions[0].FunctionCalls
println(functionCalls)

assertEquals(functionCalls.size, 9)

val fourthCall = functionCalls[3]
assertEquals(fourthCall.NodeName, "Dao.db")
assertEquals(fourthCall.FunctionName, "Exec")
assertEquals(fourthCall.Parameters.size, 2)
val secondParameter = fourthCall.Parameters[1]
assertEquals(secondParameter.TypeValue, "\"INSERT INTO member_channel_video%d (mid,cid,aid,order_num,modify_time) VALUES %s\", channelHit(mid), strings.Join(values,\",\")")

val codeProperty = secondParameter.Parameters
assertEquals(codeProperty[0].TypeValue, "\"INSERT INTO member_channel_video%d (mid,cid,aid,order_num,modify_time) VALUES %s\"")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,8 @@ data class CodeProperty(
/// for TypeScript and Parameter
var ObjectValue: List<CodeProperty> = listOf(),
var ReturnTypes: List<CodeProperty> = listOf(),
/**
* in Golang, we also use it to save fmt.Print series values, like `fmt.Println("hello", "world")`
*/
var Parameters: List<CodeProperty> = listOf(),
)

0 comments on commit cbb9134

Please sign in to comment.