🎉 初始化项目
This commit is contained in:
62
server/utils/ast/extract_func.go
Normal file
62
server/utils/ast/extract_func.go
Normal file
@@ -0,0 +1,62 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ExtractFuncSourceByPosition 根据文件路径与行号,提取包含该行的整个方法源码
|
||||
// 返回:方法名、完整源码、起止行号
|
||||
func ExtractFuncSourceByPosition(filePath string, line int) (name string, source string, startLine int, endLine int, err error) {
|
||||
// 读取源文件
|
||||
src, readErr := os.ReadFile(filePath)
|
||||
if readErr != nil {
|
||||
err = fmt.Errorf("read file failed: %w", readErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析 AST
|
||||
fset := token.NewFileSet()
|
||||
file, parseErr := parser.ParseFile(fset, filePath, src, parser.ParseComments)
|
||||
if parseErr != nil {
|
||||
err = fmt.Errorf("parse file failed: %w", parseErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 在 AST 中定位包含指定行号的函数声明
|
||||
var target *ast.FuncDecl
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
fd, ok := n.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
s := fset.Position(fd.Pos()).Line
|
||||
e := fset.Position(fd.End()).Line
|
||||
if line >= s && line <= e {
|
||||
target = fd
|
||||
startLine = s
|
||||
endLine = e
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if target == nil {
|
||||
err = fmt.Errorf("no function encloses line %d in %s", line, filePath)
|
||||
return
|
||||
}
|
||||
|
||||
// 使用字节偏移精确提取源码片段(包含注释与原始格式)
|
||||
start := fset.Position(target.Pos()).Offset
|
||||
end := fset.Position(target.End()).Offset
|
||||
if start < 0 || end > len(src) || start >= end {
|
||||
err = fmt.Errorf("invalid offsets for function: start=%d end=%d len=%d", start, end, len(src))
|
||||
return
|
||||
}
|
||||
source = string(src[start:end])
|
||||
name = target.Name.Name
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user