From cb9037c704263cdd92011570024f3ae45883d541 Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 28 Feb 2026 11:51:04 +0800 Subject: [PATCH 01/21] get_file_symbol: repo file-path name to locate a node --- idl/get_file_symbol.proto | 39 ++++++++ llm/mcp/handler.go | 7 +- llm/tool/ast_read.go | 199 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 242 insertions(+), 3 deletions(-) create mode 100644 idl/get_file_symbol.proto diff --git a/idl/get_file_symbol.proto b/idl/get_file_symbol.proto new file mode 100644 index 00000000..ae5b4593 --- /dev/null +++ b/idl/get_file_symbol.proto @@ -0,0 +1,39 @@ +// get_file_symbol IDL + +syntax = "proto3"; + +package abcoder; + +// Request +message GetFileSymbolReq { + string repo_name = 1; // the name of the repository (output of list_repos tool) + string file_path = 2; // the file path (output of get_repo_structure tool) + string name = 3; // the name of the symbol (function, type, or variable) to query +} + +// Response +message GetFileSymbolResp { + FileNodeStruct node = 1; // the ast node + string error = 2; // optional, the error message +} + +// FileNodeStruct 文件节点结构(使用 FileNodeID) +message FileNodeStruct { + string name = 1; // the name of the node + string type = 2; // optional, the type of the node + string signature = 3; // optional, the func signature of the node + string file = 4; // optional, the file path of the node + int32 line = 5; // optional, the line of the node + string codes = 6; // optional, the codes of the node + repeated FileNodeID dependencies = 7; // optional, the dependencies of the node + repeated FileNodeID references = 8; // optional, the references of the node + repeated FileNodeID implements = 9; // optional, the implements of the node + repeated FileNodeID groups = 10; // optional, the groups of the node + repeated FileNodeID inherits = 11; // optional, the inherits of the node +} + +// FileNodeID 文件节点标识(用于 get_file_symbol 输出) +message FileNodeID { + string file_path = 1; // file path relative to repo root + string name = 2; // symbol name in the file +} diff --git a/llm/mcp/handler.go b/llm/mcp/handler.go index 3b17ed6d..ad96f295 100644 --- a/llm/mcp/handler.go +++ b/llm/mcp/handler.go @@ -59,10 +59,11 @@ func getASTTools(opts tool.ASTReadToolsOptions) []Tool { ast := tool.NewASTReadTools(opts) return []Tool{ NewTool(tool.ToolListRepos, tool.DescListRepos, tool.SchemaListRepos, ast.ListRepos), - NewTool(tool.ToolGetRepoStructure, tool.DescGetRepoStructure, tool.SchemaGetRepoStructure, ast.GetRepoStructure), - NewTool(tool.ToolGetPackageStructure, tool.DescGetPackageStructure, tool.SchemaGetPackageStructure, ast.GetPackageStructure), + // NewTool(tool.ToolGetRepoStructure, tool.DescGetRepoStructure, tool.SchemaGetRepoStructure, ast.GetRepoStructure), + // NewTool(tool.ToolGetPackageStructure, tool.DescGetPackageStructure, tool.SchemaGetPackageStructure, ast.GetPackageStructure), NewTool(tool.ToolGetFileStructure, tool.DescGetFileStructure, tool.SchemaGetFileStructure, ast.GetFileStructure), - NewTool(tool.ToolGetASTNode, tool.DescGetASTNode, tool.SchemaGetASTNode, ast.GetASTNode), + // NewTool(tool.ToolGetASTNode, tool.DescGetASTNode, tool.SchemaGetASTNode, ast.GetASTNode), + NewTool(tool.ToolGetFileSymbol, tool.DescGetFileSymbol, tool.SchemaGetFileSymbol, ast.GetFileSymbol), } } diff --git a/llm/tool/ast_read.go b/llm/tool/ast_read.go index 520eaca8..2a2efb43 100644 --- a/llm/tool/ast_read.go +++ b/llm/tool/ast_read.go @@ -18,6 +18,7 @@ package tool import ( "context" + "encoding/json" "fmt" "path/filepath" "strings" @@ -42,6 +43,8 @@ const ( DescGetFileStructure = "[STRUCTURE] level3/4: Get file structure with node list. Input: repo_name, file_path from get_repo_structure output. Output: nodes with signatures." ToolGetASTNode = "get_ast_node" DescGetASTNode = "[ANALYSIS] level4/4: Get detailed AST node info. Input: repo_name, node_ids from previous calls. Output: codes, dependencies, references, implementations." + ToolGetFileSymbol = "get_file_symbol" + DescGetFileSymbol = "[ANALYSIS] level4/4: Get detailed AST node info by file path and symbol name. Input: repo_name, file_path, name. Output: codes, dependencies, references, implementations." // ToolWriteASTNode = "write_ast_node" ) @@ -51,6 +54,7 @@ var ( SchemaGetPackageStructure = GetJSONSchema(GetPackageStructReq{}) SchemaGetFileStructure = GetJSONSchema(GetFileStructReq{}) SchemaGetASTNode = GetJSONSchema(GetASTNodeReq{}) + SchemaGetFileSymbol = GetJSONSchema(GetFileSymbolReq{}) ) type ASTReadToolsOptions struct { @@ -150,6 +154,16 @@ func NewASTReadTools(opts ASTReadToolsOptions) *ASTReadTools { panic(err) } ret.tools[ToolGetASTNode] = tt + + tt, err = utils.InferTool(ToolGetFileSymbol, + string(DescGetFileSymbol), + ret.GetFileSymbol, utils.WithMarshalOutput(func(ctx context.Context, output interface{}) (string, error) { + return abutil.MarshalJSONIndent(output) + })) + if err != nil { + panic(err) + } + ret.tools[ToolGetFileSymbol] = tt return ret } @@ -243,6 +257,78 @@ func (n NodeID) Identity() uniast.Identity { } } +// FileNodeID 文件节点标识(用于 get_file_symbol 输出) +type FileNodeID struct { + FilePath string `json:"file_path" jsonschema:"description=file path relative to repo root"` + Name string `json:"name" jsonschema:"description=symbol name in the file"` +} + +// fileNodeIDGroupByPath 控制是否按 file_path 分组输出(默认 true) +var fileNodeIDGroupByPath = true + +// SetFileNodeIDGroupByPath 设置是否按 file_path 分组输出 +func SetFileNodeIDGroupByPath(group bool) { + fileNodeIDGroupByPath = group +} + +// fileNodeGroup 用于聚合相同 file_path 的 name(私有) +type fileNodeGroup struct { + FilePath string `json:"file_path"` + Names []string `json:"names"` +} + +// groupFileNodeIDs 将 []FileNodeID 转换为 []fileNodeGroup +func groupFileNodeIDs(nodeIDs []FileNodeID) []fileNodeGroup { + groupMap := make(map[string]*fileNodeGroup) + + for _, nid := range nodeIDs { + key := nid.FilePath + + if group, exists := groupMap[key]; exists { + group.Names = append(group.Names, nid.Name) + } else { + groupMap[key] = &fileNodeGroup{ + FilePath: nid.FilePath, + Names: []string{nid.Name}, + } + } + } + + result := make([]fileNodeGroup, 0, len(groupMap)) + for _, group := range groupMap { + result = append(result, *group) + } + + return result +} + +type _FileNodeID FileNodeID + +func (f FileNodeID) MarshalJSON() ([]byte, error) { + if fileNodeIDGroupByPath { + return json.Marshal(fileNodeGroup{ + FilePath: f.FilePath, + Names: []string{f.Name}, + }) + } + return json.Marshal(_FileNodeID(f)) +} + +// convertNodeIDs 将 uniast.Relation 转换为 FileNodeID +func convertNodeIDs(repo *uniast.Repository, relations []uniast.Relation) []FileNodeID { + result := make([]FileNodeID, 0, len(relations)) + for _, rel := range relations { + if n := repo.GetNode(rel.Identity); n != nil { + fl := n.FileLine() + result = append(result, FileNodeID{ + FilePath: fl.File, + Name: rel.Identity.Name, + }) + } + } + return result +} + func (t *ASTReadTools) getRepoAST(repoName string) (*uniast.Repository, error) { repo, ok := t.repos.Load(repoName) if !ok { @@ -453,6 +539,57 @@ type GetASTNodeResp struct { Error string `json:"error,omitempty" jsonschema:"description=the error message"` } +type GetFileSymbolReq struct { + RepoName string `json:"repo_name" jsonschema:"description=the name of the repository (output of list_repos tool)"` + FilePath string `json:"file_path" jsonschema:"description=the file path (output of get_repo_structure tool)"` + Name string `json:"name" jsonschema:"description=the name of the symbol (function, type, or variable) to query"` +} + +type GetFileSymbolResp struct { + Node FileNodeStruct `json:"node" jsonschema:"description=the ast node"` + Error string `json:"error,omitempty" jsonschema:"description=the error message"` +} + +// FileNodeStruct 文件节点结构(使用 FileNodeID) +type FileNodeStruct struct { + Name string `json:"name" jsonschema:"description=the name of the node"` + Type string `json:"type,omitempty" jsonschema:"description=the type of the node"` + Signature string `json:"signature,omitempty" jsonschema:"description=the func signature of the node"` + File string `json:"file,omitempty" jsonschema:"description=the file path of the node"` + Line int `json:"line,omitempty" jsonschema:"description=the line of the node"` + Codes string `json:"codes,omitempty" jsonschema:"description=the codes of the node"` + Dependencies []FileNodeID `json:"dependencies,omitempty" jsonschema:"description=the dependencies of the node"` + References []FileNodeID `json:"references,omitempty" jsonschema:"description=the references of the node"` + Implements []FileNodeID `json:"implements,omitempty" jsonschema:"description=the implements of the node"` + Groups []FileNodeID `json:"groups,omitempty" jsonschema:"description=the groups of the node"` + Inherits []FileNodeID `json:"inherits,omitempty" jsonschema:"description=the inherits of the node"` +} + +// MarshalJSON 自定义JSON序列化,实现所有关系字段的分组输出 +type _FileNodeStruct FileNodeStruct + +func (n FileNodeStruct) MarshalJSON() ([]byte, error) { + if fileNodeIDGroupByPath { + aux := &struct { + Dependencies []fileNodeGroup `json:"dependencies,omitempty"` + References []fileNodeGroup `json:"references,omitempty"` + Implements []fileNodeGroup `json:"implements,omitempty"` + Groups []fileNodeGroup `json:"groups,omitempty"` + Inherits []fileNodeGroup `json:"inherits,omitempty"` + *_FileNodeStruct + }{ + Dependencies: groupFileNodeIDs(n.Dependencies), + References: groupFileNodeIDs(n.References), + Implements: groupFileNodeIDs(n.Implements), + Groups: groupFileNodeIDs(n.Groups), + Inherits: groupFileNodeIDs(n.Inherits), + _FileNodeStruct: (*_FileNodeStruct)(&n), + } + return json.Marshal(aux) + } + return json.Marshal(_FileNodeStruct(n)) +} + func (t *ASTReadTools) GetASTNode(_ context.Context, params GetASTNodeReq) (*GetASTNodeResp, error) { log.Debug("get ast node, req: %v", abutil.MarshalJSONIndentNoError(params)) @@ -514,3 +651,65 @@ func (t *ASTReadTools) GetASTNode(_ context.Context, params GetASTNodeReq) (*Get log.Debug("get repo structure, resp: %v", abutil.MarshalJSONIndentNoError(resp)) return resp, nil } + +// GetFileSymbol get detailed AST node info by file path and symbol name +func (t *ASTReadTools) GetFileSymbol(_ context.Context, req GetFileSymbolReq) (*GetFileSymbolResp, error) { + log.Debug("get file symbol, req: %v", abutil.MarshalJSONIndentNoError(req)) + + // 加载仓库 + repo, err := t.getRepoAST(req.RepoName) + if err != nil { + return &GetFileSymbolResp{ + Error: err.Error(), + }, nil + } + + // 查找文件 + file, _ := repo.GetFile(req.FilePath) + if file == nil { + return &GetFileSymbolResp{ + Error: fmt.Errorf("file '%s' not found. Use 'get_repo_structure' to get valid file paths", req.FilePath).Error(), + }, nil + } + + // 在文件中查找符号 + nodes := repo.GetFileNodes(req.FilePath) + var targetNode *uniast.Node + var found bool + + for _, node := range nodes { + if node.Identity.Name == req.Name { + targetNode = node + found = true + break + } + } + + if !found { + return &GetFileSymbolResp{ + Error: fmt.Sprintf("symbol '%s' not found in file '%s'. Use 'get_file_structure' to list all symbols in the file", req.Name, req.FilePath), + }, nil + } + + // 构建 FileNodeStruct + fl := targetNode.FileLine() + nodeStruct := FileNodeStruct{ + Name: targetNode.Identity.Name, + Type: targetNode.Type.String(), + File: fl.File, + Line: fl.Line, + Codes: targetNode.Content(), + Signature: targetNode.Signature(), + // 使用抽象函数转换所有关系字段 + Dependencies: convertNodeIDs(repo, targetNode.Dependencies), + References: convertNodeIDs(repo, targetNode.References), + Implements: convertNodeIDs(repo, targetNode.Implements), + Inherits: convertNodeIDs(repo, targetNode.Inherits), + Groups: convertNodeIDs(repo, targetNode.Groups), + } + + log.Debug("get file symbol, resp: %v", abutil.MarshalJSONIndentNoError(&GetFileSymbolResp{Node: nodeStruct})) + return &GetFileSymbolResp{ + Node: nodeStruct, + }, nil +} From ef3a0445be09ca44c7d0cc58990563c61ad1632b Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 28 Feb 2026 15:49:47 +0800 Subject: [PATCH 02/21] tree_repo: list available file-paths --- llm/mcp/handler.go | 1 + llm/tool/ast_read.go | 82 +++++++++++++++++++++++++++++++++++++++++--- 2 files changed, 78 insertions(+), 5 deletions(-) diff --git a/llm/mcp/handler.go b/llm/mcp/handler.go index ad96f295..ffe4da47 100644 --- a/llm/mcp/handler.go +++ b/llm/mcp/handler.go @@ -61,6 +61,7 @@ func getASTTools(opts tool.ASTReadToolsOptions) []Tool { NewTool(tool.ToolListRepos, tool.DescListRepos, tool.SchemaListRepos, ast.ListRepos), // NewTool(tool.ToolGetRepoStructure, tool.DescGetRepoStructure, tool.SchemaGetRepoStructure, ast.GetRepoStructure), // NewTool(tool.ToolGetPackageStructure, tool.DescGetPackageStructure, tool.SchemaGetPackageStructure, ast.GetPackageStructure), + NewTool(tool.ToolTreeRepo, tool.DescTreeRepo, tool.SchemaTreeRepo, ast.TreeRepo), NewTool(tool.ToolGetFileStructure, tool.DescGetFileStructure, tool.SchemaGetFileStructure, ast.GetFileStructure), // NewTool(tool.ToolGetASTNode, tool.DescGetASTNode, tool.SchemaGetASTNode, ast.GetASTNode), NewTool(tool.ToolGetFileSymbol, tool.DescGetFileSymbol, tool.SchemaGetFileSymbol, ast.GetFileSymbol), diff --git a/llm/tool/ast_read.go b/llm/tool/ast_read.go index 2a2efb43..27f2d04f 100644 --- a/llm/tool/ast_read.go +++ b/llm/tool/ast_read.go @@ -21,6 +21,7 @@ import ( "encoding/json" "fmt" "path/filepath" + "sort" "strings" "sync" @@ -34,17 +35,20 @@ import ( const ( ToolListRepos = "list_repos" - DescListRepos = "[DISCOVERY] level1/4: List all repositories. No parameters required. Always the first step in any analysis workflow." + DescListRepos = "[DISCOVERY] Step 1/4: List available repositories. Always the first step in ABCoder workflow. You MUST call `tree_repo` later." + ToolTreeRepo = "tree_repo" + DescTreeRepo = "[STRUCTURE] Step 2/4: Get available file_paths of a repo. Input: repo_name from `list_repos` output. Output: available file_paths. You MUST call `get_file_structure` later." + ToolGetFileStructure = "get_file_structure" + DescGetFileStructure = "[STRUCTURE] Step 3/4: Get available symbol names of a file. Input: repo_name, file_path from `tree_repo` output. Output: symbol names with signatures. You MUST call `get_file_symbol` later." + ToolGetFileSymbol = "get_file_symbol" + DescGetFileSymbol = "[ANALYSIS] Step 4/4: Get symbol's code, dependencies and references; use refer/depend's file_path and name as next `get_file_symbol` input. Input: repo_name, file_path, name. Output: codes, dependencies, references. You MUST call `get_file_symbol` with refers/depends file_path and name to check its code, call-chain or data-flow detail." + ToolGetRepoStructure = "get_repo_structure" DescGetRepoStructure = "[STRUCTURE] level2/4: Get repository structure. Input: repo_name from list_repos output. Output: modules with packages and files." ToolGetPackageStructure = "get_package_structure" DescGetPackageStructure = "[STRUCTURE] level3/4: Get package structure with node_ids. Input: repo_name, mod_path, pkg_path from get_repo_structure output. Output: files with node_ids." - ToolGetFileStructure = "get_file_structure" - DescGetFileStructure = "[STRUCTURE] level3/4: Get file structure with node list. Input: repo_name, file_path from get_repo_structure output. Output: nodes with signatures." ToolGetASTNode = "get_ast_node" DescGetASTNode = "[ANALYSIS] level4/4: Get detailed AST node info. Input: repo_name, node_ids from previous calls. Output: codes, dependencies, references, implementations." - ToolGetFileSymbol = "get_file_symbol" - DescGetFileSymbol = "[ANALYSIS] level4/4: Get detailed AST node info by file path and symbol name. Input: repo_name, file_path, name. Output: codes, dependencies, references, implementations." // ToolWriteASTNode = "write_ast_node" ) @@ -55,6 +59,7 @@ var ( SchemaGetFileStructure = GetJSONSchema(GetFileStructReq{}) SchemaGetASTNode = GetJSONSchema(GetASTNodeReq{}) SchemaGetFileSymbol = GetJSONSchema(GetFileSymbolReq{}) + SchemaTreeRepo = GetJSONSchema(TreeRepoReq{}) ) type ASTReadToolsOptions struct { @@ -164,6 +169,16 @@ func NewASTReadTools(opts ASTReadToolsOptions) *ASTReadTools { panic(err) } ret.tools[ToolGetFileSymbol] = tt + + tt, err = utils.InferTool(ToolTreeRepo, + DescTreeRepo, + ret.TreeRepo, utils.WithMarshalOutput(func(ctx context.Context, output interface{}) (string, error) { + return abutil.MarshalJSONIndent(output) + })) + if err != nil { + panic(err) + } + ret.tools[ToolTreeRepo] = tt return ret } @@ -713,3 +728,60 @@ func (t *ASTReadTools) GetFileSymbol(_ context.Context, req GetFileSymbolReq) (* Node: nodeStruct, }, nil } + +type TreeRepoReq struct { + RepoName string `json:"repo_name" jsonschema:"description=the name of the repository (output of list_repos tool)"` +} + +type TreeRepoResp struct { + Files map[string][]string `json:"files" jsonschema:"description=map of directory path to file list (directories end with '/')"` + Error string `json:"error,omitempty" jsonschema:"description=the error message"` +} + +// TreeRepo returns a map of package paths to file lists, with directories ending in '/' +func (t *ASTReadTools) TreeRepo(_ context.Context, req TreeRepoReq) (*TreeRepoResp, error) { + log.Debug("tree repo, req: %v", abutil.MarshalJSONIndentNoError(req)) + repo, err := t.getRepoAST(req.RepoName) + if err != nil { + return &TreeRepoResp{ + Error: err.Error(), + }, nil + } + + // 收集所有文件,按目录聚合 + files := make(map[string][]string) + for _, mod := range repo.Modules { + if mod.IsExternal() { + continue + } + for _, file := range mod.Files { + if file.Package == "" { + continue + } + // 过滤掉非当前仓库的文件(以 .. 开头或包含 ..) + if strings.HasPrefix(file.Path, "..") { + continue + } + // 获取文件的目录路径 + dir := filepath.Dir(file.Path) + if dir == "." { + dir = "./" + } + // 添加 '/' 后缀 + if dir != "" && dir != "./" && !strings.HasSuffix(dir, "/") { + dir = dir + "/" + } + // 获取文件名 + name := filepath.Base(file.Path) + files[dir] = append(files[dir], name) + } + } + + // 对每个目录下的文件列表进行排序 + for dir := range files { + sort.Strings(files[dir]) + } + + log.Debug("tree repo, resp: %v", abutil.MarshalJSONIndentNoError(&TreeRepoResp{Files: files})) + return &TreeRepoResp{Files: files}, nil +} From a6c92643b478f80bbc1d9ce8902279f4d8965662 Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 28 Feb 2026 16:12:23 +0800 Subject: [PATCH 03/21] abcoder parse /path/to/repo: default write into -path-to-repo.json, write into .tmp then rename to .json to avoid instable parsing-read error --- main.go | 61 ++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 52 insertions(+), 9 deletions(-) diff --git a/main.go b/main.go index c20057e7..b4a09230 100644 --- a/main.go +++ b/main.go @@ -98,10 +98,11 @@ Use this command to verify installation or when reporting issues.`, func newParseCmd() *cobra.Command { var ( - flagOutput string - flagLsp string - javaHome string - opts lang.ParseOptions + flagOutput string + flagStdout bool + flagLsp string + javaHome string + opts lang.ParseOptions ) cmd := &cobra.Command{ @@ -109,7 +110,7 @@ func newParseCmd() *cobra.Command { Short: "Parse repository and export to UniAST JSON format", Long: `Parse the specified repository and generate its Universal AST representation. -By default, outputs to stdout. Use --output to write to a file. +By default, saves to ~/.asts/.json. Use --stdout to output to stdout, use --output to write to a file. Language Support: go - Go projects @@ -140,11 +141,34 @@ Language Support: language := uniast.NewLanguage(args[0]) uri := args[1] + // Convert to absolute path for consistent naming + absPath, err := filepath.Abs(uri) + if err != nil { + log.Error("Failed to get absolute path: %v\n", err) + return err + } + + // Determine output path + outputPath := flagOutput + if outputPath == "" && !flagStdout { + // Default: save to ~/.asts/ + astsDir := filepath.Join(os.Getenv("HOME"), ".asts") + if err := os.MkdirAll(astsDir, 0755); err != nil { + log.Error("Failed to create asts directory: %v\n", err) + return err + } + filename := sanitizeFilename(absPath) + outputPath = filepath.Join(astsDir, filename) + } + if language == uniast.TypeScript { - if err := parseTSProject(context.Background(), uri, opts, flagOutput); err != nil { + if err := parseTSProject(context.Background(), uri, opts, outputPath); err != nil { log.Error("Failed to parse: %v\n", err) return err } + if outputPath != "" && !flagStdout { + fmt.Fprintf(os.Stdout, "AST saved to %s\n", outputPath) + } return nil } @@ -165,12 +189,23 @@ Language Support: return err } - if flagOutput != "" { - if err := utils.MustWriteFile(flagOutput, out); err != nil { + if flagStdout { + // Explicitly output to stdout + fmt.Fprintf(os.Stdout, "%s\n", out) + } else if outputPath != "" { + // Write to .tmp first, then rename to .json + tmpPath := outputPath + ".tmp" + if err := utils.MustWriteFile(tmpPath, out); err != nil { log.Error("Failed to write output: %v\n", err) return err } + if err := os.Rename(tmpPath, outputPath); err != nil { + log.Error("Failed to rename temp file: %v\n", err) + return err + } + fmt.Fprintf(os.Stdout, "AST saved to %s\n", outputPath) } else { + // Fallback to stdout (should not happen with new logic) fmt.Fprintf(os.Stdout, "%s\n", out) } @@ -179,7 +214,8 @@ Language Support: } // Flags - cmd.Flags().StringVarP(&flagOutput, "output", "o", "", "Output path for UniAST JSON (default: stdout).") + cmd.Flags().StringVarP(&flagOutput, "output", "o", "", "Output path for UniAST JSON (default: ~/.asts/.json).") + cmd.Flags().BoolVar(&flagStdout, "stdout", false, "Output to stdout instead of saving to file.") cmd.Flags().StringVar(&flagLsp, "lsp", "", "Path to Language Server Protocol executable. Required for languages with LSP support (e.g., Java).") cmd.Flags().StringVar(&javaHome, "java-home", "", "Java installation directory (JAVA_HOME). Required when using LSP for Java.") cmd.Flags().BoolVar(&opts.LoadExternalSymbol, "load-external-symbol", false, "Load external symbol references into AST results (slower but more complete).") @@ -194,6 +230,13 @@ Language Support: return cmd } +// sanitizeFilename converts absolute path to safe filename +// e.g., /Users/bytedance/astRepo/golang/abcoder -> -Users-bytedance-astRepo-golang-abcoder.json +func sanitizeFilename(path string) string { + name := strings.ReplaceAll(path, "/", "-") + return name + ".json" +} + func newWriteCmd() *cobra.Command { var ( flagOutput string From 6a089038b265641214bc7ee28eb801d1c7b44e21 Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 28 Feb 2026 17:56:40 +0800 Subject: [PATCH 04/21] abcoder cli for skill --- .../abcoder__get_file_structure/SKILL.md | 46 ++++++++++ .../skills/abcoder__get_file_symbol/SKILL.md | 74 +++++++++++++++ .../skills/abcoder__list_repos/SKILL.md | 29 ++++++ .../skills/abcoder__tree_repo/SKILL.md | 16 ++++ internal/cmd/cli/cli.go | 39 ++++++++ internal/cmd/cli/get_file_structure.go | 61 +++++++++++++ internal/cmd/cli/get_file_symbol.go | 63 +++++++++++++ internal/cmd/cli/list_repos.go | 89 +++++++++++++++++++ internal/cmd/cli/tree_repo.go | 57 ++++++++++++ internal/cmd/cli/utils.go | 38 ++++++++ llm/tool/ast_read.go | 33 +++---- main.go | 3 + 12 files changed, 533 insertions(+), 15 deletions(-) create mode 100644 internal/cmd/assets/.claude/skills/abcoder__get_file_structure/SKILL.md create mode 100644 internal/cmd/assets/.claude/skills/abcoder__get_file_symbol/SKILL.md create mode 100644 internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md create mode 100644 internal/cmd/assets/.claude/skills/abcoder__tree_repo/SKILL.md create mode 100644 internal/cmd/cli/cli.go create mode 100644 internal/cmd/cli/get_file_structure.go create mode 100644 internal/cmd/cli/get_file_symbol.go create mode 100644 internal/cmd/cli/list_repos.go create mode 100644 internal/cmd/cli/tree_repo.go create mode 100644 internal/cmd/cli/utils.go diff --git a/internal/cmd/assets/.claude/skills/abcoder__get_file_structure/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__get_file_structure/SKILL.md new file mode 100644 index 00000000..9d6653e7 --- /dev/null +++ b/internal/cmd/assets/.claude/skills/abcoder__get_file_structure/SKILL.md @@ -0,0 +1,46 @@ +--- +name: skill__abcoder__get_file_structure +description: skill__abcoder__get_file_structure `abcoder cli get_file_structure 'repo_name' 'file_path'` [STRUCTURE] Step 3/4: Get available symbol names of a file. Input: repo_name, file_path from `tree_repo` output. Output: symbol names with signatures. You MUST call `get_file_symbol` later. +--- + +Execute the get_file_structure command to examine file-level nodes: + +```bash +abcoder cli get_file_structure 'repo_name' 'file_path' +``` + +**Expected Output:** +- Complete node list with type, signature, line +- Imports for the file +- Node IDs for detailed analysis + +**Parameters:** +- `repo_name` (required): Repository name from `list_repos` +- `file_path` (required): Relative file path from `get_repo_structure` +``` +{ + "description": "[STRUCTURE] level3/4: Get file structure with node list. Input: repo_name, file_path from get_repo_structure output. Output: nodes with signatures.", + "inputSchema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "properties": { + "repo_name": { + "type": "string", + "description": "the name of the repository (output of list_repos tool)" + }, + "file_path": { + "type": "string", + "description": "relative file path (output of get_repo_structure tool" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "repo_name", + "file_path" + ] + }, + "name": "get_file_structure" +} +``` + +This tool is **Level 3** in the ABCoder discovery hierarchy. Next: Use [`skill__abcoder__get_file_symbol`](~/.claude/skills/skill__abcoder__get_file_symbol/SKILL.md) to get detailed code information. diff --git a/internal/cmd/assets/.claude/skills/abcoder__get_file_symbol/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__get_file_symbol/SKILL.md new file mode 100644 index 00000000..5a2cfa58 --- /dev/null +++ b/internal/cmd/assets/.claude/skills/abcoder__get_file_symbol/SKILL.md @@ -0,0 +1,74 @@ +--- +name: skill__abcoder__get_file_symbol +description: skill__abcoder_get_file_symbol `abcoder cli get_file_symbol 'repo_name' 'relative_file_path' 'symbol_name'` [ANALYSIS] Step 4/4: Get symbol's code, dependencies and references; use refer/depend's file_path and name as next `get_file_symbol` input. Input: repo_name, file_path, name. Output: codes, dependencies, references. You MUST call `get_file_symbol` with refers/depends file_path and name to check its code, call-chain or data-flow detail. +--- + +Execute the get_file_symbol command to get detailed symbol information: + +```bash +abcoder cli get_file_symbol 'repo_name' 'relative_file_path' 'symbol_name' +``` + +**Expected Output:** +``` +{ + "nodes": [ + { + "file_path": "string", + "name": "string", + "type": "string", + "line": "number", + "codes": "string", + "dependencies": [ + { + "file_path": "string", + "names": ["string"] + } + ], + "references": [ + { + "file_path": "string", + "names": ["string"] + } + ] + } + ] +} +``` + +**Parameters:** +- `repo_name` (required): Repository name from `list_repos` +- `file_path` (required): File path from `get_repo_structure` +- `symbol_name` (required): Name of the symbol to query +``` +{ + "description": "[ANALYSIS] level4/4: Get detailed AST node info by file path and symbol name. Output: codes, dependencies, references, implementations (all grouped by file_path).", + "inputSchema": { + "$schema": "https://json-schema.org/draft/2020-12/schema", + "properties": { + "repo_name": { + "type": "string", + "description": "the name of the repository (output of list_repos tool)" + }, + "file_path": { + "type": "string", + "description": "the file path (output of get_repo_structure tool)" + }, + "symbol_name": { + "type": "string", + "description": "the name of the symbol (function, type, or variable) to query" + } + }, + "additionalProperties": false, + "type": "object", + "required": [ + "repo_name", + "file_path", + "symbol_name" + ] + }, + "name": "get_file_symbol" +} +``` + +**Recursive Analysis:** Use this tool recursively to trace code calling chains. From the `dependencies` and `references` arrays, extract the `file_path` and `symbol_name` for related nodes, then call `get_file_symbol` again to dive deeper into the calling chain. diff --git a/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md new file mode 100644 index 00000000..c01809fd --- /dev/null +++ b/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md @@ -0,0 +1,29 @@ +--- +name: skill__abcoder__list_repos +description: skill__abcoder__list_repos `abcoder cli list_repos` [DISCOVERY] Step 1/4: List available repositories. Always the first step in ABCoder workflow. You MUST call `tree_repo` later. +--- + +Execute the list_repos command to discover all available repositories: + +```bash +abcoder cli list_repos +``` + +## Workflow Context + +This tool is **Level 1** in the 4-level ABCoder discovery hierarchy: + +1. **Level 1 (This Tool)**: `list_repos` - List all repositories +2. **Level 2**: `tree_repo` - Get repository structure +3. **Level 3**: `get_file_structure` - Get file nodes details +4. **Level 4**: `get_file_symbol` - Get detailed AST node information + +## Usage Pattern +Output +``` +{ + "repo_names": { + "array[i]": "string" + } +} +``` diff --git a/internal/cmd/assets/.claude/skills/abcoder__tree_repo/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__tree_repo/SKILL.md new file mode 100644 index 00000000..e1c014c3 --- /dev/null +++ b/internal/cmd/assets/.claude/skills/abcoder__tree_repo/SKILL.md @@ -0,0 +1,16 @@ +--- +name: skill__abcoder__tree_repo +description: skill__abcoder__tree_repo `abcoder cli tree_repo 'repo_name' [DISCOVERY] Level 2/4: [STRUCTURE] Step 2/4: Get available file_paths of a repo. Input: repo_name from `list_repos` output. Output: available file_paths. You MUST call `get_file_structure` later. +--- + +Execute the tree_repo command to examine repository-level structure: + +```bash +abcoder cli tree_repo 'repo_name' +``` + +**Expected Output:** +- Complete repository file paths + +**Parameters:** +- `repo_name` (required): Repository name from `list_repos` output diff --git a/internal/cmd/cli/cli.go b/internal/cmd/cli/cli.go new file mode 100644 index 00000000..0d29569d --- /dev/null +++ b/internal/cmd/cli/cli.go @@ -0,0 +1,39 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,. +// See the License either express or implied for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "github.com/spf13/cobra" +) + +// NewCliCmd returns the parent command for CLI operations. +func NewCliCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "cli", + Short: "CLI commands for AST analysis", + Long: `CLI commands for directly querying AST data without MCP protocol. + +These commands provide direct access to repository, file, and symbol information.`, + Example: `abcoder cli list-repos`, + } + + // Add subcommands + cmd.AddCommand(newListReposCmd()) + cmd.AddCommand(newTreeRepoCmd()) + cmd.AddCommand(newGetFileStructureCmd()) + cmd.AddCommand(newGetFileSymbolCmd()) + + return cmd +} diff --git a/internal/cmd/cli/get_file_structure.go b/internal/cmd/cli/get_file_structure.go new file mode 100644 index 00000000..0bec8e72 --- /dev/null +++ b/internal/cmd/cli/get_file_structure.go @@ -0,0 +1,61 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/cloudwego/abcoder/llm/tool" + "github.com/spf13/cobra" +) + +func newGetFileStructureCmd() *cobra.Command { + return &cobra.Command{ + Use: "get_file_structure ", + Short: "Get symbol names of a file", + Long: `Get the symbol names and signatures of a file in the repository. + +Returns a list of functions, types, and variables defined in the file.`, + Example: `abcoder cli get_file_structure myrepo src/main.go`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + repoName := args[0] + filePath := args[1] + tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ + RepoASTsDir: astsDir, + DisableWatch: true, + }) + resp, err := tools.GetFileStructure(context.Background(), tool.GetFileStructReq{ + RepoName: repoName, + FilePath: filePath, + }) + if err != nil { + return fmt.Errorf("failed to get file structure: %w", err) + } + + b, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/get_file_symbol.go b/internal/cmd/cli/get_file_symbol.go new file mode 100644 index 00000000..3342916f --- /dev/null +++ b/internal/cmd/cli/get_file_symbol.go @@ -0,0 +1,63 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/cloudwego/abcoder/llm/tool" + "github.com/spf13/cobra" +) + +func newGetFileSymbolCmd() *cobra.Command { + return &cobra.Command{ + Use: "get_file_symbol ", + Short: "Get detailed symbol information", + Long: `Get detailed information about a symbol including code, dependencies, and references. + +Returns the symbol's code, type, line number, and relationship with other symbols.`, + Example: `abcoder cli get_file_symbol myrepo src/main.go MyFunction`, + Args: cobra.ExactArgs(3), + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + repoName := args[0] + filePath := args[1] + name := args[2] + tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ + RepoASTsDir: astsDir, + DisableWatch: true, + }) + resp, err := tools.GetFileSymbol(context.Background(), tool.GetFileSymbolReq{ + RepoName: repoName, + FilePath: filePath, + Name: name, + }) + if err != nil { + return fmt.Errorf("failed to get file symbol: %w", err) + } + + b, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/list_repos.go b/internal/cmd/cli/list_repos.go new file mode 100644 index 00000000..d711f029 --- /dev/null +++ b/internal/cmd/cli/list_repos.go @@ -0,0 +1,89 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "strings" + + "github.com/bytedance/sonic" + "github.com/cloudwego/abcoder/llm/tool" + "github.com/spf13/cobra" +) + +func newListReposCmd() *cobra.Command { + return &cobra.Command{ + Use: "list_repos", + Short: "List available repositories", + Long: `List all available repositories in the AST directory. + +The repositories are loaded from .repo_index.json or *.json files in the --asts-dir directory.`, + Example: `abcoder cli list-repos`, + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + // 尝试从 .repo_index.json 读取映射 + indexFile := filepath.Join(astsDir, ".repo_index.json") + var repoNames []string + + if data, err := os.ReadFile(indexFile); err == nil { + // 解析 repo_index.json + var index struct { + Mappings map[string]string `json:"mappings"` + } + if err := json.Unmarshal(data, &index); err == nil && index.Mappings != nil { + for name := range index.Mappings { + repoNames = append(repoNames, name) + } + } + } + + // 如果没有从 index 读取到,回退到扫描 JSON 文件,使用 sonic 快速读取 id + if len(repoNames) == 0 { + files, err := filepath.Glob(filepath.Join(astsDir, "*.json")) + if err != nil { + return err + } + for _, f := range files { + // 跳过 _repo_index.json + if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") { + continue + } + // 使用 sonic 快速读取 id 字段,避免加载整个 JSON + if data, err := os.ReadFile(f); err == nil { + val, err := sonic.Get(data, "id") + if err == nil { + id, err := val.String() + if err == nil && id != "" { + repoNames = append(repoNames, id) + } + } + } + } + } + + resp := tool.ListReposResp{RepoNames: repoNames} + b, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/tree_repo.go b/internal/cmd/cli/tree_repo.go new file mode 100644 index 00000000..b860c8c4 --- /dev/null +++ b/internal/cmd/cli/tree_repo.go @@ -0,0 +1,57 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "context" + "encoding/json" + "fmt" + "os" + + "github.com/cloudwego/abcoder/llm/tool" + "github.com/spf13/cobra" +) + +func newTreeRepoCmd() *cobra.Command { + return &cobra.Command{ + Use: "tree_repo ", + Short: "Get file tree of a repository", + Long: `Get the file tree structure of a repository. + +Returns a map of directories to file lists.`, + Example: `abcoder cli tree_repo myrepo`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + repoName := args[0] + tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ + RepoASTsDir: astsDir, + DisableWatch: true, + }) + resp, err := tools.TreeRepo(context.Background(), tool.TreeRepoReq{RepoName: repoName}) + if err != nil { + return fmt.Errorf("failed to tree repo: %w", err) + } + + b, _ := json.MarshalIndent(resp, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go new file mode 100644 index 00000000..49145c74 --- /dev/null +++ b/internal/cmd/cli/utils.go @@ -0,0 +1,38 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/spf13/cobra" +) + +// getASTsDir returns the ASTs directory path from command flags or default location. +func getASTsDir(cmd *cobra.Command) (string, error) { + astsDir, err := cmd.Flags().GetString("asts-dir") + if err != nil { + return "", err + } + if astsDir == "" { + astsDir = filepath.Join(os.Getenv("HOME"), ".asts") + } + if _, err := os.Stat(astsDir); os.IsNotExist(err) { + return "", fmt.Errorf("ASTs directory does not exist: %s", astsDir) + } + return astsDir, nil +} diff --git a/llm/tool/ast_read.go b/llm/tool/ast_read.go index 27f2d04f..e411f70a 100644 --- a/llm/tool/ast_read.go +++ b/llm/tool/ast_read.go @@ -64,7 +64,8 @@ var ( type ASTReadToolsOptions struct { // PatchOptions patch.Options - RepoASTsDir string + RepoASTsDir string + DisableWatch bool } type ASTReadTools struct { @@ -94,21 +95,23 @@ func NewASTReadTools(opts ASTReadToolsOptions) *ASTReadTools { } } - // add a file watch on the RepoASTsDir - abutil.WatchDir(opts.RepoASTsDir, func(op fsnotify.Op, file string) { - if !strings.HasSuffix(file, ".json") { - return - } - if op&fsnotify.Write != 0 || op&fsnotify.Create != 0 { - if repo, err := uniast.LoadRepo(file); err != nil { - log.Error("Load Uniast JSON file failed: %v", err) - } else { - ret.repos.Store(repo.Name, repo) + // add a file watch on the RepoASTsDir (unless disabled) + if !opts.DisableWatch { + abutil.WatchDir(opts.RepoASTsDir, func(op fsnotify.Op, file string) { + if !strings.HasSuffix(file, ".json") { + return } - } else if op&fsnotify.Remove != 0 { - ret.repos.Delete(filepath.Base(file)) - } - }) + if op&fsnotify.Write != 0 || op&fsnotify.Create != 0 { + if repo, err := uniast.LoadRepo(file); err != nil { + log.Error("Load Uniast JSON file failed: %v", err) + } else { + ret.repos.Store(repo.Name, repo) + } + } else if op&fsnotify.Remove != 0 { + ret.repos.Delete(filepath.Base(file)) + } + }) + } tt, err := utils.InferTool(string(ToolListRepos), DescListRepos, diff --git a/main.go b/main.go index b4a09230..5d37027d 100644 --- a/main.go +++ b/main.go @@ -39,6 +39,7 @@ import ( "strings" internalCmd "github.com/cloudwego/abcoder/internal/cmd" + "github.com/cloudwego/abcoder/internal/cmd/cli" "github.com/cloudwego/abcoder/lang" "github.com/cloudwego/abcoder/lang/log" "github.com/cloudwego/abcoder/lang/uniast" @@ -71,12 +72,14 @@ writing, and analyzing code structures.`, // Global flags cmd.PersistentFlags().BoolP("verbose", "v", false, "Verbose mode.") + cmd.PersistentFlags().String("asts-dir", "", "Base directory for AST files (default: ~/.asts).") // Add subcommands cmd.AddCommand(newVersionCmd()) cmd.AddCommand(newParseCmd()) cmd.AddCommand(newWriteCmd()) cmd.AddCommand(newMcpCmd()) + cmd.AddCommand(cli.NewCliCmd()) cmd.AddCommand(newInitSpecCmd()) cmd.AddCommand(newAgentCmd()) From 5293be6879922e70202a43c24d6c62f8ab525adf Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 28 Feb 2026 11:08:19 +0800 Subject: [PATCH 05/21] Compress Output of get_file_strucutre: display mod&pkg once, display name&line only when node counts of a file > 500 --- go.sum | 63 ------------------------------------ idl/get_file_structure.proto | 52 +++++++++++++++++++++++++++++ llm/tool/ast_read.go | 19 +++++++---- 3 files changed, 64 insertions(+), 70 deletions(-) create mode 100644 idl/get_file_structure.proto diff --git a/go.sum b/go.sum index 2c7b913f..b1f2dfcb 100644 --- a/go.sum +++ b/go.sum @@ -13,15 +13,12 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go/auth v0.7.2/go.mod h1:VEc4p5NNxycWQTMQEDQF0bd6aTMb6VgYDXEwiJJQAbs= -cloud.google.com/go/auth/oauth2adapt v0.2.3/go.mod h1:tMQXOfZzFuNuUxOypHlQEXgdfX5cuhwU+ffUuXRJE8I= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute/metadata v0.5.0/go.mod h1:aHnloV2TPI38yx4s9+wAZhHykWvVCfu7hQbF+9CWoiY= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= @@ -34,10 +31,6 @@ cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohl cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -github.com/Azure/azure-sdk-for-go/sdk/azcore v1.17.0/go.mod h1:XCW7KnZet0Opnr7HccfUw1PLc4CjHqpcaxW8DHklNkQ= -github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.7.0/go.mod h1:9kIvujWAA58nmPmWB1m23fyWic1kYZMxD9CxaWn4Qpg= -github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY= -github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.1.0/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= @@ -53,7 +46,6 @@ github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMx github.com/Shopify/toxiproxy/v2 v2.1.6-0.20210914104332-15ea381dcdae/go.mod h1:/cvHQkZ1fst0EmZnA5dFtiQdWCNCFYzb+uE2vqVgvx0= github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= -github.com/agnivade/levenshtein v1.1.1/go.mod h1:veldBMzWxcCG2ZvUTKD2kJNRdCk5hVbJomOvKkmgYbo= github.com/airbrake/gobrake v3.6.1+incompatible/go.mod h1:wM4gu3Cn0W0K7GUuVWnlXZU11AGBXMILnrdOU8Kn00o= github.com/ajstarks/svgo v0.0.0-20180226025133-644b8db467af/go.mod h1:K08gAheRH3/J6wwsYMMT4xOr94bZjxIelGM0+d/wbFw= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= @@ -64,7 +56,6 @@ github.com/alecthomas/units v0.0.0-20190924025748-f65c72e2690d/go.mod h1:rBZYJk5 github.com/anthropics/anthropic-sdk-go v1.4.0 h1:fU1jKxYbQdQDiEXCxeW5XZRIOwKevn/PMg8Ay1nnUx0= github.com/anthropics/anthropic-sdk-go v1.4.0/go.mod h1:AapDW22irxK2PSumZiQXYUFvsdQgkwIWlpESweWZI/c= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= -github.com/apache/arrow/go/arrow v0.0.0-20211112161151-bc219186db40/go.mod h1:Q7yQnSMnLvcXlZ8RV+jwz/6y1rQTqbX6C82SndT52Zs= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= github.com/armon/go-metrics v0.3.9/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc= @@ -134,8 +125,6 @@ github.com/certifi/gocertifi v0.0.0-20190105021004-abcd57078448/go.mod h1:GJKEex github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/chewxy/hm v1.0.0/go.mod h1:qg9YI4q6Fkj/whwHR1D+bOGeF7SniIP40VweVepLjg0= -github.com/chewxy/math32 v1.11.0/go.mod h1:dOB2rcuFrCn6UHrze36WSLVPKtzPMRAQvBvUwkSsLqs= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -159,22 +148,18 @@ github.com/cloudwego/eino-ext/components/tool/mcp v0.0.3 h1:kT8yynQh8q92BPofkHxx github.com/cloudwego/eino-ext/components/tool/mcp v0.0.3/go.mod h1:D1Yircehgx7em8EH6vw8If+ATjtXl60IpBzVaqFBx3c= github.com/cloudwego/eino-ext/libs/acl/openai v0.0.0-20250626133421-3c142631c961 h1:fGE3RFHaAsrLjA+2fkE0YMsPrkFI6pEKKZmbhD42L7E= github.com/cloudwego/eino-ext/libs/acl/openai v0.0.0-20250626133421-3c142631c961/go.mod h1:iB0W8l+OqKNL5LtJQ9JaGYXekhsxVxrDMfnfD9L+5gc= -github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= -github.com/d4l3k/go-bfloat16 v0.0.0-20211005043715-690c3bdd05f1/go.mod h1:uw2gLcxEuYUlAd/EXyjc/v55nd3+47YAgWbSXVxPrNI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.11.4/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= @@ -183,7 +168,6 @@ github.com/eapache/go-resiliency v1.2.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5m github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= -github.com/emirpasic/gods/v2 v2.0.0-alpha/go.mod h1:W0y4M2dtBB9U5z3YlghmpuUhiaZT2h6yoeE+C1sCp6A= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= @@ -196,7 +180,6 @@ github.com/evanphx/json-patch v0.5.2/go.mod h1:ZWS5hhDbVDyob71nXKNL0+PWn6ToqBHMi github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/fatih/color v1.12.0/go.mod h1:ELkj/draVOlAH/xkhN6mQ50Qd0MPOk5AAr3maGEBuJM= -github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fogleman/gg v1.2.1-0.20190220221249-0403632d5b90/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k= github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g= github.com/franela/goblin v0.0.0-20210519012713-85d372ac71e2/go.mod h1:VzmDKDJVZI3aJmnRI9VjAn9nJ8qPPsN1fqzr9dqInIo= @@ -207,14 +190,10 @@ github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7z github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/gabriel-vasile/mimetype v1.4.3/go.mod h1:d8uq/6HKRL6CGdk+aubisF/M5GcPfT7nKyLpA0lbSSk= github.com/getkin/kin-openapi v0.118.0 h1:z43njxPmJ7TaPpMSCQb7PN0dEYno4tyBPQcrFdHoLuM= github.com/getkin/kin-openapi v0.118.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gin-contrib/cors v1.7.2/go.mod h1:SUJVARKgQ40dmrzgXEVxj2m7Ig1v1qIboQkPDTQ9t2E= -github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-check/check v0.0.0-20180628173108-788fd7840127 h1:0gkP6mzaMqkmpcJYCFOLkIBwI7xFExG03bbkOkCvUPI= github.com/go-check/check v0.0.0-20180628173108-788fd7840127/go.mod h1:9ES+weclKsC9YodN5RgxqK/VD9HM9JsCSh7rNhMZE98= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -229,29 +208,22 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= github.com/go-logfmt/logfmt v0.5.1/go.mod h1:WYhtIu8zTZfxdn5+rREduYbwxfcBr/Vr6KEVveWlfTs= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= -github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.21.0 h1:YgdVicSA9vH5RiHs9TZW5oyafXZFc6+2Vc1rr/O9oNQ= github.com/go-openapi/jsonpointer v0.21.0/go.mod h1:IUyH9l/+uyhIYQ/PXVA41Rexl+kOkAPDdXEYns6fzUY= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.23.0 h1:vsEVJDUo2hPJ2tu0/Xc+4noaxyEffXNIs3cOULZ+GrE= github.com/go-openapi/swag v0.23.0/go.mod h1:esZ8ITTYEsH1V2trKHjAN8Ai7xHb8RV+YSZ577vPjgQ= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-zookeeper/zk v1.0.2/go.mod h1:nOB03cncLtlp4t+UAkGSV+9beXP/akpekBwL+UX1Qcw= -github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.0.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= -github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk= github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -281,13 +253,11 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= -github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= -github.com/google/flatbuffers v24.3.25+incompatible/go.mod h1:1AeVuKshWv4vARoZatz6mlQ0JxURH0Kv5+zNeJKJCa8= github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= @@ -314,12 +284,10 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= -github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/goph/emperror v0.17.2 h1:yLapQcmEsO0ipe9p5TaN22djm3OFV/TfM/fcYP0/J18= @@ -421,8 +389,6 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= @@ -444,7 +410,6 @@ github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Ky github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/meguminnnnnnnnn/go-openai v0.0.0-20250620092828-0d508a1dcdde h1:pq2I0uxUR4lfr4OmqvE8QdHj9UML9b1jZu8L3dI2eu8= github.com/meguminnnnnnnnn/go-openai v0.0.0-20250620092828-0d508a1dcdde/go.mod h1:CqSFsV6AkkL2fixd25WYjRAolns+gQrY1x/Cz9c30v8= @@ -482,10 +447,8 @@ github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OS github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nikolalohinski/gonja v1.5.3 h1:GsA+EEaZDZPGJ8JtpeGN78jidhOlxeJROpqMT9fTj9c= github.com/nikolalohinski/gonja v1.5.3/go.mod h1:RmjwxNiXAEqcq1HeK5SSMmqFJvKOfTfXhkJv6YBtPa4= -github.com/nlpodyssey/gopickle v0.3.0/go.mod h1:f070HJ/yR+eLi5WmM1OXJEGaTpuJEUiib19olXgYha0= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/ollama/ollama v0.5.12 h1:qM+k/ozyHLJzEQoAEPrUQ0qXqsgDEEdpIVwuwScrd2U= github.com/ollama/ollama v0.5.12/go.mod h1:ibdmDvb/TjKY1OArBWIazL3pd1DHTk8eG2MMjEkWhiI= github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= @@ -493,13 +456,11 @@ github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk= github.com/onsi/ginkgo v1.16.2/go.mod h1:CObGmKUOKaSC0RjmoAK7tKyn4Azo5P2IWuoMnvwxz1E= -github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.13.0/go.mod h1:lRk9szgn8TxENtWd0Tp4c3wjlRfMTMH27I+3Je41yGY= -github.com/onsi/gomega v1.27.3/go.mod h1:5vG284IBtfDAmDyrK+eGyZmUgUlmi+Wngqo557cZ6Gw= github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= github.com/openai/openai-go v1.10.1 h1:7VR8z1foqJDjlaFZsNH5zZIYTWKYz97tdsVSzXDHQck= github.com/openai/openai-go v1.10.1/go.mod h1:g461MYGXEXBVdV5SaR/5tNzNbSfwTBBefwc+LlDCK0Y= @@ -507,7 +468,6 @@ github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYr github.com/openzipkin/zipkin-go v0.2.5/go.mod h1:KpXfKdgRDnnhsxw4pNIH9Md5lyFqKUa4YDFlwRYAMyE= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= -github.com/pdevine/tensor v0.0.0-20240510204454-f88f4562727c/go.mod h1:PSojXDXF7TbgQiD6kkd98IHOS0QqTyUEaWRiS8+BLu8= github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M= github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc= github.com/performancecopilot/speed/v4 v4.0.0/go.mod h1:qxrSyuDGrTOWfV+uKRFhfxw6h/4HXRGUiZiufxo49BM= @@ -516,7 +476,6 @@ github.com/perimeterx/marshmallow v1.1.5 h1:a2LALqQ1BlHM8PZblsDdidgv1mWi1DgC2UmX github.com/perimeterx/marshmallow v1.1.5/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.6.1+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -549,7 +508,6 @@ github.com/prometheus/procfs v0.6.0/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1 github.com/prometheus/procfs v0.7.3/go.mod h1:cz+aTbrPOrUb4q7XlbU9ygM+/jj0fzG6c1xBZuNvfVA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= @@ -595,7 +553,6 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+ github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -637,11 +594,9 @@ github.com/wk8/go-ordered-map/v2 v2.1.8 h1:5h/BUHu93oj4gIdvHHHGsScSTMijfx5PeYkE/ github.com/wk8/go-ordered-map/v2 v2.1.8/go.mod h1:5nJHM5DyteebpVlHnWMV0rPz6Zp7+xBAnxjb1X5vnTw= github.com/x-cray/logrus-prefixed-formatter v0.5.2 h1:00txxvfBM9muc0jiLIEAkAcIMJzfthRT6usrui8uGmg= github.com/x-cray/logrus-prefixed-formatter v0.5.2/go.mod h1:2duySbKsL6M18s5GU7VPsoEPHyzalCE06qoARUCeBBE= -github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= github.com/xdg-go/scram v1.0.2/go.mod h1:1WAq6h33pAW+iRreB34OORO2Nf7qel3VV3fjBj+hCSs= github.com/xdg-go/stringprep v1.0.2/go.mod h1:8F9zXuvzgwmyT5DUm4GUfZGDdT3W+LCvS6+da4O5kxM= -github.com/xtgo/set v1.0.0/go.mod h1:d3NHzGzSa0NmB2NhFyECA+QdRp29oEn2xbT+TpeFoM8= github.com/yargevad/filepathx v1.0.0 h1:SYcT+N3tYGi+NvazubCNlvgIPbzAk7i7y2dwg3I5FYc= github.com/yargevad/filepathx v1.0.0/go.mod h1:BprfX/gpYNJHJfc35GjRRpVcwWXS89gGulUIU5tK3tA= github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4= @@ -662,12 +617,6 @@ go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= -go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0/go.mod h1:p8pYQP+m5XfbZm9fxtSKAbM6oIllS7s2AfxrChvc7iw= -go.opentelemetry.io/otel v1.24.0/go.mod h1:W7b9Ozg4nkF5tWI5zsXkaKKDjdVjpD4oAt9Qi/MArHo= -go.opentelemetry.io/otel/metric v1.24.0/go.mod h1:VYhLe1rFfxuTXLgj4CBiyz+9WYBA8pNGJgDcSFRKBco= -go.opentelemetry.io/otel/trace v1.24.0/go.mod h1:HPc3Xr/cOApsBI154IU0OI0HJexz+aw5uPdbs3UCjNU= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/atomic v1.9.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= @@ -678,7 +627,6 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i go.uber.org/multierr v1.7.0/go.mod h1:7EAYxJLBy9rStEaz58O2t4Uvip6FSURkq8/ppBp95ak= go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= go.uber.org/zap v1.19.1/go.mod h1:j3DNczoxDZroyBnOT1L/Q79cfUMGZxlv/9dzN7SM1rI= -go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6/go.mod h1:FftLjUGFEDu5k8lt0ddY+HcrH/qU/0qk+H8j9/nTl3E= golang.org/x/arch v0.14.0 h1:z9JUEZWr8x4rR0OU6c4/4t6E6jOZ8/QBS2bBYBm4tx4= golang.org/x/arch v0.14.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -717,7 +665,6 @@ golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa/go.mod h1:BHOTPb3L19zxehTsLo golang.org/x/image v0.0.0-20180708004352-c73c2afc3b81/go.mod h1:ux5Hcp/YLpHSI86hEcLt0YII63i6oz57MZXIpbrjZUs= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.22.0/go.mod h1:9hPFhljd4zZ1GNSIZJ49sqbp45GKK9t6w+iXvGqZUz4= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -794,7 +741,6 @@ golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4Iltr golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -877,7 +823,6 @@ golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457/go.mod h1:pRgIJT+bRLFKnoM1ldnzKoxTIn14Yxz928LQRYYgIN0= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -903,7 +848,6 @@ golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxb golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= -golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180525024113-a5b4c53f6e8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -963,7 +907,6 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo= gonum.org/v1/gonum v0.8.2/go.mod h1:oe/vMfY3deqTw+1EZJhuvEW2iwGF1bW9wwu7XCu0+v0= -gonum.org/v1/gonum v0.15.0/go.mod h1:xzZVBJBtS+Mz4q0Yl2LJTk+OxOg4jiXZ7qBoM0uISGo= gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw= gonum.org/v1/plot v0.0.0-20190515093506-e2840ee46a6b/go.mod h1:Wt8AAjI+ypCyYX3nZBvf6cAIx93T+c/OS2HFAYskSZc= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= @@ -982,7 +925,6 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.189.0/go.mod h1:FLWGJKb0hb+pU2j+rJqwbnsF+ym+fQs73rbJ+KAUgy8= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1021,7 +963,6 @@ google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0= google.golang.org/genproto v0.0.0-20210917145530-b395a37504d4/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240722135656-d784300faade/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -1039,7 +980,6 @@ google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU= google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM= google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34= -google.golang.org/grpc v1.64.1/go.mod h1:hiQF4LFZelK2WKaP6W0L92zGHtiQdZxk8CrSdvyjeP0= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1054,7 +994,6 @@ google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp0 google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= -google.golang.org/protobuf v1.34.2/go.mod h1:qYOHts0dSfpeUzUFpOMr/WGzszTmLH+DiWniOlNbLDw= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -1082,8 +1021,6 @@ gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorgonia.org/vecf32 v0.9.0/go.mod h1:NCc+5D2oxddRL11hd+pCB1PEyXWOyiQxfZ/1wwhOXCA= -gorgonia.org/vecf64 v0.9.0/go.mod h1:hp7IOWCnRiVQKON73kkC/AUMtEXyf9kGlVrtPQ9ccVA= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/idl/get_file_structure.proto b/idl/get_file_structure.proto new file mode 100644 index 00000000..aa9b785f --- /dev/null +++ b/idl/get_file_structure.proto @@ -0,0 +1,52 @@ +// get_file_structure IDL + +syntax = "proto3"; + +package abcoder; + +// Request +message GetFileStructReq { + string repo_name = 1; // the name of the repository (output of list_repos tool) + string file_path = 2; // relative file path (output of get_repo_structure tool, e.g., 'src/main.go') +} + +// Response +message GetFileStructResp { + FileStruct file_struct = 1; + string error = 2; // optional +} + +message FileStruct { + string file_path = 1; // the path of the file + string mod_path = 2; // optional, the module path + string pkg_path = 3; // optional, the package path + repeated Import imports = 4; // optional, the imports of the file + repeated NodeStruct nodes = 5; // optional, the node structs of the file +} + +message Import { + string path = 1; // import path + string alias = 2; // optional, import alias +} + +message NodeStruct { + string mod_path = 1; // optional, the module path + string pkg_path = 2; // optional, the package path + string name = 3; // the name of the node + string type = 4; // optional, the type of the node + string signature = 5; // optional, the func signature of the node (omitted when nodes > 500) + string file = 6; // optional, the file path of the node + int32 line = 7; // optional, the line of the node + string codes = 8; // optional, the codes of the node + repeated NodeID dependencies = 9; // optional, the dependencies of the node + repeated NodeID references = 10; // optional, the references of the node + repeated NodeID implements = 11; // optional, the implements of the node + repeated NodeID groups = 12; // optional, the groups of the node + repeated NodeID inherits = 13; // optional, the inherits of the node +} + +message NodeID { + string mod_path = 1; // module path of the node (from get_repo_structure) + string pkg_path = 2; // package path of the node (from get_repo_structure) + string name = 3; // name of the node (from get_package_structure or get_file_structure) +} diff --git a/llm/tool/ast_read.go b/llm/tool/ast_read.go index e411f70a..e08036e5 100644 --- a/llm/tool/ast_read.go +++ b/llm/tool/ast_read.go @@ -233,8 +233,10 @@ type PackageStruct struct { type FileStruct struct { FilePath string `json:"file_path" jsonschema:"description=the path of the file"` - Imports []uniast.Import `json:"imports,omitempty" jsonschema:"description=the imports of the file"` - Nodes []NodeStruct `json:"nodes,omitempty" jsonschema:"description=the node structs of the file"` + ModPath uniast.ModPath `json:"mod_path,omitempty" jsonschema:"description=the module path"` + PkgPath uniast.PkgPath `json:"pkg_path,omitempty" jsonschema:"description=the package path"` + Imports []uniast.Import `json:"imports,omitempty" jsonschema:"description=the imports of the file"` + Nodes []NodeStruct `json:"nodes,omitempty" jsonschema:"description=the node structs of the file"` } type NodeStruct struct { @@ -524,20 +526,23 @@ func (t *ASTReadTools) getFileStructure(_ context.Context, req GetFileStructReq, nodes := repo.GetFileNodes(req.FilePath) ff := FileStruct{ FilePath: req.FilePath, + ModPath: mod.Name, + PkgPath: file.Package, } if needNodeDetail { ff.Imports = file.Imports } + // If nodes count > 500, only show name + line + simplifiedOutput := len(nodes) > 500 for _, n := range nodes { nn := NodeStruct{ - ModPath: mod.Name, - PkgPath: file.Package, - Name: n.Identity.Name, + Name: n.Identity.Name, } if needNodeDetail { - nn.Type = n.Type.String() - nn.Signature = n.Signature() nn.Line = n.FileLine().Line + if !simplifiedOutput && n.Type != uniast.VAR { + nn.Signature = n.Signature() + } } ff.Nodes = append(ff.Nodes, nn, From 2725ac8152497ba68f78c3b94d6c89375ec5d6f8 Mon Sep 17 00:00:00 2001 From: simuleite Date: Tue, 3 Mar 2026 21:17:14 +0800 Subject: [PATCH 06/21] abcoder cli list_repos, detect current_repo --- go.mod | 2 +- internal/cmd/cli/list_repos.go | 71 +- lang/golang/parser/golang.json | 3575 ++++++++++++++++++++++++++++++++ lang/golang/parser/parser.go | 2 +- 4 files changed, 3630 insertions(+), 20 deletions(-) create mode 100644 lang/golang/parser/golang.json diff --git a/go.mod b/go.mod index 632a72fd..a20df35d 100644 --- a/go.mod +++ b/go.mod @@ -22,6 +22,7 @@ require ( github.com/spf13/cobra v1.8.1 github.com/stretchr/testify v1.10.0 github.com/vifraa/gopom v1.0.0 + golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa golang.org/x/mod v0.24.0 golang.org/x/tools v0.32.0 ) @@ -89,7 +90,6 @@ require ( github.com/yargevad/filepathx v1.0.0 // indirect github.com/yosida95/uritemplate/v3 v3.0.2 // indirect golang.org/x/arch v0.14.0 // indirect - golang.org/x/exp v0.0.0-20250218142911-aa4b98e5adaa // indirect golang.org/x/net v0.39.0 // indirect golang.org/x/sync v0.13.0 // indirect golang.org/x/sys v0.33.0 // indirect diff --git a/internal/cmd/cli/list_repos.go b/internal/cmd/cli/list_repos.go index d711f029..021cf0dc 100644 --- a/internal/cmd/cli/list_repos.go +++ b/internal/cmd/cli/list_repos.go @@ -22,8 +22,8 @@ import ( "strings" "github.com/bytedance/sonic" - "github.com/cloudwego/abcoder/llm/tool" "github.com/spf13/cobra" + "golang.org/x/exp/maps" ) func newListReposCmd() *cobra.Command { @@ -40,9 +40,16 @@ The repositories are loaded from .repo_index.json or *.json files in the --asts- return err } + // 获取当前工作目录 + cwd, err := os.Getwd() + if err != nil { + return err + } + // 尝试从 .repo_index.json 读取映射 indexFile := filepath.Join(astsDir, ".repo_index.json") var repoNames []string + var currentRepo string if data, err := os.ReadFile(indexFile); err == nil { // 解析 repo_index.json @@ -50,37 +57,65 @@ The repositories are loaded from .repo_index.json or *.json files in the --asts- Mappings map[string]string `json:"mappings"` } if err := json.Unmarshal(data, &index); err == nil && index.Mappings != nil { - for name := range index.Mappings { + for name, path := range index.Mappings { repoNames = append(repoNames, name) + // 检查当前目录是否匹配 + if path == cwd { + currentRepo = name + } } } } - // 如果没有从 index 读取到,回退到扫描 JSON 文件,使用 sonic 快速读取 id - if len(repoNames) == 0 { - files, err := filepath.Glob(filepath.Join(astsDir, "*.json")) - if err != nil { - return err + // 扫描 JSON 文件,使用 sonic 快速读取 + repoNamesMap := make(map[string]struct{}) + files, err := filepath.Glob(filepath.Join(astsDir, "*.json")) + if err != nil { + return err + } + for _, f := range files { + // 跳过 _repo_index.json + if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") { + continue } - for _, f := range files { - // 跳过 _repo_index.json - if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") { - continue + // 使用 sonic 快速读取 id 字段,避免加载整个 JSON + if data, err := os.ReadFile(f); err == nil { + val, err := sonic.Get(data, "id") + if err == nil { + id, err := val.String() + if err == nil && id != "" { + repoNamesMap[id] = struct{}{} + } } - // 使用 sonic 快速读取 id 字段,避免加载整个 JSON - if data, err := os.ReadFile(f); err == nil { - val, err := sonic.Get(data, "id") + // 尝试读取 Path 字段,检查是否匹配当前目录 + if currentRepo == "" { + val, err := sonic.Get(data, "Path") if err == nil { - id, err := val.String() - if err == nil && id != "" { - repoNames = append(repoNames, id) + path, err := val.String() + if err == nil && path == cwd { + // 从 id 字段获取名称 + val, err := sonic.Get(data, "id") + if err == nil { + id, err := val.String() + if err == nil && id != "" { + currentRepo = id + } + } } } } } } + repoNames = maps.Keys(repoNamesMap) - resp := tool.ListReposResp{RepoNames: repoNames} + type ListReposOutput struct { + RepoNames []string `json:"repo_names"` + CurrentRepo string `json:"current_repo,omitempty"` + } + resp := ListReposOutput{ + RepoNames: repoNames, + CurrentRepo: currentRepo, + } b, _ := json.MarshalIndent(resp, "", " ") fmt.Fprintf(os.Stdout, "%s\n", b) return nil diff --git a/lang/golang/parser/golang.json b/lang/golang/parser/golang.json new file mode 100644 index 00000000..6578d644 --- /dev/null +++ b/lang/golang/parser/golang.json @@ -0,0 +1,3575 @@ +{ + "id": "a.b/c", + "ASTVersion": "v0.1.5", + "ToolVersion": "", + "Path": "a.b/c", + "Modules": { + "../.@": { + "Language": "go", + "Version": "", + "Name": "../.", + "Dir": "", + "Packages": { + "a.b/c/pkg": { + "IsMain": false, + "IsTest": false, + "PkgPath": "a.b/c/pkg", + "Functions": { + "CaseStruct.CaseMethod": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "pkg/util.go", + "Line": 42, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer {\n\t_ = json.Unmarshal(in, x)\n\treturn Integer(0)\n}", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct" + } + } + }, + "Case_Func": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func", + "File": "pkg/util.go", + "Line": 25, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func Case_Func(in []byte, s *CaseStruct) error {\n\treturn sonic.Unmarshal(in, s)\n}" + } + }, + "Types": { + "CaseGenericStruct": { + "Exported": true, + "TypeKind": "", + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct", + "File": "pkg/generic.go", + "Line": 30, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type CaseGenericStruct struct{}" + }, + "CaseStruct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 29, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type CaseStruct struct {\n\tFieldPremitive string\n\tFieldType Integer\n\tFieldExternalType entity.MyStruct\n\tFieldInterface InterfaceA\n\tFieldExternalInterface entity.InterfaceB\n\tFieldClosuer func(in string) int\n}", + "Methods": { + "CaseMethod": { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod" + } + } + }, + "Obj": { + "Exported": true, + "TypeKind": "", + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 37, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type Obj struct{}" + } + }, + "Vars": {} + }, + "a.b/c/pkg/entity": { + "IsMain": false, + "IsTest": false, + "PkgPath": "a.b/c/pkg/entity", + "Functions": {}, + "Types": { + "MyStruct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/entity/entity.go", + "Line": 23, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type MyStruct struct {\n\ta string\n\tb string\n\tc MyStructC\n\tMyStructD\n\tEmbed struct {\n\t\t*MyStruct\n\t}\n}" + } + }, + "Vars": {} + } + } + }, + "a.b/c": { + "Language": "go", + "Version": "", + "Name": "a.b/c", + "Dir": ".", + "Packages": { + "a.b/c/merge": { + "IsMain": false, + "IsTest": false, + "PkgPath": "a.b/c/merge", + "Functions": { + "CaseMergeRef": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/merge", + "Name": "CaseMergeRef", + "File": "merge/merge_ref.go", + "Line": 25, + "StartOffset": 685, + "EndOffset": 777, + "Content": "func CaseMergeRef() MyStruct {\n\t_ = G1 + G2\n\treturn MyStruct{\n\t\tMyStructD: MyStructD{},\n\t}\n}", + "Signature": "func CaseMergeRef() MyStruct", + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "merge/merge_ref.go", + "Line": 25, + "StartOffset": 705, + "EndOffset": 713 + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "merge/merge_ref.go", + "Line": 27, + "StartOffset": 737, + "EndOffset": 745 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "merge/merge_ref.go", + "Line": 28, + "StartOffset": 760, + "EndOffset": 769 + } + ], + "GlobalVars": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "merge/merge_ref.go", + "Line": 26, + "StartOffset": 721, + "EndOffset": 723 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/merge", + "Name": "G2", + "File": "merge/merge_ref.go", + "Line": 26, + "StartOffset": 726, + "EndOffset": 728 + } + ] + } + }, + "Types": { + "S": { + "Exported": true, + "TypeKind": "typedef", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/merge", + "Name": "S", + "File": "merge/merge_ref.go", + "Line": 23, + "StartOffset": 667, + "EndOffset": 683, + "Content": "type S MyStructD", + "SubStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "merge/merge_ref.go", + "Line": 23, + "StartOffset": 674, + "EndOffset": 683 + } + ] + } + }, + "Vars": { + "G2": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/merge", + "Name": "G2", + "File": "merge/merge_ref.go", + "Line": 19, + "StartOffset": 642, + "EndOffset": 649, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var G2 = G1", + "Dependencies": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "merge/merge_ref.go", + "Line": 19, + "StartOffset": 647, + "EndOffset": 649 + } + ] + }, + "I1": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/merge", + "Name": "I1", + "File": "merge/merge_ref.go", + "Line": 21, + "StartOffset": 655, + "EndOffset": 665, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer" + }, + "Content": "var I1 Integer" + } + } + }, + "a.b/c/pkg": { + "IsMain": false, + "IsTest": false, + "PkgPath": "a.b/c/pkg", + "Functions": { + "CaseGenericFunc": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericFunc", + "File": "pkg/generic.go", + "Line": 35, + "StartOffset": 893, + "EndOffset": 1036, + "Content": "func CaseGenericFunc[U InterfaceA, T entity.InterfaceB, V any](a T, b U, c V) string {\n\treturn a.String() + fmt.Sprintf(\"%v\", c) + b.String()\n}", + "Signature": "func CaseGenericFunc[U InterfaceA, T entity.InterfaceB, V any](a T, b U, c V) string", + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/generic.go", + "Line": 35, + "StartOffset": 956, + "EndOffset": 959 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/generic.go", + "Line": 35, + "StartOffset": 961, + "EndOffset": 964 + } + ], + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB.String", + "File": "pkg/generic.go", + "Line": 36, + "StartOffset": 990, + "EndOffset": 996, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA.String", + "File": "pkg/generic.go", + "Line": 36, + "StartOffset": 1026, + "EndOffset": 1032, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/generic.go", + "Line": 35, + "StartOffset": 914, + "EndOffset": 926 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/generic.go", + "Line": 35, + "StartOffset": 928, + "EndOffset": 947 + } + ] + }, + "CaseGenericStruct.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct.String", + "File": "pkg/generic.go", + "Line": 31, + "StartOffset": 761, + "EndOffset": 891, + "Content": "func (s *CaseGenericStruct[_, _, _]) String() string {\n\treturn s.Prefix.String() + fmt.Sprintf(\"%v\", s.Data) + s.Subfix.String()\n}", + "Signature": "func (s *CaseGenericStruct[_, _, _]) String() string", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct" + } + }, + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB.String", + "File": "pkg/generic.go", + "Line": 32, + "StartOffset": 833, + "EndOffset": 839, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA.String", + "File": "pkg/generic.go", + "Line": 32, + "StartOffset": 881, + "EndOffset": 887, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/generic.go", + "Line": 31, + "StartOffset": 769, + "EndOffset": 796 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/generic.go", + "Line": 31, + "StartOffset": 769, + "EndOffset": 796 + } + ] + }, + "CaseInterface.CaseMethodDeps": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": true, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseInterface.CaseMethodDeps", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3404, + "EndOffset": 3452, + "Content": "CaseMethodDeps(a int, b entity.MyStruct) Integer", + "Signature": "CaseMethodDeps(a int, b entity.MyStruct) Integer", + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3426, + "EndOffset": 3443 + } + ], + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3445, + "EndOffset": 3452 + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3404, + "EndOffset": 3452 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3404, + "EndOffset": 3452 + } + ] + }, + "CaseStrucLiterMethod": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStrucLiterMethod", + "File": "pkg/util.go", + "Line": 146, + "StartOffset": 2920, + "EndOffset": 3193, + "Content": "func CaseStrucLiterMethod() {\n\t_ = (\u0026CaseStruct{\n\t\tFieldPremitive: \"a\",\n\t\tFieldType: 1,\n\t\tFieldExternalType: entity.MyStruct{},\n\t\tFieldInterface: nil,\n\t\tFieldExternalInterface: nil,\n\t\tFieldClosuer: nil,\n\t}).CaseMethod(nil, nil)\n}", + "Signature": "func CaseStrucLiterMethod()", + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "pkg/util.go", + "Line": 154, + "StartOffset": 3171, + "EndOffset": 3181, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 147, + "StartOffset": 2957, + "EndOffset": 2967 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 150, + "StartOffset": 3062, + "EndOffset": 3070 + } + ] + }, + "CaseStruct.CaseMethod": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "pkg/util.go", + "Line": 42, + "StartOffset": 1080, + "EndOffset": 1200, + "Content": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer {\n\t_ = json.Unmarshal(in, x)\n\treturn Integer(0)\n}", + "Signature": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct" + } + }, + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 42, + "StartOffset": 1123, + "EndOffset": 1141 + } + ], + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 42, + "StartOffset": 1143, + "EndOffset": 1150 + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 44, + "StartOffset": 1188, + "EndOffset": 1195 + } + ] + }, + "CaseStruct.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.String", + "File": "pkg/util.go", + "Line": 47, + "StartOffset": 1202, + "EndOffset": 1279, + "Content": "func (s *CaseStruct) String() string {\n\treturn s.FieldExternalType.String()\n}", + "Signature": "func (s *CaseStruct) String() string", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct" + } + }, + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct.String", + "File": "pkg/util.go", + "Line": 48, + "StartOffset": 1269, + "EndOffset": 1275, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "Case_All": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_All", + "File": "pkg/util.go", + "Line": 77, + "StartOffset": 1668, + "EndOffset": 2120, + "Content": "func Case_All(in string, a entity.MyStruct, b CaseStruct) (int, Integer, entity.Integer) {\n\tvar x entity.Integer\n\tvar y Integer\n\t_ = int(x) + int(y)\n\tvar s CaseStruct\n\t_ = s.CaseMethod(nil, nil)\n\tvar a2 entity.MyStruct\n\t_ = a2.String()\n\tb.FieldClosuer = func(in string) int { return 0 }\n\t_ = b.CaseMethod(nil, nil)\n\ta.MyStructD = entity.MyStructD{}\n\t_ = a.String()\n\t_ = Case_Func(nil, nil)\n\t_ = entity.A(\"\")\n\t_ = GlobalVar + entity.G1\n\treturn 0, 0, 0\n}", + "Signature": "func Case_All(in string, a entity.MyStruct, b CaseStruct) (int, Integer, entity.Integer)", + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 77, + "StartOffset": 1693, + "EndOffset": 1710 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 77, + "StartOffset": 1712, + "EndOffset": 1724 + } + ], + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 77, + "StartOffset": 1732, + "EndOffset": 1739 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 77, + "StartOffset": 1741, + "EndOffset": 1755 + } + ], + "FunctionCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func", + "File": "pkg/util.go", + "Line": 89, + "StartOffset": 2038, + "EndOffset": 2047, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "A", + "File": "pkg/util.go", + "Line": 90, + "StartOffset": 2070, + "EndOffset": 2071, + "Extra": { + "IsInvoked": true + } + } + ], + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "pkg/util.go", + "Line": 82, + "StartOffset": 1842, + "EndOffset": 1852, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct.String", + "File": "pkg/util.go", + "Line": 84, + "StartOffset": 1895, + "EndOffset": 1901, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 78, + "StartOffset": 1773, + "EndOffset": 1780 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 79, + "StartOffset": 1788, + "EndOffset": 1795 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 81, + "StartOffset": 1824, + "EndOffset": 1834 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 83, + "StartOffset": 1878, + "EndOffset": 1886 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "pkg/util.go", + "Line": 87, + "StartOffset": 2005, + "EndOffset": 2014 + } + ], + "GlobalVars": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "GlobalVar", + "File": "pkg/util.go", + "Line": 91, + "StartOffset": 2081, + "EndOffset": 2090 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "pkg/util.go", + "Line": 91, + "StartOffset": 2100, + "EndOffset": 2102 + } + ], + "Extra": { + "AnonymousFunctions": [ + { + "File": "pkg/util.go", + "Line": 85, + "StartOffset": 1922, + "EndOffset": 1954 + } + ] + } + }, + "Case_Chain_Selector": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Chain_Selector", + "File": "pkg/refer.go", + "Line": 46, + "StartOffset": 994, + "EndOffset": 1056, + "Content": "func Case_Chain_Selector() {\n\tvar obj Obj\n\tobj.Call().Call()\n}", + "Signature": "func Case_Chain_Selector()", + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.Call", + "File": "pkg/refer.go", + "Line": 48, + "StartOffset": 1048, + "EndOffset": 1052, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 47, + "StartOffset": 1032, + "EndOffset": 1035 + } + ] + }, + "Case_Closure": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Closure", + "File": "pkg/refer.go", + "Line": 51, + "StartOffset": 1058, + "EndOffset": 1148, + "Content": "func Case_Closure() {\n\tvar obj Obj\n\tobj.CallFunc(func(o Obj) Obj {\n\t\treturn o.Call()\n\t})\n}", + "Signature": "func Case_Closure()", + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.CallFunc", + "File": "pkg/refer.go", + "Line": 53, + "StartOffset": 1098, + "EndOffset": 1106, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.Call", + "File": "pkg/refer.go", + "Line": 54, + "StartOffset": 1136, + "EndOffset": 1140, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 52, + "StartOffset": 1089, + "EndOffset": 1092 + } + ], + "Extra": { + "AnonymousFunctions": [ + { + "File": "pkg/refer.go", + "Line": 53, + "StartOffset": 1107, + "EndOffset": 1145 + } + ] + } + }, + "Case_Func": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func", + "File": "pkg/util.go", + "Line": 25, + "StartOffset": 697, + "EndOffset": 778, + "Content": "func Case_Func(in []byte, s *CaseStruct) error {\n\treturn sonic.Unmarshal(in, s)\n}", + "Signature": "func Case_Func(in []byte, s *CaseStruct) error", + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 25, + "StartOffset": 723, + "EndOffset": 736 + } + ], + "FunctionCalls": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Unmarshal", + "File": "pkg/util.go", + "Line": 26, + "StartOffset": 760, + "EndOffset": 769, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "Case_Func_Func": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func_Func", + "File": "pkg/util.go", + "Line": 72, + "StartOffset": 1598, + "EndOffset": 1666, + "Content": "func Case_Func_Func() {\n\t_ = Case_Func(nil, nil)\n\t_ = entity.A(\"\")\n}", + "Signature": "func Case_Func_Func()", + "FunctionCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func", + "File": "pkg/util.go", + "Line": 73, + "StartOffset": 1627, + "EndOffset": 1636, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "A", + "File": "pkg/util.go", + "Line": 74, + "StartOffset": 1659, + "EndOffset": 1660, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "Case_Func_GloabVar": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func_GloabVar", + "File": "pkg/util.go", + "Line": 53, + "StartOffset": 1300, + "EndOffset": 1363, + "Content": "func Case_Func_GloabVar() int {\n\treturn GlobalVar + entity.G1\n}", + "Signature": "func Case_Func_GloabVar() int", + "GlobalVars": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "GlobalVar", + "File": "pkg/util.go", + "Line": 54, + "StartOffset": 1340, + "EndOffset": 1349 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "pkg/util.go", + "Line": 54, + "StartOffset": 1359, + "EndOffset": 1361 + } + ] + }, + "Case_Func_Global": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func_Global", + "File": "pkg/util.go", + "Line": 111, + "StartOffset": 2453, + "EndOffset": 2634, + "Content": "func Case_Func_Global() {\n\t_ = Enum1\n\t_ = Enum2\n\t_ = Enum3\n\t_ = Enum4\n\t_ = Var1\n\t_ = Var2\n\t_ = Var3\n\t_ = Var4\n\t_ = Var5\n\t_ = Var6\n\t_ = Var7\n\t_ = Var8\n\t_ = entity.G1\n\t_ = entity.V1\n}", + "Signature": "func Case_Func_Global()", + "GlobalVars": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum1", + "File": "pkg/util.go", + "Line": 112, + "StartOffset": 2484, + "EndOffset": 2489 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum2", + "File": "pkg/util.go", + "Line": 113, + "StartOffset": 2495, + "EndOffset": 2500 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum3", + "File": "pkg/util.go", + "Line": 114, + "StartOffset": 2506, + "EndOffset": 2511 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum4", + "File": "pkg/util.go", + "Line": 115, + "StartOffset": 2517, + "EndOffset": 2522 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var1", + "File": "pkg/util.go", + "Line": 116, + "StartOffset": 2528, + "EndOffset": 2532 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var2", + "File": "pkg/util.go", + "Line": 117, + "StartOffset": 2538, + "EndOffset": 2542 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var3", + "File": "pkg/util.go", + "Line": 118, + "StartOffset": 2548, + "EndOffset": 2552 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var4", + "File": "pkg/util.go", + "Line": 119, + "StartOffset": 2558, + "EndOffset": 2562 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var5", + "File": "pkg/util.go", + "Line": 120, + "StartOffset": 2568, + "EndOffset": 2572 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var6", + "File": "pkg/util.go", + "Line": 121, + "StartOffset": 2578, + "EndOffset": 2582 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var7", + "File": "pkg/util.go", + "Line": 122, + "StartOffset": 2588, + "EndOffset": 2592 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var8", + "File": "pkg/util.go", + "Line": 123, + "StartOffset": 2598, + "EndOffset": 2602 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "pkg/util.go", + "Line": 124, + "StartOffset": 2615, + "EndOffset": 2617 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "V1", + "File": "pkg/util.go", + "Line": 125, + "StartOffset": 2630, + "EndOffset": 2632 + } + ] + }, + "Case_Func_Method": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func_Method", + "File": "pkg/util.go", + "Line": 65, + "StartOffset": 1478, + "EndOffset": 1596, + "Content": "func Case_Func_Method() {\n\ts := \u0026CaseStruct{}\n\t_ = s.CaseMethod(nil, nil)\n\ts2 := \u0026entity.MyStruct{}\n\t_ = s2.String()\n}", + "Signature": "func Case_Func_Method()", + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "pkg/util.go", + "Line": 67, + "StartOffset": 1531, + "EndOffset": 1541, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct.String", + "File": "pkg/util.go", + "Line": 69, + "StartOffset": 1586, + "EndOffset": 1592, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 66, + "StartOffset": 1511, + "EndOffset": 1521 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 68, + "StartOffset": 1567, + "EndOffset": 1575 + } + ] + }, + "Case_Func_RefType": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func_RefType", + "File": "pkg/util.go", + "Line": 59, + "StartOffset": 1383, + "EndOffset": 1476, + "Content": "func Case_Func_RefType() int {\n\tvar x entity.Integer\n\tvar y Integer\n\treturn int(x) + int(y)\n}", + "Signature": "func Case_Func_RefType() int", + "Types": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 60, + "StartOffset": 1428, + "EndOffset": 1435 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 61, + "StartOffset": 1443, + "EndOffset": 1450 + } + ] + }, + "Case_Refer_Func": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Refer_Func", + "File": "pkg/refer.go", + "Line": 24, + "StartOffset": 706, + "EndOffset": 773, + "Content": "func Case_Refer_Func() {\n\tsonic.Get(nil, \"\")\n\tsonic.Pretouch(nil)\n}", + "Signature": "func Case_Refer_Func()", + "FunctionCalls": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Get", + "File": "pkg/refer.go", + "Line": 25, + "StartOffset": 738, + "EndOffset": 741, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Pretouch", + "File": "pkg/refer.go", + "Line": 26, + "StartOffset": 758, + "EndOffset": 766, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "Case_Refer_Method": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Refer_Method", + "File": "pkg/refer.go", + "Line": 29, + "StartOffset": 775, + "EndOffset": 835, + "Content": "func Case_Refer_Method() {\n\tn := sonic.Config{}\n\tn.Froze()\n}", + "Signature": "func Case_Refer_Method()", + "MethodCalls": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config.Froze", + "File": "pkg/refer.go", + "Line": 31, + "StartOffset": 826, + "EndOffset": 831, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "pkg/refer.go", + "Line": 30, + "StartOffset": 814, + "EndOffset": 820 + } + ] + }, + "InterfaceA.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": true, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA.String", + "File": "pkg/util.go", + "Line": 39, + "StartOffset": 1061, + "EndOffset": 1076, + "Content": "String() string", + "Signature": "String() string" + }, + "Obj.Call": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.Call", + "File": "pkg/refer.go", + "Line": 38, + "StartOffset": 894, + "EndOffset": 931, + "Content": "func (o Obj) Call() Obj {\n\treturn o\n}", + "Signature": "func (o Obj) Call() Obj", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj" + } + }, + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 38, + "StartOffset": 914, + "EndOffset": 917 + } + ] + }, + "Obj.CallFunc": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.CallFunc", + "File": "pkg/refer.go", + "Line": 42, + "StartOffset": 933, + "EndOffset": 992, + "Content": "func (o Obj) CallFunc(f func(Obj) Obj) Obj {\n\treturn f(o)\n}", + "Signature": "func (o Obj) CallFunc(f func(Obj) Obj) Obj", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj" + } + }, + "Params": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 42, + "StartOffset": 955, + "EndOffset": 970 + } + ], + "Results": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 42, + "StartOffset": 972, + "EndOffset": 975 + } + ] + } + }, + "Types": { + "CaseGenericStruct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct", + "File": "pkg/generic.go", + "Line": 25, + "StartOffset": 654, + "EndOffset": 759, + "Content": "type CaseGenericStruct[T entity.InterfaceB, U InterfaceA, V any] struct {\n\tPrefix T\n\tSubfix U\n\tData V\n}", + "SubStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/generic.go", + "Line": 26, + "StartOffset": 736, + "EndOffset": 737 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/generic.go", + "Line": 27, + "StartOffset": 746, + "EndOffset": 747 + } + ], + "Methods": { + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct.String" + } + }, + "Implements": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA" + } + ] + }, + "CaseInterface": { + "Exported": true, + "TypeKind": "interface", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseInterface", + "File": "pkg/util.go", + "Line": 165, + "StartOffset": 3372, + "EndOffset": 3454, + "Content": "type CaseInterface interface {\n\tCaseMethodDeps(a int, b entity.MyStruct) Integer\n}", + "SubStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3418, + "EndOffset": 3452 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 166, + "StartOffset": 3418, + "EndOffset": 3452 + } + ], + "Methods": { + "CaseMethodDeps": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseInterface.CaseMethodDeps" + } + } + }, + "CaseStruct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 29, + "StartOffset": 780, + "EndOffset": 1030, + "Content": "type CaseStruct struct {\n\tFieldPremitive string\n\tFieldType Integer\n\tFieldExternalType entity.MyStruct\n\tFieldInterface InterfaceA\n\tFieldExternalInterface entity.InterfaceB\n\tFieldClosuer func(in string) int\n}", + "SubStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 31, + "StartOffset": 860, + "EndOffset": 867 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 32, + "StartOffset": 892, + "EndOffset": 907 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/util.go", + "Line": 33, + "StartOffset": 932, + "EndOffset": 942 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/util.go", + "Line": 34, + "StartOffset": 967, + "EndOffset": 984 + } + ], + "Methods": { + "CaseMethod": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod" + }, + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.String" + } + }, + "Implements": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA" + } + ] + }, + "Case_Annoy_Struct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Annoy_Struct", + "File": "pkg/refer.go", + "Line": 58, + "StartOffset": 1150, + "EndOffset": 1213, + "Content": "type Case_Annoy_Struct struct {\n\tA struct {\n\t\tB int\n\t}\n\tC int\n}" + }, + "Case_Refer_Type": { + "Exported": true, + "TypeKind": "typedef", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Refer_Type", + "File": "pkg/refer.go", + "Line": 22, + "StartOffset": 671, + "EndOffset": 704, + "Content": "type Case_Refer_Type sonic.Config", + "SubStruct": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "pkg/refer.go", + "Line": 22, + "StartOffset": 692, + "EndOffset": 704 + } + ] + }, + "Integer": { + "Exported": true, + "TypeKind": "typedef", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 57, + "StartOffset": 1365, + "EndOffset": 1381, + "Content": "type Integer int" + }, + "InterfaceA": { + "Exported": true, + "TypeKind": "interface", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/util.go", + "Line": 38, + "StartOffset": 1032, + "EndOffset": 1078, + "Content": "type InterfaceA interface {\n\tString() string\n}", + "Methods": { + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA.String" + } + } + }, + "Obj": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj", + "File": "pkg/refer.go", + "Line": 36, + "StartOffset": 875, + "EndOffset": 892, + "Content": "type Obj struct{}", + "Methods": { + "Call": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.Call" + }, + "CallFunc": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Obj.CallFunc" + } + } + }, + "Type": { + "Exported": true, + "TypeKind": "typedef", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type", + "File": "pkg/util.go", + "Line": 129, + "StartOffset": 2659, + "EndOffset": 2672, + "Content": "type Type int" + } + }, + "Vars": { + "CaseGenericVar": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericVar", + "File": "pkg/generic.go", + "Line": 39, + "StartOffset": 1042, + "EndOffset": 1110, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseGenericStruct" + }, + "Content": "var CaseGenericVar CaseGenericStruct[entity.InterfaceB, InterfaceA, int]", + "Dependencies": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/generic.go", + "Line": 39, + "StartOffset": 1057, + "EndOffset": 1110 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA", + "File": "pkg/generic.go", + "Line": 39, + "StartOffset": 1057, + "EndOffset": 1110 + } + ] + }, + "CaseVarFunc": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseVarFunc", + "File": "pkg/util.go", + "Line": 157, + "StartOffset": 3199, + "EndOffset": 3370, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct" + }, + "Content": "var CaseVarFunc CaseStruct = func() CaseStruct {\n\treturn CaseStruct{\n\t\tFieldPremitive: Var4,\n\t\tFieldType: Integer(1),\n\t\tFieldExternalType: entity.MyStruct{},\n\t}\n}()", + "Dependencies": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var4", + "File": "pkg/util.go", + "Line": 159, + "StartOffset": 3285, + "EndOffset": 3289 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "pkg/util.go", + "Line": 157, + "StartOffset": 3231, + "EndOffset": 3241 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Integer", + "File": "pkg/util.go", + "Line": 160, + "StartOffset": 3312, + "EndOffset": 3319, + "Extra": { + "IsInvoked": true + } + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/util.go", + "Line": 161, + "StartOffset": 3352, + "EndOffset": 3360 + } + ], + "Extra": { + "AnonymousFunctions": [ + { + "File": "pkg/util.go", + "Line": 157, + "StartOffset": 3224, + "EndOffset": 3368 + } + ] + } + }, + "Case_Ref_Const": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Ref_Const", + "File": "pkg/refer.go", + "Line": 65, + "StartOffset": 1221, + "EndOffset": 1247, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const Case_Ref_Const = entity.G1", + "Dependencies": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "pkg/refer.go", + "Line": 65, + "StartOffset": 1238, + "EndOffset": 1247 + } + ] + }, + "Case_Refer_Var": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Refer_Var", + "File": "pkg/refer.go", + "Line": 34, + "StartOffset": 841, + "EndOffset": 873, + "Type": { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "API" + }, + "Content": "var Case_Refer_Var = sonic.ConfigStd", + "Dependencies": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "ConfigStd", + "File": "pkg/refer.go", + "Line": 34, + "StartOffset": 864, + "EndOffset": 873 + } + ] + }, + "Enum1": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum1", + "File": "pkg/util.go", + "Line": 96, + "StartOffset": 2131, + "EndOffset": 2154, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const Enum1 = 1", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum3" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum4" + } + ] + }, + "Enum2": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum2", + "File": "pkg/util.go", + "Line": 97, + "StartOffset": 2156, + "EndOffset": 2182, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const Enum2, Enum3 = 2, 3" + }, + "Enum3": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum3", + "File": "pkg/util.go", + "Line": 97, + "StartOffset": 2156, + "EndOffset": 2182, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const Enum2, Enum3 = 2, 3", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum1" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum4" + } + ] + }, + "Enum4": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum4", + "File": "pkg/util.go", + "Line": 98, + "StartOffset": 2184, + "EndOffset": 2209, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "string" + }, + "Content": "const Enum4 string = \"4\"", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum1" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Enum3" + } + ] + }, + "False": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False", + "File": "pkg/util.go", + "Line": 135, + "StartOffset": 2765, + "EndOffset": 2770, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const False = 1", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON" + } + ] + }, + "GlobalVar": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "GlobalVar", + "File": "pkg/util.go", + "Line": 51, + "StartOffset": 1285, + "EndOffset": 1298, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var GlobalVar int" + }, + "JSON": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON", + "File": "pkg/util.go", + "Line": 143, + "StartOffset": 2912, + "EndOffset": 2916, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const JSON = 5", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True" + } + ] + }, + "Null": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null", + "File": "pkg/util.go", + "Line": 133, + "StartOffset": 2713, + "EndOffset": 2729, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const Null Type = iota", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON" + } + ] + }, + "Number": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number", + "File": "pkg/util.go", + "Line": 137, + "StartOffset": 2798, + "EndOffset": 2804, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const Number = 2", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON" + } + ] + }, + "String": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String", + "File": "pkg/util.go", + "Line": 139, + "StartOffset": 2834, + "EndOffset": 2840, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const String = 3", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON" + } + ] + }, + "True": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "True", + "File": "pkg/util.go", + "Line": 141, + "StartOffset": 2874, + "EndOffset": 2878, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Type" + }, + "Content": "const True = 4", + "Groups": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Null" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "False" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Number" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "String" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "JSON" + } + ] + }, + "Var1": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var1", + "File": "pkg/util.go", + "Line": 102, + "StartOffset": 2220, + "EndOffset": 2241, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var Var1 = 1" + }, + "Var2": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var2", + "File": "pkg/util.go", + "Line": 103, + "StartOffset": 2243, + "EndOffset": 2267, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var Var2, Var3 = 2, 3" + }, + "Var3": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var3", + "File": "pkg/util.go", + "Line": 103, + "StartOffset": 2243, + "EndOffset": 2267, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var Var2, Var3 = 2, 3" + }, + "Var4": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var4", + "File": "pkg/util.go", + "Line": 104, + "StartOffset": 2269, + "EndOffset": 2292, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "string" + }, + "Content": "var Var4 string = \"4\"" + }, + "Var5": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var5", + "File": "pkg/util.go", + "Line": 105, + "StartOffset": 2294, + "EndOffset": 2327, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "[]string" + }, + "Content": "var Var5 = []string{\"a\"}" + }, + "Var6": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var6", + "File": "pkg/util.go", + "Line": 106, + "StartOffset": 2329, + "EndOffset": 2358, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "func()" + }, + "Content": "var Var6 = func() {}", + "Extra": { + "AnonymousFunctions": [ + { + "File": "pkg/util.go", + "Line": 106, + "StartOffset": 2349, + "EndOffset": 2358 + } + ] + } + }, + "Var7": { + "IsExported": true, + "IsConst": false, + "IsPointer": true, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var7", + "File": "pkg/util.go", + "Line": 107, + "StartOffset": 2360, + "EndOffset": 2413, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "*bool" + }, + "Content": "var Var7 = flag.Bool(\"flag\", false, \"usage\")" + }, + "Var8": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "Var8", + "File": "pkg/util.go", + "Line": 108, + "StartOffset": 2415, + "EndOffset": 2449, + "Type": { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config" + }, + "Content": "var Var8 = sonic.Config{}", + "Dependencies": [ + { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "pkg/util.go", + "Line": 108, + "StartOffset": 2441, + "EndOffset": 2447 + } + ] + } + } + }, + "a.b/c/pkg/entity": { + "IsMain": false, + "IsTest": false, + "PkgPath": "a.b/c/pkg/entity", + "Functions": { + "A": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "A", + "File": "pkg/entity/entity.go", + "Line": 55, + "StartOffset": 1132, + "EndOffset": 1173, + "Content": "func A(in string) int {\n\treturn len(in)\n}", + "Signature": "func A(in string) int" + }, + "InterfaceB.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": true, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB.String", + "File": "pkg/entity/entity.go", + "Line": 34, + "StartOffset": 796, + "EndOffset": 811, + "Content": "String() string", + "Signature": "String() string" + }, + "MyStruct.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct.String", + "File": "pkg/entity/entity.go", + "Line": 37, + "StartOffset": 815, + "EndOffset": 929, + "Content": "func (a MyStruct) String() string {\n\t_ = a.Embed.MyStruct\n\t_ = a.MyStructD\n\treturn \"base struct\" + a.DFunction()\n}", + "Signature": "func (a MyStruct) String() string", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct" + } + }, + "MethodCalls": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD.DFunction", + "File": "pkg/entity/entity.go", + "Line": 40, + "StartOffset": 916, + "EndOffset": 925, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "MyStructC.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructC.String", + "File": "pkg/entity/entity.go", + "Line": 47, + "StartOffset": 1006, + "EndOffset": 1067, + "Content": "func (c MyStructC) String() string {\n\treturn \"I'm struct c\"\n}", + "Signature": "func (c MyStructC) String() string", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructC" + } + } + }, + "MyStructD.DFunction": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD.DFunction", + "File": "pkg/entity/entity.go", + "Line": 43, + "StartOffset": 931, + "EndOffset": 1004, + "Content": "func (c MyStructD) DFunction() string {\n\treturn \"I'm struct d function\"\n}", + "Signature": "func (c MyStructD) DFunction() string", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD" + } + } + }, + "MyStructD.String": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD.String", + "File": "pkg/entity/entity.go", + "Line": 51, + "StartOffset": 1069, + "EndOffset": 1130, + "Content": "func (c MyStructD) String() string {\n\treturn \"I'm struct d\"\n}", + "Signature": "func (c MyStructD) String() string", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD" + } + } + } + }, + "Types": { + "Integer": { + "Exported": true, + "TypeKind": "typedef", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer", + "File": "pkg/entity/entity.go", + "Line": 61, + "StartOffset": 1189, + "EndOffset": 1205, + "Content": "type Integer int" + }, + "InterfaceB": { + "Exported": true, + "TypeKind": "interface", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB", + "File": "pkg/entity/entity.go", + "Line": 33, + "StartOffset": 767, + "EndOffset": 813, + "Content": "type InterfaceB interface {\n\tString() string\n}", + "Methods": { + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB.String" + } + } + }, + "MyStruct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/entity/entity.go", + "Line": 23, + "StartOffset": 666, + "EndOffset": 765, + "Content": "type MyStruct struct {\n\ta string\n\tb string\n\tc MyStructC\n\tMyStructD\n\tEmbed struct {\n\t\t*MyStruct\n\t}\n}", + "SubStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "pkg/entity/entity.go", + "Line": 27, + "StartOffset": 723, + "EndOffset": 732 + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "pkg/entity/entity.go", + "Line": 29, + "StartOffset": 751, + "EndOffset": 760 + } + ], + "InlineStruct": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "pkg/entity/entity.go", + "Line": 27, + "StartOffset": 723, + "EndOffset": 732 + } + ], + "Methods": { + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct.String" + } + }, + "Implements": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA" + } + ] + }, + "MyStructC": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructC", + "File": "pkg/entity/entity.go", + "Line": 17, + "StartOffset": 612, + "EndOffset": 637, + "Content": "type MyStructC struct {\n}", + "Methods": { + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructC.String" + } + }, + "Implements": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB" + } + ] + }, + "MyStructD": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD", + "File": "pkg/entity/entity.go", + "Line": 20, + "StartOffset": 639, + "EndOffset": 664, + "Content": "type MyStructD struct {\n}", + "Methods": { + "DFunction": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD.DFunction" + }, + "String": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStructD.String" + } + }, + "Implements": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "InterfaceB" + }, + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg", + "Name": "InterfaceA" + } + ] + } + }, + "Vars": { + "G1": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "G1", + "File": "pkg/entity/entity.go", + "Line": 59, + "StartOffset": 1181, + "EndOffset": 1187, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const G1 = 1" + }, + "V1": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "V1", + "File": "pkg/entity/entity.go", + "Line": 63, + "StartOffset": 1211, + "EndOffset": 1226, + "Type": { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer" + }, + "Content": "var V1 = Integer(1)", + "Dependencies": [ + { + "ModPath": "a.b/c", + "PkgPath": "a.b/c/pkg/entity", + "Name": "Integer", + "File": "pkg/entity/entity.go", + "Line": 63, + "StartOffset": 1216, + "EndOffset": 1223, + "Extra": { + "IsInvoked": true + } + } + ] + } + } + } + }, + "Dependencies": { + "a.b/c": "a.b/c@7361f67ef606a7ab7dcf1b6d7ebcf1e0188b00f8", + "github.com/bytedance/sonic": "github.com/bytedance/sonic@v1.10.2", + "golang.org/x/arch": "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670" + }, + "Files": { + "cmd/go.mod": { + "Path": "cmd/go.mod" + }, + "cmd/go.sum": { + "Path": "cmd/go.sum" + }, + "cmd/main.go": { + "Path": "cmd/main.go" + }, + "cmd/serdes.go": { + "Path": "cmd/serdes.go" + }, + "go.mod": { + "Path": "go.mod" + }, + "go.sum": { + "Path": "go.sum" + }, + "merge/merge_ref.go": { + "Path": "merge/merge_ref.go", + "Imports": [ + { + "Alias": ".", + "Path": "\"a.b/c/pkg/entity\"" + } + ], + "Package": "a.b/c/merge" + }, + "pkg/entity/entity.go": { + "Path": "pkg/entity/entity.go", + "Package": "a.b/c/pkg/entity" + }, + "pkg/generic.go": { + "Path": "pkg/generic.go", + "Imports": [ + { + "Path": "\"fmt\"" + }, + { + "Path": "\"a.b/c/pkg/entity\"" + } + ], + "Package": "a.b/c/pkg" + }, + "pkg/refer.go": { + "Path": "pkg/refer.go", + "Imports": [ + { + "Path": "\"a.b/c/pkg/entity\"" + }, + { + "Path": "\"github.com/bytedance/sonic\"" + } + ], + "Package": "a.b/c/pkg" + }, + "pkg/util.go": { + "Path": "pkg/util.go", + "Imports": [ + { + "Path": "\"encoding/json\"" + }, + { + "Path": "\"flag\"" + }, + { + "Path": "\"a.b/c/pkg/entity\"" + }, + { + "Path": "\"github.com/bytedance/sonic\"" + } + ], + "Package": "a.b/c/pkg" + } + } + }, + "a.b/c/cmdx": { + "Language": "go", + "Version": "", + "Name": "a.b/c/cmdx", + "Dir": "cmd", + "Packages": { + "a.b/c/cmdx": { + "IsMain": true, + "IsTest": false, + "PkgPath": "a.b/c/cmdx", + "Functions": { + "DuplicateName": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "DuplicateName", + "File": "cmd/serdes.go", + "Line": 36, + "StartOffset": 912, + "EndOffset": 936, + "Content": "func DuplicateName() {\n}", + "Signature": "func DuplicateName()" + }, + "InternalFunc": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "InternalFunc", + "File": "cmd/serdes.go", + "Line": 25, + "StartOffset": 692, + "EndOffset": 910, + "Content": "func InternalFunc(in []byte) {\n\tvar s = new(pkg.CaseStruct)\n\tif err := pkg.Case_Func(in, s); err != nil {\n\t\tprintln(err.Error())\n\t}\n\tvar x = new(entity.MyStruct)\n\tif v := s.CaseMethod(in, x); v != 0 {\n\t\tprintln(v)\n\t}\n}", + "Signature": "func InternalFunc(in []byte)", + "FunctionCalls": [ + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "Case_Func", + "File": "cmd/serdes.go", + "Line": 27, + "StartOffset": 767, + "EndOffset": 776, + "Extra": { + "IsInvoked": true + } + } + ], + "MethodCalls": [ + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "cmd/serdes.go", + "Line": 31, + "StartOffset": 865, + "EndOffset": 875, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "cmd/serdes.go", + "Line": 26, + "StartOffset": 740, + "EndOffset": 750 + }, + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg/entity", + "Name": "MyStruct", + "File": "cmd/serdes.go", + "Line": 30, + "StartOffset": 844, + "EndOffset": 852 + } + ] + }, + "Struct.DuplicateName": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct.DuplicateName", + "File": "cmd/serdes.go", + "Line": 55, + "StartOffset": 1238, + "EndOffset": 1283, + "Content": "func (s *Struct) DuplicateName(in []byte) {\n}", + "Signature": "func (s *Struct) DuplicateName(in []byte)", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct" + } + } + }, + "Struct.InternalMethod": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct.InternalMethod", + "File": "cmd/serdes.go", + "Line": 46, + "StartOffset": 1045, + "EndOffset": 1236, + "Content": "func (s *Struct) InternalMethod(in []byte) {\n\tif err := sonic.Unmarshal(in, \u0026s); err != nil {\n\t\tprintln(err.Error())\n\t}\n\tif err := s.Field2.CaseMethod(in, nil); err != 0 {\n\t\tprintln(err)\n\t}\n}", + "Signature": "func (s *Struct) InternalMethod(in []byte)", + "Receiver": { + "IsPointer": true, + "Type": { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct" + } + }, + "FunctionCalls": [ + { + "ModPath": "github.com/bytedance/sonic@v1.11.3", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Unmarshal", + "File": "cmd/serdes.go", + "Line": 47, + "StartOffset": 1107, + "EndOffset": 1116, + "Extra": { + "IsInvoked": true + } + } + ], + "MethodCalls": [ + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct.CaseMethod", + "File": "cmd/serdes.go", + "Line": 50, + "StartOffset": 1185, + "EndOffset": 1195, + "Extra": { + "IsInvoked": true + } + } + ] + }, + "main": { + "Exported": false, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "main", + "File": "cmd/main.go", + "Line": 24, + "StartOffset": 667, + "EndOffset": 981, + "Content": "func main() {\n\tif len(os.Args) \u003c 2 {\n\t\tprintln(\"missing argument\")\n\t\tos.Exit(1)\n\t}\n\t// content, err := readFile(os.Args[1])\n\t// if err != nil {\n\t// \tprintln(err.Error())\n\t// \tos.Exit(1)\n\t// }\n\tcontent := []byte(\"{}\")\n\tInternalFunc(content)\n\tvar s = new(Struct)\n\ts.Field4 = InternalFunc\n\ts.InternalMethod(content)\n}", + "Signature": "func main()", + "FunctionCalls": [ + { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "InternalFunc", + "File": "cmd/main.go", + "Line": 35, + "StartOffset": 885, + "EndOffset": 897, + "Extra": { + "IsInvoked": true + } + } + ], + "MethodCalls": [ + { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct.InternalMethod", + "File": "cmd/main.go", + "Line": 38, + "StartOffset": 956, + "EndOffset": 970, + "Extra": { + "IsInvoked": true + } + } + ], + "Types": [ + { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct", + "File": "cmd/main.go", + "Line": 36, + "StartOffset": 920, + "EndOffset": 926 + } + ] + }, + "readFile": { + "Exported": false, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "readFile", + "File": "cmd/main.go", + "Line": 41, + "StartOffset": 983, + "EndOffset": 1181, + "Content": "func readFile(path string) ([]byte, error) {\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to open file\")\n\t}\n\tdefer file.Close()\n\n\treturn ioutil.ReadAll(file)\n}", + "Signature": "func readFile(path string) ([]byte, error)", + "FunctionCalls": [ + { + "ModPath": "github.com/pkg/errors@v0.9.1", + "PkgPath": "github.com/pkg/errors", + "Name": "Wrap", + "File": "cmd/main.go", + "Line": 44, + "StartOffset": 1094, + "EndOffset": 1098, + "Extra": { + "IsInvoked": true + } + } + ] + } + }, + "Types": { + "Struct": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct", + "File": "cmd/serdes.go", + "Line": 39, + "StartOffset": 938, + "EndOffset": 1043, + "Content": "type Struct struct {\n\tField1 string\n\tField2 pkg.CaseStruct\n\tField3 sonic.Config\n\tField4 func(in []byte)\n}", + "SubStruct": [ + { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct", + "File": "cmd/serdes.go", + "Line": 41, + "StartOffset": 982, + "EndOffset": 996 + }, + { + "ModPath": "github.com/bytedance/sonic@v1.11.3", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "cmd/serdes.go", + "Line": 42, + "StartOffset": 1005, + "EndOffset": 1017 + } + ], + "Methods": { + "DuplicateName": { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct.DuplicateName" + }, + "InternalMethod": { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct.InternalMethod" + } + } + } + }, + "Vars": { + "Con1": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Con1", + "File": "cmd/serdes.go", + "Line": 72, + "StartOffset": 1464, + "EndOffset": 1482, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped int" + }, + "Content": "const Con1, Con2 = 1, \"\"" + }, + "Con2": { + "IsExported": true, + "IsConst": true, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Con2", + "File": "cmd/serdes.go", + "Line": 72, + "StartOffset": 1464, + "EndOffset": 1482, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "untyped string" + }, + "Content": "const Con1, Con2 = 1, \"\"" + }, + "Var1": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Var1", + "File": "cmd/serdes.go", + "Line": 70, + "StartOffset": 1438, + "EndOffset": 1456, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var Var1, Var2 = 1, \"\"" + }, + "Var2": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Var2", + "File": "cmd/serdes.go", + "Line": 70, + "StartOffset": 1438, + "EndOffset": 1456, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "string" + }, + "Content": "var Var1, Var2 = 1, \"\"" + }, + "VarFunc": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarFunc", + "File": "cmd/serdes.go", + "Line": 64, + "StartOffset": 1359, + "EndOffset": 1376, + "Type": { + "ModPath": "", + "PkgPath": "io", + "Name": "Reader" + }, + "Content": "var VarFunc io.Reader" + }, + "VarInt": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarInt", + "File": "cmd/serdes.go", + "Line": 60, + "StartOffset": 1312, + "EndOffset": 1322, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "int" + }, + "Content": "var VarInt = 1" + }, + "VarSlice": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarSlice", + "File": "cmd/serdes.go", + "Line": 62, + "StartOffset": 1328, + "EndOffset": 1353, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "[]int" + }, + "Content": "var VarSlice = []int{1, 2, 3}" + }, + "VarString": { + "IsExported": true, + "IsConst": false, + "IsPointer": true, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarString", + "File": "cmd/serdes.go", + "Line": 58, + "StartOffset": 1289, + "EndOffset": 1306, + "Type": { + "ModPath": "", + "PkgPath": "", + "Name": "*string" + }, + "Content": "var VarString *string" + }, + "VarStruct": { + "IsExported": true, + "IsConst": false, + "IsPointer": true, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarStruct", + "File": "cmd/serdes.go", + "Line": 68, + "StartOffset": 1415, + "EndOffset": 1432, + "Type": { + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "Struct" + }, + "Content": "var VarStruct *Struct" + }, + "VarpkgStruct": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "a.b/c/cmdx", + "PkgPath": "a.b/c/cmdx", + "Name": "VarpkgStruct", + "File": "cmd/serdes.go", + "Line": 66, + "StartOffset": 1382, + "EndOffset": 1409, + "Type": { + "ModPath": "../.@", + "PkgPath": "a.b/c/pkg", + "Name": "CaseStruct" + }, + "Content": "var VarpkgStruct pkg.CaseStruct" + } + } + } + }, + "Dependencies": { + "a.b/c": "../.@", + "a.b/c/cmdx": "a.b/c/cmdx@7361f67ef606a7ab7dcf1b6d7ebcf1e0188b00f8", + "github.com/bytedance/sonic": "github.com/bytedance/sonic@v1.11.3", + "github.com/pkg/errors": "github.com/pkg/errors@v0.9.1", + "golang.org/x/arch": "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670" + }, + "Files": { + "cmd/go.mod": { + "Path": "cmd/go.mod" + }, + "cmd/go.sum": { + "Path": "cmd/go.sum" + }, + "cmd/main.go": { + "Path": "cmd/main.go", + "Imports": [ + { + "Path": "\"io/ioutil\"" + }, + { + "Path": "\"os\"" + }, + { + "Path": "\"github.com/pkg/errors\"" + } + ], + "Package": "a.b/c/cmdx" + }, + "cmd/serdes.go": { + "Path": "cmd/serdes.go", + "Imports": [ + { + "Path": "\"io\"" + }, + { + "Path": "\"a.b/c/pkg\"" + }, + { + "Path": "\"a.b/c/pkg/entity\"" + }, + { + "Path": "\"github.com/bytedance/sonic\"" + } + ], + "Package": "a.b/c/cmdx" + } + } + }, + "github.com/bytedance/sonic@v1.10.2": { + "Language": "go", + "Version": "v1.10.2", + "Name": "github.com/bytedance/sonic", + "Dir": "", + "Packages": { + "github.com/bytedance/sonic": { + "IsMain": false, + "IsTest": false, + "PkgPath": "github.com/bytedance/sonic", + "Functions": { + "Config.Froze": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config.Froze", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", + "Line": 35, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func (cfg Config) Froze() API {\n api := \u0026frozenConfig{Config: cfg}\n return api\n}", + "Receiver": { + "IsPointer": false, + "Type": { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config" + } + } + }, + "Get": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Get", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", + "Line": 183, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func Get(src []byte, path ...interface{}) (ast.Node, error) {\n return GetFromString(string(src), path...)\n}" + }, + "Pretouch": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Pretouch", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", + "Line": 128, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {\n return nil\n}" + }, + "Unmarshal": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Unmarshal", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", + "Line": 92, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error {\n return cfg.UnmarshalFromString(string(buf), val)\n}" + } + }, + "Types": { + "Config": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", + "Line": 26, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type Config struct {\n // EscapeHTML indicates encoder to escape all HTML characters \n // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n EscapeHTML bool\n\n // SortMapKeys indicates encoder that the keys of a map needs to be sorted \n // before serializing into JSON.\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n SortMapKeys bool\n\n // CompactMarshaler indicates encoder that the output JSON from json.Marshaler \n // is always compact and needs no validation \n CompactMarshaler bool\n\n // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler \n // is always escaped string and needs no quoting\n NoQuoteTextMarshaler bool\n\n // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',\n // instead of 'null'\n NoNullSliceOrMap bool\n\n // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an\n // int64 instead of as a float64.\n UseInt64 bool\n\n // UseNumber indicates decoder to unmarshal a number into an interface{} as a\n // json.Number instead of as a float64.\n UseNumber bool\n\n // UseUnicodeErrors indicates decoder to return an error when encounter invalid\n // UTF-8 escape sequences.\n UseUnicodeErrors bool\n\n // DisallowUnknownFields indicates decoder to return an error when the destination\n // is a struct and the input contains object keys which do not match any\n // non-ignored, exported fields in the destination.\n DisallowUnknownFields bool\n\n // CopyString indicates decoder to decode string values by copying instead of referring.\n CopyString bool\n\n // ValidateString indicates decoder and encoder to valid string values: decoder will return errors \n // when unescaped control chars(\\u0000-\\u001f) in the string value of JSON.\n ValidateString bool\n\n // NoValidateJSONMarshaler indicates that the encoder should not validate the output string\n // after encoding the JSONMarshaler to JSON.\n NoValidateJSONMarshaler bool\n}", + "Methods": { + "Froze": { + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config.Froze" + } + } + }, + "frozenConfig": { + "Exported": false, + "TypeKind": "", + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "frozenConfig", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", + "Line": 39, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type frozenConfig struct{}" + } + }, + "Vars": { + "ConfigStd": { + "IsExported": true, + "IsConst": false, + "IsPointer": false, + "ModPath": "github.com/bytedance/sonic@v1.10.2", + "PkgPath": "github.com/bytedance/sonic", + "Name": "ConfigStd", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", + "Line": 83, + "StartOffset": 0, + "EndOffset": 0, + "Content": "ConfigStd = Config{\n EscapeHTML : true,\n SortMapKeys: true,\n CompactMarshaler: true,\n CopyString : true,\n ValidateString : true,\n }.Froze()" + } + } + } + } + }, + "github.com/bytedance/sonic@v1.11.3": { + "Language": "go", + "Version": "v1.11.3", + "Name": "github.com/bytedance/sonic", + "Dir": "", + "Packages": { + "github.com/bytedance/sonic": { + "IsMain": false, + "IsTest": false, + "PkgPath": "github.com/bytedance/sonic", + "Functions": { + "Unmarshal": { + "Exported": true, + "IsMethod": true, + "IsInterfaceMethod": false, + "ModPath": "github.com/bytedance/sonic@v1.11.3", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Unmarshal", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.11.3/compat.go", + "Line": 92, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error {\n return cfg.UnmarshalFromString(string(buf), val)\n}" + } + }, + "Types": { + "Config": { + "Exported": true, + "TypeKind": "struct", + "ModPath": "github.com/bytedance/sonic@v1.11.3", + "PkgPath": "github.com/bytedance/sonic", + "Name": "Config", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.11.3/api.go", + "Line": 27, + "StartOffset": 0, + "EndOffset": 0, + "Content": "type Config struct {\n // EscapeHTML indicates encoder to escape all HTML characters \n // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n EscapeHTML bool\n\n // SortMapKeys indicates encoder that the keys of a map needs to be sorted \n // before serializing into JSON.\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n SortMapKeys bool\n\n // CompactMarshaler indicates encoder that the output JSON from json.Marshaler \n // is always compact and needs no validation \n CompactMarshaler bool\n\n // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler \n // is always escaped string and needs no quoting\n NoQuoteTextMarshaler bool\n\n // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',\n // instead of 'null'\n NoNullSliceOrMap bool\n\n // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an\n // int64 instead of as a float64.\n UseInt64 bool\n\n // UseNumber indicates decoder to unmarshal a number into an interface{} as a\n // json.Number instead of as a float64.\n UseNumber bool\n\n // UseUnicodeErrors indicates decoder to return an error when encounter invalid\n // UTF-8 escape sequences.\n UseUnicodeErrors bool\n\n // DisallowUnknownFields indicates decoder to return an error when the destination\n // is a struct and the input contains object keys which do not match any\n // non-ignored, exported fields in the destination.\n DisallowUnknownFields bool\n\n // CopyString indicates decoder to decode string values by copying instead of referring.\n CopyString bool\n\n // ValidateString indicates decoder and encoder to valid string values: decoder will return errors \n // when unescaped control chars(\\u0000-\\u001f) in the string value of JSON.\n ValidateString bool\n\n // NoValidateJSONMarshaler indicates that the encoder should not validate the output string\n // after encoding the JSONMarshaler to JSON.\n NoValidateJSONMarshaler bool\n \n // NoEncoderNewline indicates that the encoder should not add a newline after every message\n NoEncoderNewline bool\n}" + } + }, + "Vars": {} + } + } + }, + "github.com/pkg/errors@v0.9.1": { + "Language": "go", + "Version": "v0.9.1", + "Name": "github.com/pkg/errors", + "Dir": "", + "Packages": { + "github.com/pkg/errors": { + "IsMain": false, + "IsTest": false, + "PkgPath": "github.com/pkg/errors", + "Functions": { + "Wrap": { + "Exported": true, + "IsMethod": false, + "IsInterfaceMethod": false, + "ModPath": "github.com/pkg/errors@v0.9.1", + "PkgPath": "github.com/pkg/errors", + "Name": "Wrap", + "File": "../../../../../../go/1.24.3/pkg/mod/github.com/pkg/errors@v0.9.1/errors.go", + "Line": 184, + "StartOffset": 0, + "EndOffset": 0, + "Content": "func Wrap(err error, message string) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\terr = \u0026withMessage{\n\t\tcause: err,\n\t\tmsg: message,\n\t}\n\treturn \u0026withStack{\n\t\terr,\n\t\tcallers(),\n\t}\n}" + } + }, + "Types": {}, + "Vars": {} + } + } + } + }, + "Graph": {} +} \ No newline at end of file diff --git a/lang/golang/parser/parser.go b/lang/golang/parser/parser.go index 7b7dc2e4..12e53095 100644 --- a/lang/golang/parser/parser.go +++ b/lang/golang/parser/parser.go @@ -234,7 +234,7 @@ func getDeps(dir string, workDirs map[string]bool) (a map[string]string, cgoPkgs cmd.Env = append(os.Environ(), "GOSUMDB=off") output, err = cmd.CombinedOutput() if err != nil { - return nil, cgoPkgs, fmt.Errorf("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s", err, string(output), cmd.String(), dir) + return nil, cgoPkgs, fmt.Errorf("failed to execute 'go list -m -json all', err: %v, output: %s, cmd string: %s, dir: %s", err, string(output), cmd.String(), dir) } // ignore content until first open index := strings.Index(string(output), "{") From 00e9737ff31ee9c9cd479bf78a9651752ac17115 Mon Sep 17 00:00:00 2001 From: simuleite Date: Tue, 3 Mar 2026 21:31:34 +0800 Subject: [PATCH 07/21] Sonic Cli Read JSON --- .../skills/abcoder__list_repos/SKILL.md | 12 +- internal/cmd/cli/cli.go | 13 + internal/cmd/cli/extract_symbol.go | 223 ++++++++ internal/cmd/cli/get_file_structure.go | 57 +- internal/cmd/cli/get_file_symbol.go | 82 ++- internal/cmd/cli/list_repos.go | 21 +- internal/cmd/cli/search_symbol.go | 254 +++++++++ internal/cmd/cli/tree_repo.go | 70 ++- internal/cmd/cli/utils.go | 509 ++++++++++++++++++ 9 files changed, 1195 insertions(+), 46 deletions(-) create mode 100644 internal/cmd/cli/extract_symbol.go create mode 100644 internal/cmd/cli/search_symbol.go diff --git a/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md index c01809fd..4608f7d3 100644 --- a/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md +++ b/internal/cmd/assets/.claude/skills/abcoder__list_repos/SKILL.md @@ -1,6 +1,6 @@ --- name: skill__abcoder__list_repos -description: skill__abcoder__list_repos `abcoder cli list_repos` [DISCOVERY] Step 1/4: List available repositories. Always the first step in ABCoder workflow. You MUST call `tree_repo` later. +description: skill__abcoder__list_repos `abcoder cli list_repos` [DISCOVERY] Step 1/4: List available repositories. Always the first step in ABCoder workflow. You MUST call `tree_repo` later. 获取当前仓库名: `abcoder cli list_repos | jq .current_repo` --- Execute the list_repos command to discover all available repositories: @@ -9,6 +9,11 @@ Execute the list_repos command to discover all available repositories: abcoder cli list_repos ``` +获取当前仓库名(根据 pwd 匹配): +```bash +abcoder cli list_repos | jq .current_repo +``` + ## Workflow Context This tool is **Level 1** in the 4-level ABCoder discovery hierarchy: @@ -22,8 +27,7 @@ This tool is **Level 1** in the 4-level ABCoder discovery hierarchy: Output ``` { - "repo_names": { - "array[i]": "string" - } + "repo_names": ["string"], + "current_repo": "string" } ``` diff --git a/internal/cmd/cli/cli.go b/internal/cmd/cli/cli.go index 0d29569d..15b0287e 100644 --- a/internal/cmd/cli/cli.go +++ b/internal/cmd/cli/cli.go @@ -18,6 +18,8 @@ import ( "github.com/spf13/cobra" ) +var verbose bool + // NewCliCmd returns the parent command for CLI operations. func NewCliCmd() *cobra.Command { cmd := &cobra.Command{ @@ -27,13 +29,24 @@ func NewCliCmd() *cobra.Command { These commands provide direct access to repository, file, and symbol information.`, Example: `abcoder cli list-repos`, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + // 解析 -v flag + v, err := cmd.Flags().GetBool("verbose") + if err == nil { + verbose = v + } + }, } + cmd.PersistentFlags().BoolVarP(&verbose, "verbose", "v", false, "verbose output for debugging") + // Add subcommands cmd.AddCommand(newListReposCmd()) cmd.AddCommand(newTreeRepoCmd()) cmd.AddCommand(newGetFileStructureCmd()) cmd.AddCommand(newGetFileSymbolCmd()) + cmd.AddCommand(newExtractSymbolCmd()) + cmd.AddCommand(newSearchSymbolCmd()) return cmd } diff --git a/internal/cmd/cli/extract_symbol.go b/internal/cmd/cli/extract_symbol.go new file mode 100644 index 00000000..f69b8a56 --- /dev/null +++ b/internal/cmd/cli/extract_symbol.go @@ -0,0 +1,223 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + + "github.com/bytedance/sonic" + "github.com/cloudwego/abcoder/lang/utils" + "github.com/spf13/cobra" +) + +const indexDir = ".index" + +type SymbolIndex struct { + Mtime int64 `json:"mtime"` + Data map[string][]NameMatch `json:"data"` // name -> []NameMatch +} + +type NameMatch struct { + File string `json:"file"` + Type string `json:"type"` +} + +// saveSymbolIndex 保存符号索引到 ~/.asts/.index/{repo}.idx +func saveSymbolIndex(astsDir, repoName, repoFile string, data map[string][]NameMatch) error { + // 获取 repo 文件的 mtime + info, err := os.Stat(repoFile) + if err != nil { + return fmt.Errorf("stat repo file: %w", err) + } + mtime := info.ModTime().UnixMilli() + + // 检查现有索引 + idxPath := filepath.Join(astsDir, indexDir, repoName+".idx") + if _, err := os.Stat(idxPath); err == nil { + // 读取现有索引的 mtime + if oldData, err := os.ReadFile(idxPath); err == nil { + var oldIdx SymbolIndex + if json.Unmarshal(oldData, &oldIdx) == nil && oldIdx.Mtime == mtime { + return nil // mtime 一致,无需更新 + } + } + } + + // 创建索引 + idx := SymbolIndex{ + Mtime: mtime, + Data: data, + } + + // 写入 .tmp 再 rename + idxPathTmp := idxPath + ".tmp" + b, err := json.Marshal(idx) + if err != nil { + return fmt.Errorf("marshal index: %w", err) + } + if err := utils.MustWriteFile(idxPathTmp, b); err != nil { + return fmt.Errorf("write index: %w", err) + } + if err := os.Rename(idxPathTmp, idxPath); err != nil { + return fmt.Errorf("rename index: %w", err) + } + return nil +} + +type Symbol struct { + Name string `json:"name"` + File string `json:"file"` + Type string `json:"type"` // FUNC, TYPE, VAR +} + +type ExtractResult struct { + RepoName string `json:"repo_name"` + Files map[string]map[string][]string `json:"files"` // file -> type -> names +} + +func newExtractSymbolCmd() *cobra.Command { + return &cobra.Command{ + Use: "extract_symbol ", + Short: "Extract all symbols from repo JSON", + Long: `Extract all symbol names and file paths from a repository's uniast JSON. +Only extracts filepath + name (no content), for use with search_node.`, + Example: `abcoder cli extract_symbol myrepo`, + Args: cobra.ExactArgs(1), + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + repoName := args[0] + + repoFile := findRepoFile(astsDir, repoName) + if repoFile == "" { + return fmt.Errorf("repo not found: %s", repoName) + } + + data, err := os.ReadFile(repoFile) + if err != nil { + return fmt.Errorf("failed to read repo file: %w", err) + } + + // 获取所有 mod keys(只遍历 keys) + modKeys, err := getModuleKeys(data) + if err != nil { + return err + } + + var files = make(map[string]map[string][]string) + var indexData = make(map[string][]NameMatch) + + // 遍历所有模块 + for _, modPath := range modKeys { + // 跳过外部模块 + isExtVal, _ := sonic.Get(data, "Modules", modPath, "IsExternal") + if isExt, _ := isExtVal.Bool(); isExt { + continue + } + + // 获取所有 package keys(只遍历 keys) + pkgKeys, err := getPackageKeys(data, modPath) + if err != nil { + continue + } + + // 遍历所有包 + for _, pkgPath := range pkgKeys { + // 提取 Functions: 只读取 Name + File(极致按需) + if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Functions"); err == nil { + for _, r := range results { + name, file := r[0], r[1] + if files[file] == nil { + files[file] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } + } + files[file]["FUNC"] = append(files[file]["FUNC"], name) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "FUNC"}) + } + } + + // 提取 Types + if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Types"); err == nil { + for _, r := range results { + name, file := r[0], r[1] + if files[file] == nil { + files[file] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } + } + files[file]["TYPE"] = append(files[file]["TYPE"], name) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "TYPE"}) + } + } + + // 提取 Vars + if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Vars"); err == nil { + for _, r := range results { + name, file := r[0], r[1] + if files[file] == nil { + files[file] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } + } + files[file]["VAR"] = append(files[file]["VAR"], name) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "VAR"}) + } + } + } + } + + // 保存索引文件 + if err := saveSymbolIndex(astsDir, repoName, repoFile, indexData); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to save index: %v\n", err) + } + + // 过滤掉空的 TYPE 和 VAR + for file, types := range files { + if len(types["TYPE"]) == 0 { + delete(types, "TYPE") + } + if len(types["VAR"]) == 0 { + delete(types, "VAR") + } + // 如果 FUNC 也空,删除整个文件 + if len(types["FUNC"]) == 0 { + delete(files, file) + } + } + + result := ExtractResult{ + RepoName: repoName, + Files: files, + } + + b, _ := json.MarshalIndent(result, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/get_file_structure.go b/internal/cmd/cli/get_file_structure.go index 0bec8e72..a01ba5f1 100644 --- a/internal/cmd/cli/get_file_structure.go +++ b/internal/cmd/cli/get_file_structure.go @@ -15,12 +15,10 @@ package cli import ( - "context" "encoding/json" "fmt" "os" - "github.com/cloudwego/abcoder/llm/tool" "github.com/spf13/cobra" ) @@ -41,16 +39,53 @@ Returns a list of functions, types, and variables defined in the file.`, repoName := args[0] filePath := args[1] - tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ - RepoASTsDir: astsDir, - DisableWatch: true, - }) - resp, err := tools.GetFileStructure(context.Background(), tool.GetFileStructReq{ - RepoName: repoName, - FilePath: filePath, - }) + + repoFile := findRepoFile(astsDir, repoName) + if repoFile == "" { + return fmt.Errorf("repo not found: %s", repoName) + } + + // 加载 data(用于后续按需读取) + data, err := loadRepoFileData(repoFile) + if err != nil { + return err + } + + // 1. 定位 pkgPath(极致按需:只读取 File 字段验证) + modPath, pkgPath, err := findPkgPathByFile(data, filePath) if err != nil { - return fmt.Errorf("failed to get file structure: %w", err) + return fmt.Errorf("file '%s' not found in repo", filePath) + } + + // 2. 读取该文件所有 symbols + syms, err := getFileSymbolsByFile(data, modPath, pkgPath, filePath) + if err != nil || len(syms) == 0 { + return fmt.Errorf("no symbols found in file '%s'", filePath) + } + + type Node struct { + Name string `json:"name"` + Line int `json:"line"` + Signature string `json:"signature,omitempty"` + } + + var nodes []Node + for _, sym := range syms { + n := Node{ + Name: sym["Name"].(string), + Line: int(sym["Line"].(float64)), + } + if sig, ok := sym["Signature"].(string); ok { + n.Signature = sig + } + nodes = append(nodes, n) + } + + resp := map[string]interface{}{ + "file_path": filePath, + "mod_path": modPath, + "pkg_path": pkgPath, + "nodes": nodes, } b, _ := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/cli/get_file_symbol.go b/internal/cmd/cli/get_file_symbol.go index 3342916f..d602815e 100644 --- a/internal/cmd/cli/get_file_symbol.go +++ b/internal/cmd/cli/get_file_symbol.go @@ -15,12 +15,10 @@ package cli import ( - "context" "encoding/json" "fmt" "os" - "github.com/cloudwego/abcoder/llm/tool" "github.com/spf13/cobra" ) @@ -41,18 +39,76 @@ Returns the symbol's code, type, line number, and relationship with other symbol repoName := args[0] filePath := args[1] - name := args[2] - tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ - RepoASTsDir: astsDir, - DisableWatch: true, - }) - resp, err := tools.GetFileSymbol(context.Background(), tool.GetFileSymbolReq{ - RepoName: repoName, - FilePath: filePath, - Name: name, - }) + symbolName := args[2] + + repoFile := findRepoFile(astsDir, repoName) + if repoFile == "" { + return fmt.Errorf("repo not found: %s", repoName) + } + + // 加载 data(用于后续按需读取) + data, err := loadRepoFileData(repoFile) + if err != nil { + return err + } + + // 1. 定位 pkgPath(极致按需:只读取 File 字段验证) + modPath, pkgPath, err := findPkgPathByFile(data, filePath) if err != nil { - return fmt.Errorf("failed to get file symbol: %w", err) + return fmt.Errorf("symbol '%s' not found in file '%s'", symbolName, filePath) + } + + // 2. 读取 symbol 完整内容 + sym, err := getSymbolByFileFull(data, modPath, pkgPath, filePath, symbolName) + if err != nil { + return fmt.Errorf("symbol '%s' not found in file '%s'", symbolName, filePath) + } + + // 找到 symbol,构建返回结构 + nodeType := "FUNC" + if t, ok := sym["node_type"].(string); ok { + nodeType = t + } + + signature := "" + if s, ok := sym["Signature"].(string); ok { + signature = s + } + content := "" + if c, ok := sym["Content"].(string); ok { + content = c + } + + // 3. 按需读取 Graph References + refs, err := getSymbolReferences(data, modPath, pkgPath, symbolName) + if err != nil { + fmt.Fprintf(os.Stderr, "DEBUG: getSymbolReferences error: %v\n", err) + return err + } + + // 按 Kind 分类 + var deps, refsOnly []map[string]string + for _, r := range refs { + if r["kind"] == "Dependency" { + deps = append(deps, r) + } else { + refsOnly = append(refsOnly, r) + } + } + + node := map[string]interface{}{ + "name": symbolName, + "type": nodeType, + "file": filePath, + "line": int(sym["Line"].(float64)), + "codes": content, + "signature": signature, + "dependencies": deps, + "references": refsOnly, + } + + resp := map[string]interface{}{ + "node": node, } b, _ := json.MarshalIndent(resp, "", " ") diff --git a/internal/cmd/cli/list_repos.go b/internal/cmd/cli/list_repos.go index 021cf0dc..89dbbeef 100644 --- a/internal/cmd/cli/list_repos.go +++ b/internal/cmd/cli/list_repos.go @@ -52,16 +52,17 @@ The repositories are loaded from .repo_index.json or *.json files in the --asts- var currentRepo string if data, err := os.ReadFile(indexFile); err == nil { - // 解析 repo_index.json - var index struct { - Mappings map[string]string `json:"mappings"` - } - if err := json.Unmarshal(data, &index); err == nil && index.Mappings != nil { - for name, path := range index.Mappings { - repoNames = append(repoNames, name) - // 检查当前目录是否匹配 - if path == cwd { - currentRepo = name + // 用 sonic 解析 mappings + mappingsVal, err := sonic.Get(data, "mappings") + if err == nil { + mappings, err := mappingsVal.Map() + if err == nil { + for name, v := range mappings { + repoNames = append(repoNames, name) + // 检查当前目录是否匹配 (mappings value 是文件名,需要检查对应的 json 文件) + if pathMatchesCwd(astsDir, v.(string), cwd) { + currentRepo = name + } } } } diff --git a/internal/cmd/cli/search_symbol.go b/internal/cmd/cli/search_symbol.go new file mode 100644 index 00000000..a9018adf --- /dev/null +++ b/internal/cmd/cli/search_symbol.go @@ -0,0 +1,254 @@ +// Copyright 2025 CloudWeGo Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cli + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + + "github.com/bytedance/sonic" + "github.com/spf13/cobra" +) + +// SearchResult 搜索结果 +type SearchResult struct { + RepoName string `json:"repo_name"` + Query string `json:"query"` + Results map[string]map[string][]string `json:"results"` // file -> type -> names +} + +// loadSymbolIndex 加载符号索引 +func loadSymbolIndex(astsDir, repoName, repoFile string) (*SymbolIndex, error) { + idxPath := filepath.Join(astsDir, indexDir, repoName+".idx") + + // 检查索引文件是否存在 + if _, err := os.Stat(idxPath); err != nil { + // 索引不存在,返回 nil,让调用者知道需要生成 + return nil, nil + } + + // 读取索引 + data, err := os.ReadFile(idxPath) + if err != nil { + return nil, err + } + + var idx SymbolIndex + if err := json.Unmarshal(data, &idx); err != nil { + return nil, err + } + + // 检查 mtime 是否一致 + repoInfo, err := os.Stat(repoFile) + if err != nil { + return nil, err + } + if idx.Mtime != repoInfo.ModTime().UnixMilli() { + // mtime 不一致,返回 nil,让调用者知道需要重新生成 + return nil, nil + } + + return &idx, nil +} + +// hasRegexMetaChars 检查是否包含正则元字符 +func hasRegexMetaChars(s string) bool { + return strings.ContainsAny(s, ".+?{}[]|\\^$") +} + +// matchName 检查 name 是否匹配 query +// 支持: ripgrep 正则语法 +// - 普通字符串: 包含匹配 (*query*) +// - 含 * : 通配符匹配 (转为 .*) +// - 含其他正则元字符: 正则包含匹配 (.*query.*) +func matchName(name, query string) bool { + // 如果包含 * (通配符) + if strings.Contains(query, "*") { + // 转为 .* 并做包含匹配 + pattern := strings.ReplaceAll(query, "*", ".*") + pattern = ".*" + pattern + ".*" + matched, _ := regexp.MatchString(pattern, name) + return matched + } + + // 如果包含正则元字符,使用正则包含匹配 + if hasRegexMetaChars(query) { + pattern := ".*" + query + ".*" + matched, err := regexp.MatchString(pattern, name) + if err != nil { + // 回退到子串包含匹配 + return strings.Contains(name, query) + } + return matched + } + + // 普通字符串:包含匹配 (*query*) + pattern := ".*" + query + ".*" + matched, _ := regexp.MatchString(pattern, name) + return matched +} + +func newSearchSymbolCmd() *cobra.Command { + return &cobra.Command{ + Use: "search_symbol ", + Short: "Search symbols by name", + Long: `Search symbols in a repository by name pattern. +Supports substring match, prefix match (query*), suffix match (*query), and wildcard (*query*).`, + Example: `abcoder cli search_symbol myrepo GetUser +abcoder cli search_symbol myrepo "*User" +abcoder cli search_symbol myrepo "Get*"`, + Args: cobra.ExactArgs(2), + RunE: func(cmd *cobra.Command, args []string) error { + astsDir, err := getASTsDir(cmd) + if err != nil { + return err + } + + repoName := args[0] + query := args[1] + + repoFile := findRepoFile(astsDir, repoName) + if repoFile == "" { + return fmt.Errorf("repo not found: %s", repoName) + } + + // 尝试加载索引 + idx, err := loadSymbolIndex(astsDir, repoName, repoFile) + if err != nil { + return fmt.Errorf("failed to load index: %w", err) + } + + // 如果索引不存在或过期,需要从 JSON 构建 + if idx == nil { + fmt.Fprintf(os.Stderr, "Index not found or outdated, rebuilding...\n") + data, err := os.ReadFile(repoFile) + if err != nil { + return fmt.Errorf("failed to read repo file: %w", err) + } + + modsVal, err := sonic.Get(data, "Modules") + if err != nil { + return fmt.Errorf("failed to get modules: %w", err) + } + + mods, err := modsVal.Map() + if err != nil { + return fmt.Errorf("failed to parse modules: %w", err) + } + + indexData := make(map[string][]NameMatch) + + for _, modVal := range mods { + mod, ok := modVal.(map[string]interface{}) + if !ok { + continue + } + + pkgs, ok := mod["Packages"].(map[string]interface{}) + if !ok { + continue + } + + for _, pkgVal := range pkgs { + pkg, ok := pkgVal.(map[string]interface{}) + if !ok { + continue + } + + // Functions + if fns, ok := pkg["Functions"].(map[string]interface{}); ok { + for _, fnVal := range fns { + fn, ok := fnVal.(map[string]interface{}) + if !ok { + continue + } + name := fn["Name"].(string) + file := fn["File"].(string) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "FUNC"}) + } + } + + // Types + if types, ok := pkg["Types"].(map[string]interface{}); ok { + for _, typeVal := range types { + t, ok := typeVal.(map[string]interface{}) + if !ok { + continue + } + name := t["Name"].(string) + file := t["File"].(string) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "TYPE"}) + } + } + + // Vars + if vars, ok := pkg["Vars"].(map[string]interface{}); ok { + for _, varVal := range vars { + v, ok := varVal.(map[string]interface{}) + if !ok { + continue + } + name := v["Name"].(string) + file := v["File"].(string) + indexData[name] = append(indexData[name], NameMatch{File: file, Type: "VAR"}) + } + } + } + } + + // 保存索引 + if err := saveSymbolIndex(astsDir, repoName, repoFile, indexData); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to save index: %v\n", err) + } + + idx = &SymbolIndex{ + Mtime: 0, // 临时使用 + Data: indexData, + } + } + + // 搜索 + results := make(map[string]map[string][]string) + for name, matches := range idx.Data { + if matchName(name, query) { + for _, m := range matches { + if results[m.File] == nil { + results[m.File] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } + } + results[m.File][m.Type] = append(results[m.File][m.Type], name) + } + } + } + + output := SearchResult{ + RepoName: repoName, + Query: query, + Results: results, + } + + b, _ := json.MarshalIndent(output, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + }, + } +} diff --git a/internal/cmd/cli/tree_repo.go b/internal/cmd/cli/tree_repo.go index b860c8c4..6b1be04d 100644 --- a/internal/cmd/cli/tree_repo.go +++ b/internal/cmd/cli/tree_repo.go @@ -15,12 +15,14 @@ package cli import ( - "context" "encoding/json" "fmt" "os" + "path/filepath" + "sort" + "strings" - "github.com/cloudwego/abcoder/llm/tool" + "github.com/bytedance/sonic" "github.com/spf13/cobra" ) @@ -40,15 +42,67 @@ Returns a map of directories to file lists.`, } repoName := args[0] - tools := tool.NewASTReadTools(tool.ASTReadToolsOptions{ - RepoASTsDir: astsDir, - DisableWatch: true, - }) - resp, err := tools.TreeRepo(context.Background(), tool.TreeRepoReq{RepoName: repoName}) + repoFile := findRepoFile(astsDir, repoName) + if repoFile == "" { + return fmt.Errorf("repo not found: %s", repoName) + } + + data, err := loadRepoFileData(repoFile) + if err != nil { + return err + } + + // 获取所有 mod keys + modKeys, err := getModuleKeys(data) if err != nil { - return fmt.Errorf("failed to tree repo: %w", err) + return err + } + + // 收集所有文件,按目录聚合 + files := make(map[string][]string) + for _, modPath := range modKeys { + // 跳过外部模块(通过 IsExternal 字段判断) + isExtVal, _ := sonic.Get(data, "Modules", modPath, "IsExternal") + if isExt, _ := isExtVal.Bool(); isExt { + continue + } + + // 只遍历 Files 的 keys(极致按需:不加载 value) + filePaths, err := iterModFiles(data, modPath) + if err != nil { + continue + } + + for _, path := range filePaths { + // 过滤掉非当前仓库的文件 + if strings.HasPrefix(path, "..") { + continue + } + + // 获取目录路径 + dir := filepath.Dir(path) + if dir == "." { + dir = "./" + } + // 添加 '/' 后缀 + if dir != "" && dir != "./" && !strings.HasSuffix(dir, "/") { + dir = dir + "/" + } + + // 获取文件名 + name := filepath.Base(path) + files[dir] = append(files[dir], name) + } + } + + // 排序 + for dir := range files { + sort.Strings(files[dir]) } + resp := map[string]interface{}{ + "files": files, + } b, _ := json.MarshalIndent(resp, "", " ") fmt.Fprintf(os.Stdout, "%s\n", b) return nil diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 49145c74..2553272e 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -18,7 +18,10 @@ import ( "fmt" "os" "path/filepath" + "strings" + "github.com/bytedance/sonic" + "github.com/bytedance/sonic/ast" "github.com/spf13/cobra" ) @@ -36,3 +39,509 @@ func getASTsDir(cmd *cobra.Command) (string, error) { } return astsDir, nil } + +// findRepoFile 查找 repo 对应的 JSON 文件 +func findRepoFile(astsDir, repoName string) string { + // 先尝试直接匹配文件名 + patterns := []string{ + repoName + ".json", + repoName, + } + + // 处理特殊字符 + encoded := strings.ReplaceAll(repoName, "/", "-") + encoded = strings.ReplaceAll(encoded, ":", "-") + patterns = append(patterns, encoded+".json") + + // glob 模式 + patterns = append(patterns, "*-"+encoded+".json") + + for _, pattern := range patterns { + if match, err := filepath.Glob(filepath.Join(astsDir, pattern)); err == nil { + for _, f := range match { + return f + } + } + } + + // 遍历所有文件匹配 + files, _ := filepath.Glob(filepath.Join(astsDir, "*.json")) + for _, f := range files { + if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") { + continue + } + // 读取 id 字段匹配 + if data, err := os.ReadFile(f); err == nil { + if val, err := sonic.Get(data, "id"); err == nil { + if id, err := val.String(); err == nil && id == repoName { + return f + } + } + } + } + + return "" +} + +// loadRepoModules 用 sonic 读取 repo 的 Modules 结构 +func loadRepoModules(repoFile string) (map[string]interface{}, error) { + data, err := os.ReadFile(repoFile) + if err != nil { + return nil, fmt.Errorf("failed to read repo file: %w", err) + } + + modsVal, err := sonic.Get(data, "Modules") + if err != nil { + return nil, fmt.Errorf("failed to get modules: %w", err) + } + mods, err := modsVal.Map() + if err != nil { + return nil, fmt.Errorf("failed to parse modules: %w", err) + } + return mods, nil +} + +// pathMatchesCwd 检查 mappings 中的文件名对应的 json 文件的 Path 字段是否匹配 cwd +func pathMatchesCwd(astsDir, filename, cwd string) bool { + repoFile := filepath.Join(astsDir, filename) + data, err := os.ReadFile(repoFile) + if err != nil { + return false + } + val, err := sonic.Get(data, "Path") + if err != nil { + return false + } + path, err := val.String() + if err != nil { + return false + } + return path == cwd +} + +// loadRepoFileData 读取整个 repo JSON 文件,返回 raw data 供后续 sonic.Get 按需读取 +func loadRepoFileData(repoFile string) ([]byte, error) { + return os.ReadFile(repoFile) +} + +// getModuleKeys 获取 Modules 的所有 key(不加载 value) +func getModuleKeys(data []byte) ([]string, error) { + val, err := sonic.Get(data, "Modules") + if err != nil { + return nil, err + } + var keys []string + iter, err := val.Properties() + if err != nil { + return nil, err + } + var p ast.Pair + for iter.Next(&p) { + keys = append(keys, p.Key) + } + return keys, nil +} + +// getPackageKeys 获取指定 module 下 Packages 的所有 key(不加载 value) +func getPackageKeys(data []byte, modPath string) ([]string, error) { + val, err := sonic.Get(data, "Modules", modPath, "Packages") + if err != nil { + return nil, err + } + var keys []string + iter, err := val.Properties() + if err != nil { + return nil, err + } + var p ast.Pair + for iter.Next(&p) { + keys = append(keys, p.Key) + } + return keys, nil +} + +// iterModFiles 遍历指定 mod 的 Files,只返回 file path(不加载 value) +func iterModFiles(data []byte, modPath string) ([]string, error) { + val, err := sonic.Get(data, "Modules", modPath, "Files") + if err != nil { + return nil, err + } + iter, err := val.Properties() + if err != nil { + return nil, err + } + var keys []string + var p ast.Pair + for iter.Next(&p) { + keys = append(keys, p.Key) + } + return keys, nil +} + +// iterSymbolNameFile 遍历指定 category (Functions/Types/Vars) 的所有 symbol +// 只读取 Name 和 File 字段,不读取完整内容 +// 返回: [][]string{{name, file}, ...} +func iterSymbolNameFile(data []byte, modPath, pkgPath, category string) ([][]string, error) { + val, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath, category) + if err != nil { + return nil, err + } + if !val.Exists() { + return nil, nil + } + iter, err := val.Properties() + if err != nil { + return nil, err + } + var results [][]string + var p ast.Pair + for iter.Next(&p) { + symName := p.Key + // 只读取 File 字段 + fileVal, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath, category, symName, "File") + if err != nil || !fileVal.Exists() { + continue + } + filePath, err := fileVal.String() + if err != nil { + continue + } + results = append(results, []string{symName, filePath}) + } + return results, nil +} + +// findPkgPathByFile 通过 filePath 推导 pkgPath,验证该 pkg 包含该文件 +// 返回: modPath, pkgPath +// 特点:只读取 package 的 file 列表验证,不读取完整内容(极致按需) +func findPkgPathByFile(data []byte, filePath string) (string, string, error) { + derivedPkg := filepath.Dir(filePath) + if derivedPkg == "." { + derivedPkg = "" + } + + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] findPkgPathByFile: filePath=%s, derivedPkg=%s\n", filePath, derivedPkg) + } + + // 1. 遍历 mods,尝试直接定位 + modsVal, err := sonic.Get(data, "Modules") + if err != nil { + return "", "", err + } + modsIter, err := modsVal.Properties() + if err != nil { + return "", "", err + } + var modPair ast.Pair + + for modsIter.Next(&modPair) { + modPath := modPair.Key + + // 拼接完整 pkgPath + var fullPkgPath string + if derivedPkg == "" { + fullPkgPath = modPath + } else { + fullPkgPath = modPath + "/" + derivedPkg + } + + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] trying direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) + } + + // 检查该 package 是否存在且包含该文件(只读 File 字段验证) + if matched, _ := pkgHasFile(data, modPath, fullPkgPath, filePath, "", "Functions"); matched { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] HIT via direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) + } + return modPath, fullPkgPath, nil + } + if matched, _ := pkgHasFile(data, modPath, fullPkgPath, filePath, "", "Types"); matched { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] HIT via direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) + } + return modPath, fullPkgPath, nil + } + if matched, _ := pkgHasFile(data, modPath, fullPkgPath, filePath, "", "Vars"); matched { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] HIT via direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) + } + return modPath, fullPkgPath, nil + } + } + + // 2. 兜底:遍历搜索 + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to findPkgPathByFileField\n") + } + return findPkgPathByFileField(data, filePath) +} + +// findPkgPathByFileField 兜底方案:遍历所有 mod/pkg,通过 File 字段定位 +func findPkgPathByFileField(data []byte, filePath string) (string, string, error) { + modsVal, err := sonic.Get(data, "Modules") + if err != nil { + return "", "", err + } + modsIter, err := modsVal.Properties() + if err != nil { + return "", "", err + } + var modPair ast.Pair + + for modsIter.Next(&modPair) { + modPath := modPair.Key + + pkgsVal, err := sonic.Get(data, "Modules", modPath, "Packages") + if err != nil { + continue + } + pkgsIter, err := pkgsVal.Properties() + if err != nil { + continue + } + var pkgPair ast.Pair + + for pkgsIter.Next(&pkgPair) { + pkgPath := pkgPair.Key + + // 检查 Functions/Types/Vars 是否有该文件 + if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Functions"); matched { + return modPath, pkgPath, nil + } + if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Types"); matched { + return modPath, pkgPath, nil + } + if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Vars"); matched { + return modPath, pkgPath, nil + } + } + } + + return "", "", fmt.Errorf("file not found: %s", filePath) +} + +// pkgHasFile 检查指定 category (Functions/Types/Vars) 中是否有匹配的 file +// 如果 symbolName 不为空,则同时匹配 symbolName +func pkgHasFile(data []byte, modPath, pkgPath, filePath, symbolName, category string) (bool, error) { + categoryVal, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath, category) + if err != nil { + return false, err + } + if !categoryVal.Exists() { + return false, nil + } + + iter, err := categoryVal.Properties() + if err != nil { + return false, err + } + var pair ast.Pair + + for iter.Next(&pair) { + symName := pair.Key + + // 如果指定了 symbolName,则只检查该 symbol + if symbolName != "" && symName != symbolName { + continue + } + + // 只读取 File 字段进行比对 + fileVal, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath, category, symName, "File") + if err != nil { + continue + } + if !fileVal.Exists() { + continue + } + fnFile, err := fileVal.String() + if err != nil { + continue + } + + if fnFile == filePath { + return true, nil + } + } + + return false, nil +} + +// getSymbolByFileFull 完整读取 package 内容后匹配 symbol +// 在找到目标 pkg 后调用此函数读取完整内容 +func getSymbolByFileFull(data []byte, modPath, pkgPath, filePath, symbolName string) (map[string]interface{}, error) { + // 读取目标 package 的内容 + pkgVal, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath) + if err != nil { + return nil, fmt.Errorf("sonic.Get(Packages) failed for %s/%s: %w", modPath, pkgPath, err) + } + if !pkgVal.Exists() { + return nil, fmt.Errorf("Packages does not exist for %s/%s", modPath, pkgPath) + } + pkg, err := pkgVal.Map() + if err != nil { + return nil, fmt.Errorf("pkgVal.Map() failed: %w", err) + } + + // 检查 Functions + if fns, ok := pkg["Functions"].(map[string]interface{}); ok { + for fnName, fnVal := range fns { + if fnName == symbolName { + fn, ok := fnVal.(map[string]interface{}) + if !ok { + continue + } + if fn["File"] == filePath { + return fn, nil + } + } + } + } + // 检查 Types + if types, ok := pkg["Types"].(map[string]interface{}); ok { + for typeName, typeVal := range types { + if typeName == symbolName { + t, ok := typeVal.(map[string]interface{}) + if !ok { + continue + } + if t["File"] == filePath { + return t, nil + } + } + } + } + // 检查 Vars + if vars, ok := pkg["Vars"].(map[string]interface{}); ok { + for varName, varVal := range vars { + if varName == symbolName { + v, ok := varVal.(map[string]interface{}) + if !ok { + continue + } + if v["File"] == filePath { + return v, nil + } + } + } + } + return nil, fmt.Errorf("symbol not found") +} + +// getFileSymbolsByFile 按需读取: modPath → pkgPath → 获取该文件所有 symbols +func getFileSymbolsByFile(data []byte, modPath, pkgPath, filePath string) ([]map[string]interface{}, error) { + // 读取目标 package 的内容 + pkgVal, err := sonic.Get(data, "Modules", modPath, "Packages", pkgPath) + if err != nil { + return nil, err + } + pkg, err := pkgVal.Map() + if err != nil { + return nil, err + } + + var nodes []map[string]interface{} + + // 检查 Functions + if fns, ok := pkg["Functions"].(map[string]interface{}); ok { + for _, fnVal := range fns { + fn, ok := fnVal.(map[string]interface{}) + if !ok { + continue + } + if fn["File"] == filePath { + fn["node_type"] = "FUNC" + nodes = append(nodes, fn) + } + } + } + // 检查 Types + if types, ok := pkg["Types"].(map[string]interface{}); ok { + for _, typeVal := range types { + t, ok := typeVal.(map[string]interface{}) + if !ok { + continue + } + if t["File"] == filePath { + t["node_type"] = "TYPE" + nodes = append(nodes, t) + } + } + } + // 检查 Vars + if vars, ok := pkg["Vars"].(map[string]interface{}); ok { + for _, varVal := range vars { + v, ok := varVal.(map[string]interface{}) + if !ok { + continue + } + if v["File"] == filePath { + v["node_type"] = "VAR" + nodes = append(nodes, v) + } + } + } + return nodes, nil +} + +// getSymbolReferences 用 sonic 按需读取 Graph 节点的 Dependencies +// Identity 格式: {ModPath}?{PkgPath}#{Name} +func getSymbolReferences(data []byte, modPath, pkgPath, symbolName string) ([]map[string]string, error) { + // Graph key 格式: {ModPath}?{PkgPath}#{Name} + // Python 根目录文件的 PkgPath 是 ".",需要映射为 "." + graphKey := modPath + "?" + pkgPath + "#" + symbolName + + // 使用嵌套 Get 避免特殊字符 (?#) 处理问题 + graphVal, err := sonic.Get(data, "Graph") + if err != nil { + return nil, err + } + nodeVal := graphVal.Get(graphKey) + if !nodeVal.Exists() { + return nil, nil // 没有 Graph 节点,返回空 + } + + // 尝试 Dependencies 或 References + depsVal := nodeVal.Get("Dependencies") + if !depsVal.Exists() { + depsVal = nodeVal.Get("References") + } + if !depsVal.Exists() { + return nil, nil // 没有依赖 + } + + arr, err := depsVal.Array() + if err != nil { + return nil, err + } + + var refs []map[string]string + for _, item := range arr { + m, ok := item.(map[string]interface{}) + if !ok { + continue + } + ref := make(map[string]string) + if v, ok := m["Kind"].(string); ok { + ref["kind"] = v + } + if v, ok := m["Name"].(string); ok { + ref["name"] = v + } + if v, ok := m["ModPath"].(string); ok { + ref["mod_path"] = v + } + if v, ok := m["PkgPath"].(string); ok { + ref["pkg_path"] = v + } + if f, ok := m["File"].(string); ok { + ref["file"] = f + } + if n, ok := m["Line"].(float64); ok { + ref["line"] = fmt.Sprintf("%d", int(n)) + } + refs = append(refs, ref) + } + return refs, nil +} From 94d6a6f90db50ee9241c7dcc3003092fdd911a2b Mon Sep 17 00:00:00 2001 From: simuleite Date: Wed, 4 Mar 2026 14:21:32 +0800 Subject: [PATCH 08/21] Update Asset, Replace MCP with Skill --- .gitignore | 3 +- internal/cmd/assets/.claude/CLAUDE.md | 80 +++++++------------ .../.claude/commands/abcoder/schedule.md | 71 ++++++++++++---- .../skills/abcoder__search_symbol/SKILL.md | 51 ++++++++++++ internal/cmd/init_spec.go | 8 +- 5 files changed, 140 insertions(+), 73 deletions(-) create mode 100644 internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md diff --git a/.gitignore b/.gitignore index 61573efe..5963f29c 100644 --- a/.gitignore +++ b/.gitignore @@ -79,4 +79,5 @@ tools !testdata/asts/*.json -.claude/ \ No newline at end of file +.claude/ +!internal/cmd/assets/.claude/ diff --git a/internal/cmd/assets/.claude/CLAUDE.md b/internal/cmd/assets/.claude/CLAUDE.md index 96679ce3..b383d799 100644 --- a/internal/cmd/assets/.claude/CLAUDE.md +++ b/internal/cmd/assets/.claude/CLAUDE.md @@ -1,76 +1,54 @@ # AST-Driven Coding -你是 AST-Driven Coder,通过整合 `mcp__abcoder` 和 `mcp__sequential_thinking`,为用户提供无幻觉上下文、模糊需求质询、诚实推理和精确执行。 +你是 AST-Driven Coder,通过整合 `skill__abcoder` 和 `mcp__sequential_thinking`,为用户提供无幻觉上下文、模糊需求质询、诚实推理和精确执行。 -## MCP 工具使用体系 +## Tone Style +- 保持诚实:不为"友善"而含糊技术缺陷判断。 +- 面向用户,隐藏实现细节,仅透出必要API出入参数 +- 保持简洁;保持风格一致 -### 工具优先级决策 -**代码分析优先级**: `mcp__abcoder` > Read/Search +## Never break userspace +- 任何导致现有程序崩溃的改动都是bug,无论多么"理论正确" +- 内核的职责是服务用户,而不是教育用户 +- 向后兼容性是不可侵犯的 + +## 工具优先级决策 +**代码分析优先级**: `skill__abcoder` > Read/Search | 工具 | 适用场景 | 核心价值 | |------|----------|----------| -| `mcp__abcoder` | 本地代码深度分析 | UniAST + LSP无幻觉理解代码结构、类型信息、调用链。优于Read/Search | +| `skill__abcoder` | 本地代码深度分析 | UniAST + LSP无幻觉理解代码结构、类型信息、调用链。优于Read/Search | | `mcp__sequential_thinking` | 复杂问题分解 | 多步骤问题的系统化思考 | + ## ABCoder SOP 1. 问题分析: - 基于用户问题分析相关关键词 - - MUST 使用 `list_repos` 确认`repo_name` + - MUST 使用 `list_repos` 确认 `repo_name` -2. 代码定位 (repo→package→node→ast node relationship): - - 2.1 定位package: 基于 `get_repo_structure` 返回的package list选择目标package - - 2.2 定位node: 通过 `get_package_structure` 返回的file信息,确认目标node;无法确认时,调用 `get_files_structure` - - 2.3 确认ast node relationship: 递归调用 `get_ast_node` 获取node详细(dependencies, references, inheritance, implementation, grouping) +2. 代码定位 (repo→file→node→ast symbol relationship): + - 2.1 定位file: 基于 `tree_repo` 返回的file list选择目标file + - 2.2 定位symbol: 通过 `get_file_structure` 返回的file信息,确认目标symbol name + - 2.3 确认ast symbol relationship: 调用 `get_file_symbol` 获取symbol详细(dependencies, references);根据depends/refers的 递归调用`get_file_symbol` ### 开发中的 abcoder 使用 -- 编写前:使用 `get_package_structure` 分析相似代码模式,`get_ast_node` 学习项目最佳实践 +- 编写前:使用 `search_symbol`, `get_file_symbol` 分析相似代码模式、学习项目最佳实践; IMPORTANT: MUST 输出 数据流转API, 对齐所有 Input/Output IDL和类型 ## 分阶段开发理念 - -IMPORTANT: 开发前,MUST 与用户对齐CODE_TASK需求;对于CODE_TASK中不明确的任务(例如任务需要的SDK Method定义、返回值的JSON/IDL),质询用户 -IMPORTANT: 开始开发前,阐述此次CODE_TASK的调用链路、相关SDK Method定义、cURL JSON定义 -### 开发阶段 -1. MVP阶段:核心功能可工作,基本类型安全 -2. 完善阶段:错误处理、边界情况、测试覆盖 -3. 优化阶段:性能优化、代码重构、文档完善 - -## 代码质量标准 - -### 实现要求(按优先级) -MUST: -- Never 使用简化/Mock实现,使用真实SDK/cURL -- 类型安全:核心逻辑必须有明确类型定义 -- 基本错误处理:处理可预见的异常情况 - -SHOULD: -- 完整的边界条件处理 -- 性能敏感场景的优化 -- 复杂逻辑的注释说明 - -COULD: -- 100%遵循SOLID编码规范 -- 极致的性能优化 - -### 验证标准 -- 关键路径和边界条件 MUST 有测试 -- 通过 linter 和类型检查 -- 手动验证主要用户场景 +IMPORTANT: 开发前,MUST 与用户对齐CODE_TASK需求;对于CODE_TASK中不明确的任务(例如任务需要的相关API SDK Method cURL的IDL和类型),质询用户 +IMPORTANT: 开始开发前,阐述此次CODE_TASK的数据流转、调用链路、相关API SDK Method cURL的IDL和类型 ## 用户协作模式 | 用户行为 | 响应策略 | |----------|----------| -| 模糊需求 | 使用 `mcp__sequential_thinking` 澄清,提供具体选项 | -| BUG修复 | 使用 `mcp__abcoder__get_ast_node` 详细分析,根本解决 | -| 重构替换 | 使用 `semgrep` 和 `comby` 结构化搜索替换 | -| 代码分析请求 | MUST 使用 `mcp__abcoder` SOP | +| 模糊需求 | 使用 `AskUserQuestion` 澄清,提供具体选项 | +| BUG修复 | 使用 `skill__abcoder__get_file_symbol` 详细分析,根本解决 | +| 代码分析请求 | MUST 使用 `skill__abcoder` SOP | ## 执行要求 -1. 绝不假设 - 任何不确定代码,MUST 通过`mcp__abcoder__get_ast_node`工具验证 -2. 工具链整合 - 充分利用ABCoder等工具提升效率 -3. 质量内建 - 代码质量要求融入每个环节 -4. 渐进交付 - 复杂任务分解为可验证的小步骤 - -- **使用SubAgent时提醒使用ABCoder** - 当需要使用subAgent(如@agent-Explore、@agent-coding-executor)进行代码分析时,应该提醒SubAgent使用`mcp__abcoder__get_ast_node`以获得更准确的分析结果 -- **Never 说英语**:MUST 使用中文 +1. 绝不假设 - 任何不确定代码,MUST 通过`skill__abcoder__get_file_symbol`工具验证 +2. Demo-First - 任何新引入的外部库API,优先编写Demo代码, 验证数据流转,调试通过后根据项目上下文编写TDD;最后更新项目代码 +3. 工具链整合 - 充分利用ABCoder等工具提升效率 +4. 数据流转 - 使用一切方法(ABCoder, `go doc`, ...)明确数据流转API的Input/Output IDL和类型; 明确后, 才能更新项目代码 diff --git a/internal/cmd/assets/.claude/commands/abcoder/schedule.md b/internal/cmd/assets/.claude/commands/abcoder/schedule.md index be81cd09..30ae3ce9 100644 --- a/internal/cmd/assets/.claude/commands/abcoder/schedule.md +++ b/internal/cmd/assets/.claude/commands/abcoder/schedule.md @@ -1,34 +1,71 @@ --- name: ABCoder: Schedule -description: Design implementation plan using mcp__abcoder analysis and code exploration. +description: Design implementation plan using skill__abcoder analysis and code exploration. category: ABCoder tags: [abcoder, schedule, planning] --- -使用mcp__abcoder分析相关仓库(下钻到mcp__abcoder__get_ast_node查看细节),帮助用户设计实现方案。 -**Guardrails** -- 最大化复用项目已有功能,避免重复造轮子。 +使用`skill__abcoder`分析相关仓库(下钻到`skill__abcoder__get_file_symbol`查看细节),帮助用户设计实现方案。 + +## Guardrails +IMPORTANT: 默认保持向后兼容;但是如果新需求和旧代码存在冲突,请你清晰具体告知,质询用户 +IMPORTANT: 制定系统、根本性的解决方案 +- 最大化复用项目已有功能、优先使用外部成熟库;不重复造轮子。 +- 学习项目/外部库已有最佳实践;保持风格一致。 - 优先采用直接、最小改动的实现方式,只有在用户明确要求时才增加复杂度。 -- 严格限制修改影响面在所请求的结果范围内。 -- 找出任何模糊或含糊不清的细节,并在修改文件前提出必要的后续问题。 -- 在 Schedule 阶段禁止编写代码,禁止使用 agent。 +- 严格限制修改影响面在必要但**全面**范围。 +- 找出任何模糊或含糊不清的细节,并在`abcoder:spec`前提出必要的后续问题。 +- 在Schedule阶段禁止编写代码,禁止使用agent。 +IMPORTANT: MUST 从`skill__abcoder__list_repos`开始, 下钻到`skill__abcoder__get_file_symbol` + +在开始任何分析前,先问自己: +1. "这是个真问题还是臆想出来的?" - 拒绝过度设计 +2. "有更简单的方法吗?" - 永远寻找最简方案 +3. "会破坏什么吗?" - 向后兼容是铁律 + +结构化问题分解思考 + 第一层:数据结构分析. "Bad programmers worry about the code. Good programmers worry about data structures." + - 核心数据IDL是什么?它们的关系如何?类型是否兼容 + - 数据流向哪里?谁拥有它?谁修改它? + - 有没有不必要的数据复制或转换? + 第二层:特殊情况识别. "好代码没有特殊情况" + - 找出所有 if/else 分支 + - 哪些是真正的业务逻辑?哪些是糟糕设计的补丁? + - 能否重新设计数据结构来消除这些分支? + 第三层:复杂度审查. "如果实现需要超过3层缩进,重新设计它" + - 这个功能的本质是什么?(一句话说清) + - 当前方案用了多少概念来解决? + - 能否减少到一半?再少一半? + 第四层:破坏性分析. "Never break userspace" - 向后兼容是铁律 + - 列出所有可能受影响的现有功能 + - 哪些依赖会被破坏? + - 如何在不破坏任何东西的前提下改进? + 第五层:实用性验证. "Theory and practice sometimes clash. Theory loses. Every single time." + - 这个问题在生产环境真实存在吗? + - 有多少用户真正遇到这个问题? + - 解决方案的复杂度是否与问题的严重性匹配? + +## Style +- 面向E2E用户,隐藏实现细节(一句话总结) +- 仅暴露必要的SDK/API/Method出入参数 +- 保持简洁, 回复保持在500字以内;除非用户明确要求,不要包含代码函数体,仅透出signature、IDL数据流向 **Steps** Track these steps as TODOs and complete them one by one. -1. 从 `mcp__abcoder__get_repo_structure` 开始,获取目标仓库结构。 -2. 根据任务描述,定位相关的 package。 -3. 使用 `mcp__abcoder__get_package_structure` 获取 package 内的文件和节点列表。 -4. 使用 `mcp__abcoder__get_ast_node` 深入分析相关代码节点,理解现有实现模式。 -5. 分析依赖关系、调用链、类型信息等。 +1. 从 `skill__abcoder__tree_repo` 开始,获取目标仓库结构。 +2. 根据任务描述,生成pattern, `skill__abcoder__search_symbol` 定位相关的 symbol。 +3. 使用 `skill__abcoder__get_file_structure` 获取 file 所有 symbol。 +4. 使用 `skill__abcoder__get_file_symbol` 获取 symbol 源代码/dependence/reference, 使用depend/refer的file-path和name, 继续调用 `get_file_symbol`, 追溯数据流向。 +5. 分析依赖关系、数据流向调用链、类型信息等。 6. 设计实现方案,确保最大化复用已有功能、最小化改动。 7. 找出任何模糊或缺失的技术细节,并向用户提出后续问题。 8. 输出清晰的技术方案,包括修改范围、涉及的文件、关键实现步骤。 **Reference** -- `mcp__abcoder__list_repos` - 列出所有可用仓库 -- `mcp__abcoder__get_repo_structure` - 获取仓库结构(必须作为第一步) -- `mcp__abcoder__get_package_structure` - 获取 package 结构 -- `mcp__abcoder__get_file_structure` - 获取文件结构 -- `mcp__abcoder__get_ast_node` - 获取 AST 节点详情(下钻分析) +- `skill__abcoder__list_repos` - 列出所有可用仓库 +- `skill__abcoder__tree_repo` - 获取仓库结构(必须作为第一步) +- `skill__abcoder__search_symbol` - 搜索仓库的相关symbol(支持regex pattern) +- `skill__abcoder__get_file_structure` - 获取 file 的所有 symbol +- `skill__abcoder__get_file_symbol` - 获取 symbol 的 源代码/dependence/reference diff --git a/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md new file mode 100644 index 00000000..f0f054bf --- /dev/null +++ b/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md @@ -0,0 +1,51 @@ +--- +name: skill__abcoder__search_symbol +description: skill__abcoder__search_symbol `abcoder cli search_symbol ` Search symbols in a repository by name pattern. Supports substring match, prefix match (pattern*), suffix match (*pattern), and wildcard (*pattern*). You MUST call `get_file_symbol` later. +--- + +Execute the search_symbol command to search symbols by name: + +```bash +abcoder cli search_symbol +``` + +## Examples + +```bash +# Substring match - search for "Get" in all symbol names +abcoder cli search_symbol myrepo Get + +# Prefix match - search for symbols starting with "Get" +abcoder cli search_symbol myrepo "Get*" + +# Suffix match - search for symbols ending with "User" +abcoder cli search_symbol myrepo "*User" + +# Wildcard match - search for symbols containing "GetUser" +abcoder cli search_symbol myrepo "*GetUser*" +``` + +## Output Format + +```json +{ + "repo_name": "string", + "pattern": "string", + "results": { + "file_path": { + "FUNC": ["function_name1", "function_name2"], + "TYPE": ["type_name"], + "VAR": ["var_name"] + } + } +} +``` + +## Notes + +A powerful search tool based on ABCoder + + Usage: - ALWAYS use `abcoder__search_symbol` for search tasks. NEVER invoke `grep` or `rg` as a Bash command. The `abcoder__search_symbol` tool has been optimized for correct permissions and access. + - Supports full regex syntax (e.g., "Get*", "Domain*Controller") + - Dynamic patterns for open-ended searches requiring multiple rounds + - Pattern syntax: Uses ripgrep (not grep) - literal braces need escaping (use `interface\{\}` to find `interface{}` in Go code) diff --git a/internal/cmd/init_spec.go b/internal/cmd/init_spec.go index 8649c75e..98685a3d 100644 --- a/internal/cmd/init_spec.go +++ b/internal/cmd/init_spec.go @@ -81,10 +81,10 @@ func RunInitSpec(targetDir string) error { } claudeConfigPath := filepath.Join(homeDir, ".claude.json") - if err := configureMCPServers(claudeConfigPath, astsDir); err != nil { - return fmt.Errorf("failed to configure MCP servers: %w", err) - } - log.Info("Configured MCP servers in %s", claudeConfigPath) + // if err := configureMCPServers(claudeConfigPath, astsDir); err != nil { + // return fmt.Errorf("failed to configure MCP servers: %w", err) + // } + // log.Info("Configured MCP servers in %s", claudeConfigPath) // 4. Print success message printSuccessMessage(targetDirAbs, claudeConfigPath, astsDir) From 1183b93cc27388b81f11067698bcd55d58680763 Mon Sep 17 00:00:00 2001 From: simuleite Date: Wed, 4 Mar 2026 14:49:46 +0800 Subject: [PATCH 09/21] Compress get_file_symbol Output, Sonic --- internal/cmd/cli/get_file_symbol.go | 27 +++++++++++++++++++---- internal/cmd/cli/utils.go | 34 +++++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/internal/cmd/cli/get_file_symbol.go b/internal/cmd/cli/get_file_symbol.go index d602815e..f0d32f77 100644 --- a/internal/cmd/cli/get_file_symbol.go +++ b/internal/cmd/cli/get_file_symbol.go @@ -86,16 +86,35 @@ Returns the symbol's code, type, line number, and relationship with other symbol return err } - // 按 Kind 分类 - var deps, refsOnly []map[string]string + // 按 Kind 分类,并按 file_path 分组聚合 + depMap := make(map[string][]string) + refMap := make(map[string][]string) for _, r := range refs { + // 通过 ModPath + PkgPath + Name 反向查找 FilePath + filePath := findSymbolFile(data, r["mod_path"], r["pkg_path"], r["name"]) + if r["kind"] == "Dependency" { - deps = append(deps, r) + depMap[filePath] = append(depMap[filePath], r["name"]) } else { - refsOnly = append(refsOnly, r) + refMap[filePath] = append(refMap[filePath], r["name"]) } } + // 转换为 FileNodeID 格式(按 file_path 分组,names 为数组) + var deps, refsOnly []map[string]interface{} + for fp, names := range depMap { + deps = append(deps, map[string]interface{}{ + "file_path": fp, + "names": names, + }) + } + for fp, names := range refMap { + refsOnly = append(refsOnly, map[string]interface{}{ + "file_path": fp, + "names": names, + }) + } + node := map[string]interface{}{ "name": symbolName, "type": nodeType, diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 2553272e..705b5787 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -545,3 +545,37 @@ func getSymbolReferences(data []byte, modPath, pkgPath, symbolName string) ([]ma } return refs, nil } + +// findSymbolFile 通过 ModPath + PkgPath + Name 反向查找 FilePath +// 路径格式: .Modules[ModPath].Packages[PkgPath].Functions[Name].File +func findSymbolFile(data []byte, modPath, pkgPath, name string) string { + if modPath == "" || pkgPath == "" || name == "" { + return "" + } + + // 尝试 Functions + fileVal, _ := sonic.Get(data, "Modules", modPath, "Packages", pkgPath, "Functions", name, "File") + if fileVal.Exists() { + if f, err := fileVal.String(); err == nil { + return f + } + } + + // 尝试 Types + fileVal, _ = sonic.Get(data, "Modules", modPath, "Packages", pkgPath, "Types", name, "File") + if fileVal.Exists() { + if f, err := fileVal.String(); err == nil { + return f + } + } + + // 尝试 Vars + fileVal, _ = sonic.Get(data, "Modules", modPath, "Packages", pkgPath, "Vars", name, "File") + if fileVal.Exists() { + if f, err := fileVal.String(); err == nil { + return f + } + } + + return "" +} From 0434eea5863f3443139487be0d0a4ee16e55bf6f Mon Sep 17 00:00:00 2001 From: simuleite Date: Wed, 4 Mar 2026 15:43:51 +0800 Subject: [PATCH 10/21] When Sonic find null, roll back to non Sonic Loaded --- internal/cmd/cli/utils.go | 87 ++++++++++++++++++++++----------------- 1 file changed, 49 insertions(+), 38 deletions(-) diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 705b5787..41bbe70f 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -271,54 +271,62 @@ func findPkgPathByFile(data []byte, filePath string) (string, string, error) { } } - // 2. 兜底:遍历搜索 + // 2. 全量加载:一次性加载 Modules.Packages,建立索引查找 if verbose { - fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to findPkgPathByFileField\n") + fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to findPkgPathByFileFullLoad\n") } - return findPkgPathByFileField(data, filePath) + return findPkgPathByFileFullLoad(data, filePath) } -// findPkgPathByFileField 兜底方案:遍历所有 mod/pkg,通过 File 字段定位 -func findPkgPathByFileField(data []byte, filePath string) (string, string, error) { - modsVal, err := sonic.Get(data, "Modules") - if err != nil { - return "", "", err - } - modsIter, err := modsVal.Properties() - if err != nil { - return "", "", err - } - var modPair ast.Pair - - for modsIter.Next(&modPair) { - modPath := modPair.Key - - pkgsVal, err := sonic.Get(data, "Modules", modPath, "Packages") - if err != nil { - continue - } - pkgsIter, err := pkgsVal.Properties() - if err != nil { - continue - } - var pkgPair ast.Pair - - for pkgsIter.Next(&pkgPair) { - pkgPath := pkgPair.Key - - // 检查 Functions/Types/Vars 是否有该文件 - if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Functions"); matched { - return modPath, pkgPath, nil +// findPkgPathByFileFullLoad 全量加载方案:一次性加载 Modules.Packages,建立 file→{modPath,pkgPath} 索引 +func findPkgPathByFileFullLoad(data []byte, filePath string) (string, string, error) { + // 一次性反序列化 Modules.Packages(只加载 File 字段) + var result struct { + Modules map[string]struct { + Packages map[string]struct { + Functions map[string]struct { + File string `json:"File"` + } `json:"Functions"` + Types map[string]struct { + File string `json:"File"` + } `json:"Types"` + Vars map[string]struct { + File string `json:"File"` + } `json:"Vars"` + } `json:"Packages"` + } `json:"Modules"` + } + if err := sonic.Unmarshal(data, &result); err != nil { + return "", "", fmt.Errorf("unmarshal failed: %w", err) + } + + // 遍历建立 file → {modPath, pkgPath} 索引 + fileIndex := make(map[string][2]string) + for modPath, mod := range result.Modules { + for pkgPath, pkg := range mod.Packages { + for _, fn := range pkg.Functions { + if fn.File != "" { + fileIndex[fn.File] = [2]string{modPath, pkgPath} + } } - if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Types"); matched { - return modPath, pkgPath, nil + for _, t := range pkg.Types { + if t.File != "" { + fileIndex[t.File] = [2]string{modPath, pkgPath} + } } - if matched, _ := pkgHasFile(data, modPath, pkgPath, filePath, "", "Vars"); matched { - return modPath, pkgPath, nil + for _, v := range pkg.Vars { + if v.File != "" { + fileIndex[v.File] = [2]string{modPath, pkgPath} + } } } } + // 直接查找 + if info, ok := fileIndex[filePath]; ok { + return info[0], info[1], nil + } + return "", "", fmt.Errorf("file not found: %s", filePath) } @@ -393,6 +401,7 @@ func getSymbolByFileFull(data []byte, modPath, pkgPath, filePath, symbolName str continue } if fn["File"] == filePath { + fn["node_type"] = "FUNC" return fn, nil } } @@ -407,6 +416,7 @@ func getSymbolByFileFull(data []byte, modPath, pkgPath, filePath, symbolName str continue } if t["File"] == filePath { + t["node_type"] = "TYPE" return t, nil } } @@ -421,6 +431,7 @@ func getSymbolByFileFull(data []byte, modPath, pkgPath, filePath, symbolName str continue } if v["File"] == filePath { + v["node_type"] = "VAR" return v, nil } } From da7b653362df96ff1de90c00796efb532485df49 Mon Sep 17 00:00:00 2001 From: simuleite Date: Wed, 4 Mar 2026 18:20:20 +0800 Subject: [PATCH 11/21] Add UniAST Index for search_symbol & get_file_structure --- lang/golang/parser/parser.go | 69 ++++++++++++++++++++++++++++++++++++ lang/golang/parser/pkg.go | 3 ++ lang/uniast/ast.go | 22 +++++++++++- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lang/golang/parser/parser.go b/lang/golang/parser/parser.go index 12e53095..13270498 100644 --- a/lang/golang/parser/parser.go +++ b/lang/golang/parser/parser.go @@ -295,6 +295,7 @@ func (p *GoParser) ParseRepo() (Repository, error) { } p.associateStructWithMethods() p.associateImplements() + p.buildNameToLocations() fmt.Fprintf(os.Stderr, "total call packages.Load %d times\n", loadCount) return p.getRepo(), nil } @@ -362,6 +363,74 @@ func (p *GoParser) getRepo() Repository { return p.repo } +// buildNameToLocations 构建 name → files 反向索引 +// 解析完成后调用,一次遍历 Package 填充 +func (p *GoParser) buildNameToLocations() { + if p.repo.NameToLocations == nil { + p.repo.NameToLocations = make(map[string]NameLocations) + } + + for _, mod := range p.repo.Modules { + for _, pkg := range mod.Packages { + // Functions + for name, fn := range pkg.Functions { + if fn.File == "" { + continue + } + loc := p.repo.NameToLocations[name] + // 去重 + exists := false + for _, f := range loc.Files { + if f == fn.File { + exists = true + break + } + } + if !exists { + loc.Files = append(loc.Files, fn.File) + } + p.repo.NameToLocations[name] = loc + } + // Types + for name, t := range pkg.Types { + if t.FileLine.File == "" { + continue + } + loc := p.repo.NameToLocations[name] + exists := false + for _, f := range loc.Files { + if f == t.FileLine.File { + exists = true + break + } + } + if !exists { + loc.Files = append(loc.Files, t.FileLine.File) + } + p.repo.NameToLocations[name] = loc + } + // Vars + for name, v := range pkg.Vars { + if v.FileLine.File == "" { + continue + } + loc := p.repo.NameToLocations[name] + exists := false + for _, f := range loc.Files { + if f == v.FileLine.File { + exists = true + break + } + } + if !exists { + loc.Files = append(loc.Files, v.FileLine.File) + } + p.repo.NameToLocations[name] = loc + } + } + } +} + // ToABS converts a local package path to absolute path // If the path is not a local package, return empty string // func (p *goParser) pkgPathToABS(path PkgPath) string { diff --git a/lang/golang/parser/pkg.go b/lang/golang/parser/pkg.go index a577f060..32eaee09 100644 --- a/lang/golang/parser/pkg.go +++ b/lang/golang/parser/pkg.go @@ -276,6 +276,9 @@ func (p *GoParser) loadPackages(mod *Module, dir string, pkgPath PkgPath) (err e if f.Package == "" { f.Package = pkg.ID f.Imports = imports.Origins + // [新增] 填充 ModPath 和 PkgPath + f.ModPath = mod.Name + f.PkgPath = pkg.ID } if err := p.parseFile(ctx, file); err != nil { return err diff --git a/lang/uniast/ast.go b/lang/uniast/ast.go index d62f5d1f..a3e00ef7 100644 --- a/lang/uniast/ast.go +++ b/lang/uniast/ast.go @@ -95,6 +95,16 @@ type Repository struct { Path string // repo absolute path Modules map[string]*Module // module name => module Graph NodeGraph // node id => node + + // [新增] name → files 反向索引 + // 加速 search_symbol API,无需独立 .idx 文件 + NameToLocations map[string]NameLocations `json:"NameToLocations,omitempty"` +} + +// NameLocations represents all locations of a symbol name +// [新增] 用于反向索引 name → files +type NameLocations struct { + Files []string `json:"Files,omitempty"` } func (r Repository) ID() string { @@ -126,7 +136,14 @@ func NewRepository(name string) Repository { type File struct { Path string Imports []Import `json:",omitempty"` - Package PkgPath `json:",omitempty"` + + // Package 兼容旧字段 + Package PkgPath `json:",omitempty"` + + // [新增] Identity fields for O(1) lookup + // 解析时直接赋值,无需查询 + ModPath ModPath `json:"ModPath,omitempty"` + PkgPath PkgPath `json:"PkgPath,omitempty"` } type Import struct { @@ -569,6 +586,9 @@ type FileLine struct { // NOTICE: start line. line number start from 1 Line int + // [新增] end line number (1-based) + EndLine int `json:"EndLine,omitempty"` + // start offset in file StartOffset int From ab5650cfc5aad3b865ebc79c0a6864ad83d69bca Mon Sep 17 00:00:00 2001 From: simuleite Date: Wed, 4 Mar 2026 19:23:23 +0800 Subject: [PATCH 12/21] Write Index to UniAST --- internal/cmd/cli/search_symbol.go | 129 +++++++++++------------------- internal/cmd/cli/utils.go | 55 +++++++++++-- 2 files changed, 96 insertions(+), 88 deletions(-) diff --git a/internal/cmd/cli/search_symbol.go b/internal/cmd/cli/search_symbol.go index a9018adf..778487b3 100644 --- a/internal/cmd/cli/search_symbol.go +++ b/internal/cmd/cli/search_symbol.go @@ -128,103 +128,70 @@ abcoder cli search_symbol myrepo "Get*"`, return fmt.Errorf("repo not found: %s", repoName) } - // 尝试加载索引 - idx, err := loadSymbolIndex(astsDir, repoName, repoFile) + // 读取 JSON 文件 + data, err := os.ReadFile(repoFile) if err != nil { - return fmt.Errorf("failed to load index: %w", err) + return fmt.Errorf("failed to read repo file: %w", err) } - // 如果索引不存在或过期,需要从 JSON 构建 - if idx == nil { - fmt.Fprintf(os.Stderr, "Index not found or outdated, rebuilding...\n") - data, err := os.ReadFile(repoFile) - if err != nil { - return fmt.Errorf("failed to read repo file: %w", err) - } - - modsVal, err := sonic.Get(data, "Modules") - if err != nil { - return fmt.Errorf("failed to get modules: %w", err) - } - - mods, err := modsVal.Map() - if err != nil { - return fmt.Errorf("failed to parse modules: %w", err) - } - - indexData := make(map[string][]NameMatch) - - for _, modVal := range mods { - mod, ok := modVal.(map[string]interface{}) - if !ok { - continue - } + var results = make(map[string]map[string][]string) - pkgs, ok := mod["Packages"].(map[string]interface{}) - if !ok { - continue + // 方式1: 使用 NameToLocations(新增字段,O(1)) + nameToLocsVal, err := sonic.Get(data, "NameToLocations") + if err == nil && nameToLocsVal.Exists() { + nameToLocs, err := nameToLocsVal.Map() + if err == nil { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] using NameToLocations (new)\n") } - - for _, pkgVal := range pkgs { - pkg, ok := pkgVal.(map[string]interface{}) - if !ok { - continue - } - - // Functions - if fns, ok := pkg["Functions"].(map[string]interface{}); ok { - for _, fnVal := range fns { - fn, ok := fnVal.(map[string]interface{}) - if !ok { - continue + for name := range nameToLocs { + if matchName(name, query) { + locVal := nameToLocsVal.Get(name) + filesVal := locVal.Get("Files") + if filesVal.Exists() { + files, _ := filesVal.Array() + for _, f := range files { + fileStr, _ := f.(string) + if results[fileStr] == nil { + results[fileStr] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } + } + results[fileStr]["FUNC"] = append(results[fileStr]["FUNC"], name) } - name := fn["Name"].(string) - file := fn["File"].(string) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "FUNC"}) - } - } - - // Types - if types, ok := pkg["Types"].(map[string]interface{}); ok { - for _, typeVal := range types { - t, ok := typeVal.(map[string]interface{}) - if !ok { - continue - } - name := t["Name"].(string) - file := t["File"].(string) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "TYPE"}) } } + } - // Vars - if vars, ok := pkg["Vars"].(map[string]interface{}); ok { - for _, varVal := range vars { - v, ok := varVal.(map[string]interface{}) - if !ok { - continue - } - name := v["Name"].(string) - file := v["File"].(string) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "VAR"}) - } + // 如果有结果,直接返回 + if len(results) > 0 { + output := SearchResult{ + RepoName: repoName, + Query: query, + Results: results, } + b, _ := json.MarshalIndent(output, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil } } + } - // 保存索引 - if err := saveSymbolIndex(astsDir, repoName, repoFile, indexData); err != nil { - fmt.Fprintf(os.Stderr, "Warning: failed to save index: %v\n", err) - } - - idx = &SymbolIndex{ - Mtime: 0, // 临时使用 - Data: indexData, - } + // 方式2: 回退到 .idx 文件(旧逻辑) + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to .idx file\n") + } + idx, err := loadSymbolIndex(astsDir, repoName, repoFile) + if err != nil { + return fmt.Errorf("failed to load index: %w", err) + } + if idx == nil { + return fmt.Errorf("no symbol index found for repo: %s", repoName) } // 搜索 - results := make(map[string]map[string][]string) for name, matches := range idx.Data { if matchName(name, query) { for _, m := range matches { diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 41bbe70f..0be00013 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -211,20 +211,64 @@ func iterSymbolNameFile(data []byte, modPath, pkgPath, category string) ([][]str return results, nil } -// findPkgPathByFile 通过 filePath 推导 pkgPath,验证该 pkg 包含该文件 +// findPkgPathByFile 通过 filePath 查找 pkgPath // 返回: modPath, pkgPath -// 特点:只读取 package 的 file 列表验证,不读取完整内容(极致按需) +// 使用 File.ModPath + File.PkgPath 实现 O(1) 查找 func findPkgPathByFile(data []byte, filePath string) (string, string, error) { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] findPkgPathByFile: filePath=%s\n", filePath) + } + + // 1. 遍历 Modules,尝试直接通过 Files[filePath] 找到 File + modsVal, err := sonic.Get(data, "Modules") + if err != nil { + return "", "", err + } + modsIter, err := modsVal.Properties() + if err != nil { + return "", "", err + } + var modPair ast.Pair + + for modsIter.Next(&modPair) { + modPath := modPair.Key + + // 直接查找 Module.Files[filePath] + fileVal, err := sonic.Get(data, "Modules", modPath, "Files", filePath) + if err != nil || !fileVal.Exists() { + continue + } + + // 读取 File.ModPath 和 File.PkgPath(JSON 字段名是大写) + modPathVal, _ := fileVal.Get("ModPath").String() + pkgPathVal, _ := fileVal.Get("PkgPath").String() + + if modPathVal != "" && pkgPathVal != "" { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] HIT via Files: modPath=%s, pkgPath=%s\n", modPathVal, pkgPathVal) + } + return modPathVal, pkgPathVal, nil + } + } + + // 2. 回退:使用旧的推导方式(兼容旧数据) + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to derived path\n") + } + return findPkgPathByFileDerived(data, filePath) +} + +// findPkgPathByFileDerived 通过推导查找 pkgPath(旧逻辑,兼容) +func findPkgPathByFileDerived(data []byte, filePath string) (string, string, error) { derivedPkg := filepath.Dir(filePath) if derivedPkg == "." { derivedPkg = "" } if verbose { - fmt.Fprintf(os.Stderr, "[VERBOSE] findPkgPathByFile: filePath=%s, derivedPkg=%s\n", filePath, derivedPkg) + fmt.Fprintf(os.Stderr, "[VERBOSE] findPkgPathByFileDerived: filePath=%s, derivedPkg=%s\n", filePath, derivedPkg) } - // 1. 遍历 mods,尝试直接定位 modsVal, err := sonic.Get(data, "Modules") if err != nil { return "", "", err @@ -238,7 +282,6 @@ func findPkgPathByFile(data []byte, filePath string) (string, string, error) { for modsIter.Next(&modPair) { modPath := modPair.Key - // 拼接完整 pkgPath var fullPkgPath string if derivedPkg == "" { fullPkgPath = modPath @@ -250,7 +293,6 @@ func findPkgPathByFile(data []byte, filePath string) (string, string, error) { fmt.Fprintf(os.Stderr, "[VERBOSE] trying direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) } - // 检查该 package 是否存在且包含该文件(只读 File 字段验证) if matched, _ := pkgHasFile(data, modPath, fullPkgPath, filePath, "", "Functions"); matched { if verbose { fmt.Fprintf(os.Stderr, "[VERBOSE] HIT via direct: modPath=%s, fullPkgPath=%s\n", modPath, fullPkgPath) @@ -271,7 +313,6 @@ func findPkgPathByFile(data []byte, filePath string) (string, string, error) { } } - // 2. 全量加载:一次性加载 Modules.Packages,建立索引查找 if verbose { fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to findPkgPathByFileFullLoad\n") } From 453a645cd8d7465b0d5cd8c79d495d002140a1d7 Mon Sep 17 00:00:00 2001 From: simuleite Date: Thu, 5 Mar 2026 12:29:11 +0800 Subject: [PATCH 13/21] Keep Sonic Same With LLM Tool --- internal/cmd/cli/extract_symbol.go | 273 ++++++++++++++++++----------- internal/cmd/cli/search_symbol.go | 79 +++++++-- internal/cmd/cli/utils.go | 37 ++-- 3 files changed, 258 insertions(+), 131 deletions(-) diff --git a/internal/cmd/cli/extract_symbol.go b/internal/cmd/cli/extract_symbol.go index f69b8a56..d2c33067 100644 --- a/internal/cmd/cli/extract_symbol.go +++ b/internal/cmd/cli/extract_symbol.go @@ -18,65 +18,113 @@ import ( "encoding/json" "fmt" "os" - "path/filepath" + "strings" "github.com/bytedance/sonic" "github.com/cloudwego/abcoder/lang/utils" + "github.com/cloudwego/abcoder/lang/uniast" "github.com/spf13/cobra" ) -const indexDir = ".index" +// buildNameToLocations 从 JSON 数据构建 NameToLocations +// 如果 pathFilter 不为空,则只收集匹配前缀的 file +// 返回: name -> type -> fileSet (去重) +func buildNameToLocations(data []byte, pathFilter string) (map[string]map[string]map[string]bool, error) { + // 一次性反序列化整个 Modules + var result struct { + Modules map[string]*uniast.Module `json:"modules"` + } + if err := sonic.Unmarshal(data, &result); err != nil { + return nil, err + } -type SymbolIndex struct { - Mtime int64 `json:"mtime"` - Data map[string][]NameMatch `json:"data"` // name -> []NameMatch -} + // name -> type -> files (去重) + nameToTypeFiles := make(map[string]map[string]map[string]bool) -type NameMatch struct { - File string `json:"file"` - Type string `json:"type"` -} + // 遍历所有模块 + for _, mod := range result.Modules { + // 跳过外部模块 + if mod.IsExternal() { + continue + } -// saveSymbolIndex 保存符号索引到 ~/.asts/.index/{repo}.idx -func saveSymbolIndex(astsDir, repoName, repoFile string, data map[string][]NameMatch) error { - // 获取 repo 文件的 mtime - info, err := os.Stat(repoFile) - if err != nil { - return fmt.Errorf("stat repo file: %w", err) - } - mtime := info.ModTime().UnixMilli() - - // 检查现有索引 - idxPath := filepath.Join(astsDir, indexDir, repoName+".idx") - if _, err := os.Stat(idxPath); err == nil { - // 读取现有索引的 mtime - if oldData, err := os.ReadFile(idxPath); err == nil { - var oldIdx SymbolIndex - if json.Unmarshal(oldData, &oldIdx) == nil && oldIdx.Mtime == mtime { - return nil // mtime 一致,无需更新 + // 遍历所有包 + for _, pkg := range mod.Packages { + // 提取 Functions + for name, fn := range pkg.Functions { + if pathFilter != "" && !strings.HasPrefix(fn.File, pathFilter) { + continue + } + if nameToTypeFiles[name] == nil { + nameToTypeFiles[name] = make(map[string]map[string]bool) + } + if nameToTypeFiles[name]["FUNC"] == nil { + nameToTypeFiles[name]["FUNC"] = make(map[string]bool) + } + nameToTypeFiles[name]["FUNC"][fn.File] = true + } + + // 提取 Types + for name, typ := range pkg.Types { + if pathFilter != "" && !strings.HasPrefix(typ.FileLine.File, pathFilter) { + continue + } + if nameToTypeFiles[name] == nil { + nameToTypeFiles[name] = make(map[string]map[string]bool) + } + if nameToTypeFiles[name]["TYPE"] == nil { + nameToTypeFiles[name]["TYPE"] = make(map[string]bool) + } + nameToTypeFiles[name]["TYPE"][typ.FileLine.File] = true + } + + // 提取 Vars + for name, v := range pkg.Vars { + if pathFilter != "" && !strings.HasPrefix(v.FileLine.File, pathFilter) { + continue + } + if nameToTypeFiles[name] == nil { + nameToTypeFiles[name] = make(map[string]map[string]bool) + } + if nameToTypeFiles[name]["VAR"] == nil { + nameToTypeFiles[name]["VAR"] = make(map[string]bool) + } + nameToTypeFiles[name]["VAR"][v.FileLine.File] = true } } } - // 创建索引 - idx := SymbolIndex{ - Mtime: mtime, - Data: data, - } + return nameToTypeFiles, nil +} - // 写入 .tmp 再 rename - idxPathTmp := idxPath + ".tmp" - b, err := json.Marshal(idx) +// saveNameToLocations 写回 NameToLocations 到 JSON 文件 +func saveNameToLocations(repoFile string, nameToLocs map[string][]string) error { + data, err := os.ReadFile(repoFile) if err != nil { - return fmt.Errorf("marshal index: %w", err) + return err } - if err := utils.MustWriteFile(idxPathTmp, b); err != nil { - return fmt.Errorf("write index: %w", err) + + // 使用标准库 JSON 反序列化 + var result map[string]interface{} + if err := json.Unmarshal(data, &result); err != nil { + return err } - if err := os.Rename(idxPathTmp, idxPath); err != nil { - return fmt.Errorf("rename index: %w", err) + + // 添加 NameToLocations + result["NameToLocations"] = nameToLocs + + // 重新Marshal(保持缩进格式) + prettyJSON, err := json.MarshalIndent(result, "", " ") + if err != nil { + return err } - return nil + + // 写入 .tmp 再 rename + tmpPath := repoFile + ".tmp" + if err := utils.MustWriteFile(tmpPath, prettyJSON); err != nil { + return err + } + return os.Rename(tmpPath, repoFile) } type Symbol struct { @@ -116,86 +164,100 @@ Only extracts filepath + name (no content), for use with search_node.`, return fmt.Errorf("failed to read repo file: %w", err) } - // 获取所有 mod keys(只遍历 keys) - modKeys, err := getModuleKeys(data) - if err != nil { - return err - } - - var files = make(map[string]map[string][]string) - var indexData = make(map[string][]NameMatch) - - // 遍历所有模块 - for _, modPath := range modKeys { - // 跳过外部模块 - isExtVal, _ := sonic.Get(data, "Modules", modPath, "IsExternal") - if isExt, _ := isExtVal.Bool(); isExt { - continue + // 方式1: 优先用 sonic 读取 NameToLocations + nameToLocsVal, err := sonic.Get(data, "NameToLocations") + if err == nil && nameToLocsVal.Exists() { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] using existing NameToLocations\n") } - // 获取所有 package keys(只遍历 keys) - pkgKeys, err := getPackageKeys(data, modPath) - if err != nil { - continue - } + // 获取所有 name keys + nameToLocsMap, _ := nameToLocsVal.Map() - // 遍历所有包 - for _, pkgPath := range pkgKeys { - // 提取 Functions: 只读取 Name + File(极致按需) - if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Functions"); err == nil { - for _, r := range results { - name, file := r[0], r[1] - if files[file] == nil { - files[file] = map[string][]string{ - "FUNC": {}, - "TYPE": {}, - "VAR": {}, + // 转换为输出格式: file -> type -> names + files := make(map[string]map[string][]string) + for name := range nameToLocsMap { + filesVal, _ := sonic.Get(data, "NameToLocations", name, "Files") + if filesVal.Exists() { + fileList, err := filesVal.Array() + if err == nil { + for _, f := range fileList { + fileStr, _ := f.(string) + if files[fileStr] == nil { + files[fileStr] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, + } } + // NameToLocations 不区分类型,都归为 FUNC + files[fileStr]["FUNC"] = append(files[fileStr]["FUNC"], name) } - files[file]["FUNC"] = append(files[file]["FUNC"], name) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "FUNC"}) } } + } - // 提取 Types - if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Types"); err == nil { - for _, r := range results { - name, file := r[0], r[1] - if files[file] == nil { - files[file] = map[string][]string{ - "FUNC": {}, - "TYPE": {}, - "VAR": {}, - } - } - files[file]["TYPE"] = append(files[file]["TYPE"], name) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "TYPE"}) - } + result := ExtractResult{ + RepoName: repoName, + Files: files, + } + b, _ := json.MarshalIndent(result, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil + } + + // 方式2: 没有 NameToLocations,遍历提取并写回 JSON + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] building NameToLocations\n") + } + + // 使用公共函数构建 + nameToTypeFiles, err := buildNameToLocations(data, "") + if err != nil { + return err + } + + // 转换为 NameToLocations 格式: name -> []file + // 拍平 type,只保留 files + nameToLocsMap := make(map[string][]string) + for name, typeFiles := range nameToTypeFiles { + fileSet := make(map[string]bool) + for _, files := range typeFiles { + for file := range files { + fileSet[file] = true } + } + var fileList []string + for file := range fileSet { + fileList = append(fileList, file) + } + nameToLocsMap[name] = fileList + } - // 提取 Vars - if results, err := iterSymbolNameFile(data, modPath, pkgPath, "Vars"); err == nil { - for _, r := range results { - name, file := r[0], r[1] - if files[file] == nil { - files[file] = map[string][]string{ - "FUNC": {}, - "TYPE": {}, - "VAR": {}, - } + // 写回 JSON + if err := saveNameToLocations(repoFile, nameToLocsMap); err != nil { + fmt.Fprintf(os.Stderr, "Warning: failed to save NameToLocations: %v\n", err) + } else if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] saved NameToLocations to %s\n", repoFile) + } + + // 转换为输出格式: file -> type -> names + files := make(map[string]map[string][]string) + for name, typeFiles := range nameToTypeFiles { + for typ, fileSet := range typeFiles { + for file := range fileSet { + if files[file] == nil { + files[file] = map[string][]string{ + "FUNC": {}, + "TYPE": {}, + "VAR": {}, } - files[file]["VAR"] = append(files[file]["VAR"], name) - indexData[name] = append(indexData[name], NameMatch{File: file, Type: "VAR"}) } + files[file][typ] = append(files[file][typ], name) } } } - // 保存索引文件 - if err := saveSymbolIndex(astsDir, repoName, repoFile, indexData); err != nil { - fmt.Fprintf(os.Stderr, "Warning: failed to save index: %v\n", err) - } - // 过滤掉空的 TYPE 和 VAR for file, types := range files { if len(types["TYPE"]) == 0 { @@ -204,7 +266,6 @@ Only extracts filepath + name (no content), for use with search_node.`, if len(types["VAR"]) == 0 { delete(types, "VAR") } - // 如果 FUNC 也空,删除整个文件 if len(types["FUNC"]) == 0 { delete(files, file) } diff --git a/internal/cmd/cli/search_symbol.go b/internal/cmd/cli/search_symbol.go index 778487b3..de7805e5 100644 --- a/internal/cmd/cli/search_symbol.go +++ b/internal/cmd/cli/search_symbol.go @@ -33,6 +33,18 @@ type SearchResult struct { Results map[string]map[string][]string `json:"results"` // file -> type -> names } +const indexDir = ".index" + +type SymbolIndex struct { + Mtime int64 `json:"mtime"` + Data map[string][]NameMatch `json:"data"` // name -> []NameMatch +} + +type NameMatch struct { + File string `json:"file"` + Type string `json:"type"` +} + // loadSymbolIndex 加载符号索引 func loadSymbolIndex(astsDir, repoName, repoFile string) (*SymbolIndex, error) { idxPath := filepath.Join(astsDir, indexDir, repoName+".idx") @@ -105,14 +117,17 @@ func matchName(name, query string) bool { } func newSearchSymbolCmd() *cobra.Command { - return &cobra.Command{ + var pathFilter string + + cmd := &cobra.Command{ Use: "search_symbol ", Short: "Search symbols by name", Long: `Search symbols in a repository by name pattern. Supports substring match, prefix match (query*), suffix match (*query), and wildcard (*query*).`, Example: `abcoder cli search_symbol myrepo GetUser abcoder cli search_symbol myrepo "*User" -abcoder cli search_symbol myrepo "Get*"`, +abcoder cli search_symbol myrepo "Get*" +abcoder cli search_symbol myrepo "Graph" --path "src/main/java/com/uniast/parser"`, Args: cobra.ExactArgs(2), RunE: func(cmd *cobra.Command, args []string) error { astsDir, err := getASTsDir(cmd) @@ -152,6 +167,10 @@ abcoder cli search_symbol myrepo "Get*"`, files, _ := filesVal.Array() for _, f := range files { fileStr, _ := f.(string) + // path 前缀过滤 + if pathFilter != "" && !strings.HasPrefix(fileStr, pathFilter) { + continue + } if results[fileStr] == nil { results[fileStr] = map[string][]string{ "FUNC": {}, @@ -179,30 +198,56 @@ abcoder cli search_symbol myrepo "Get*"`, } } - // 方式2: 回退到 .idx 文件(旧逻辑) + // 方式2: 没有 NameToLocations,构建并写回 JSON if verbose { - fmt.Fprintf(os.Stderr, "[VERBOSE] fallback to .idx file\n") + fmt.Fprintf(os.Stderr, "[VERBOSE] building NameToLocations\n") } - idx, err := loadSymbolIndex(astsDir, repoName, repoFile) + + // 使用公共函数构建 + nameToTypeFiles, err := buildNameToLocations(data, pathFilter) if err != nil { - return fmt.Errorf("failed to load index: %w", err) + return err } - if idx == nil { - return fmt.Errorf("no symbol index found for repo: %s", repoName) + + // 写回 JSON(使用完整 path 构建,否则后续搜索会丢失数据) + fullNameToTypeFiles, err := buildNameToLocations(data, "") + if err == nil { + // 转换为 name -> []file 格式 + fullNameToLocsMap := make(map[string][]string) + for name, typeFiles := range fullNameToTypeFiles { + fileSet := make(map[string]bool) + for _, files := range typeFiles { + for file := range files { + fileSet[file] = true + } + } + var fileList []string + for file := range fileSet { + fileList = append(fileList, file) + } + fullNameToLocsMap[name] = fileList + } + if err := saveNameToLocations(repoFile, fullNameToLocsMap); err != nil { + if verbose { + fmt.Fprintf(os.Stderr, "Warning: failed to save NameToLocations: %v\n", err) + } + } else if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] saved NameToLocations to %s\n", repoFile) + } } - // 搜索 - for name, matches := range idx.Data { - if matchName(name, query) { - for _, m := range matches { - if results[m.File] == nil { - results[m.File] = map[string][]string{ + // 转换为输出格式(全部归为 FUNC,因为 JSON 里没存 type) + for name, typeFiles := range nameToTypeFiles { + for _, fileSet := range typeFiles { + for file := range fileSet { + if results[file] == nil { + results[file] = map[string][]string{ "FUNC": {}, "TYPE": {}, "VAR": {}, } } - results[m.File][m.Type] = append(results[m.File][m.Type], name) + results[file]["FUNC"] = append(results[file]["FUNC"], name) } } } @@ -218,4 +263,8 @@ abcoder cli search_symbol myrepo "Get*"`, return nil }, } + + cmd.Flags().StringVar(&pathFilter, "path", "", "filter by file path prefix (e.g., src/main/java/com/uniast/parser)") + + return cmd } diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 0be00013..8abf72cb 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -537,7 +537,7 @@ func getFileSymbolsByFile(data []byte, modPath, pkgPath, filePath string) ([]map return nodes, nil } -// getSymbolReferences 用 sonic 按需读取 Graph 节点的 Dependencies +// getSymbolReferences 用 sonic 按需读取 Graph 节点的 Dependencies 和 References // Identity 格式: {ModPath}?{PkgPath}#{Name} func getSymbolReferences(data []byte, modPath, pkgPath, symbolName string) ([]map[string]string, error) { // Graph key 格式: {ModPath}?{PkgPath}#{Name} @@ -554,16 +554,34 @@ func getSymbolReferences(data []byte, modPath, pkgPath, symbolName string) ([]ma return nil, nil // 没有 Graph 节点,返回空 } - // 尝试 Dependencies 或 References + var refs []map[string]string + + // 读取 Dependencies(当前节点依赖的) depsVal := nodeVal.Get("Dependencies") - if !depsVal.Exists() { - depsVal = nodeVal.Get("References") + if depsVal.Exists() { + deps, err := parseRelationItems(*depsVal, "Dependency") + if err != nil { + return nil, err + } + refs = append(refs, deps...) } - if !depsVal.Exists() { - return nil, nil // 没有依赖 + + // 读取 References(引用当前节点的) + refsVal := nodeVal.Get("References") + if refsVal.Exists() { + refsItems, err := parseRelationItems(*refsVal, "Reference") + if err != nil { + return nil, err + } + refs = append(refs, refsItems...) } - arr, err := depsVal.Array() + return refs, nil +} + +// parseRelationItems 解析关系数组,添加 kind 来源标记 +func parseRelationItems(val ast.Node, kind string) ([]map[string]string, error) { + arr, err := val.Array() if err != nil { return nil, err } @@ -575,9 +593,8 @@ func getSymbolReferences(data []byte, modPath, pkgPath, symbolName string) ([]ma continue } ref := make(map[string]string) - if v, ok := m["Kind"].(string); ok { - ref["kind"] = v - } + // 使用固定的 kind,不依赖 JSON 中的 Kind 字段 + ref["kind"] = kind if v, ok := m["Name"].(string); ok { ref["name"] = v } From ed1612b7f72e71d2011d805eccf8100437128900 Mon Sep 17 00:00:00 2001 From: simuleite Date: Thu, 5 Mar 2026 12:57:05 +0800 Subject: [PATCH 14/21] Get Mono Current Repo --- internal/cmd/cli/list_repos.go | 109 ++++++++++++++++++--------------- internal/cmd/cli/utils.go | 4 +- 2 files changed, 64 insertions(+), 49 deletions(-) diff --git a/internal/cmd/cli/list_repos.go b/internal/cmd/cli/list_repos.go index 89dbbeef..4058ccf6 100644 --- a/internal/cmd/cli/list_repos.go +++ b/internal/cmd/cli/list_repos.go @@ -19,6 +19,7 @@ import ( "fmt" "os" "path/filepath" + "sort" "strings" "github.com/bytedance/sonic" @@ -32,7 +33,7 @@ func newListReposCmd() *cobra.Command { Short: "List available repositories", Long: `List all available repositories in the AST directory. -The repositories are loaded from .repo_index.json or *.json files in the --asts-dir directory.`, +The repositories are loaded from *.json files in the --asts-dir directory.`, Example: `abcoder cli list-repos`, RunE: func(cmd *cobra.Command, args []string) error { astsDir, err := getASTsDir(cmd) @@ -45,77 +46,89 @@ The repositories are loaded from .repo_index.json or *.json files in the --asts- if err != nil { return err } - - // 尝试从 .repo_index.json 读取映射 - indexFile := filepath.Join(astsDir, ".repo_index.json") - var repoNames []string - var currentRepo string - - if data, err := os.ReadFile(indexFile); err == nil { - // 用 sonic 解析 mappings - mappingsVal, err := sonic.Get(data, "mappings") - if err == nil { - mappings, err := mappingsVal.Map() - if err == nil { - for name, v := range mappings { - repoNames = append(repoNames, name) - // 检查当前目录是否匹配 (mappings value 是文件名,需要检查对应的 json 文件) - if pathMatchesCwd(astsDir, v.(string), cwd) { - currentRepo = name - } - } - } - } + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] cwd: %s\n", cwd) } - // 扫描 JSON 文件,使用 sonic 快速读取 + // 扫描所有 JSON 文件,读取 id 和 path repoNamesMap := make(map[string]struct{}) + var currentRepos []string + type pathItem struct { + id string + path string + } + var pathItems []pathItem + files, err := filepath.Glob(filepath.Join(astsDir, "*.json")) if err != nil { return err } + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] found %d json files\n", len(files)) + } for _, f := range files { // 跳过 _repo_index.json if strings.HasSuffix(f, "_repo_index.json") || strings.HasSuffix(f, ".repo_index.json") { continue } - // 使用 sonic 快速读取 id 字段,避免加载整个 JSON + // 使用 sonic 快速读取 id 和 path 字段 if data, err := os.ReadFile(f); err == nil { - val, err := sonic.Get(data, "id") + // 读取 id + idVal, err := sonic.Get(data, "id") + if err != nil { + continue + } + id, err := idVal.String() + if err != nil || id == "" { + continue + } + repoNamesMap[id] = struct{}{} + + // 读取 path + pathVal, err := sonic.Get(data, "Path") if err == nil { - id, err := val.String() - if err == nil && id != "" { - repoNamesMap[id] = struct{}{} + path, err := pathVal.String() + if err == nil && path != "" { + pathItems = append(pathItems, pathItem{id: id, path: path}) } } - // 尝试读取 Path 字段,检查是否匹配当前目录 - if currentRepo == "" { - val, err := sonic.Get(data, "Path") - if err == nil { - path, err := val.String() - if err == nil && path == cwd { - // 从 id 字段获取名称 - val, err := sonic.Get(data, "id") - if err == nil { - id, err := val.String() - if err == nil && id != "" { - currentRepo = id - } - } - } - } + } + } + + // 按 path 排序,用于前缀匹配时提前退出 + sort.Slice(pathItems, func(i, j int) bool { + return pathItems[i].path < pathItems[j].path + }) + + // 查找 cwd 前缀匹配的 repo + for _, item := range pathItems { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] checking: id=%s, path=%s\n", item.id, item.path) + } + // 如果 path 比 cwd 短,不可能匹配,提前退出 + if len(item.path) < len(cwd) { + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] early exit: path shorter than cwd\n") + } + continue + } + if strings.HasPrefix(item.path, cwd) { + currentRepos = append(currentRepos, item.id) + if verbose { + fmt.Fprintf(os.Stderr, "[VERBOSE] MATCH: id=%s, path=%s\n", item.id, item.path) } } } - repoNames = maps.Keys(repoNamesMap) + + repoNames := maps.Keys(repoNamesMap) type ListReposOutput struct { RepoNames []string `json:"repo_names"` - CurrentRepo string `json:"current_repo,omitempty"` + CurrentRepos []string `json:"current_repos,omitempty"` } resp := ListReposOutput{ - RepoNames: repoNames, - CurrentRepo: currentRepo, + RepoNames: repoNames, + CurrentRepos: currentRepos, } b, _ := json.MarshalIndent(resp, "", " ") fmt.Fprintf(os.Stdout, "%s\n", b) diff --git a/internal/cmd/cli/utils.go b/internal/cmd/cli/utils.go index 8abf72cb..f39ee0b0 100644 --- a/internal/cmd/cli/utils.go +++ b/internal/cmd/cli/utils.go @@ -102,6 +102,7 @@ func loadRepoModules(repoFile string) (map[string]interface{}, error) { } // pathMatchesCwd 检查 mappings 中的文件名对应的 json 文件的 Path 字段是否匹配 cwd +// 支持前缀匹配:cwd 以 path 开头(支持 monorepo 场景) func pathMatchesCwd(astsDir, filename, cwd string) bool { repoFile := filepath.Join(astsDir, filename) data, err := os.ReadFile(repoFile) @@ -116,7 +117,8 @@ func pathMatchesCwd(astsDir, filename, cwd string) bool { if err != nil { return false } - return path == cwd + // 前缀匹配:cwd 以 path 开头 + return strings.HasPrefix(cwd, path) } // loadRepoFileData 读取整个 repo JSON 文件,返回 raw data 供后续 sonic.Get 按需读取 From f23558aada84ad0912daab9cdeca878cdcc795c2 Mon Sep 17 00:00:00 2001 From: simuleite Date: Thu, 5 Mar 2026 13:16:42 +0800 Subject: [PATCH 15/21] Update Skill: search_symbol --path --- .../skills/abcoder__search_symbol/SKILL.md | 15 +++++++++++++-- internal/cmd/cli/list_repos.go | 2 +- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md b/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md index f0f054bf..6d31e079 100644 --- a/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md +++ b/internal/cmd/assets/.claude/skills/abcoder__search_symbol/SKILL.md @@ -1,14 +1,22 @@ --- name: skill__abcoder__search_symbol -description: skill__abcoder__search_symbol `abcoder cli search_symbol ` Search symbols in a repository by name pattern. Supports substring match, prefix match (pattern*), suffix match (*pattern), and wildcard (*pattern*). You MUST call `get_file_symbol` later. +description: skill__abcoder__search_symbol `abcoder cli search_symbol [--path ]` Search symbols in a repository by name pattern. Supports substring match, prefix match (pattern*), suffix match (*pattern), wildcard (*pattern*), and path prefix filtering (--path). You MUST call `get_file_symbol` later. --- Execute the search_symbol command to search symbols by name: ```bash -abcoder cli search_symbol +abcoder cli search_symbol [--path ] ``` +## Arguments + +| Argument | Description | +|----------|-------------| +| `repo_name` | Repository name | +| `pattern` | Symbol name pattern (supports *, regex) | +| `--path` | (optional) Filter by file path prefix (e.g., `src/main/java/com/uniast/parser`) | + ## Examples ```bash @@ -23,6 +31,9 @@ abcoder cli search_symbol myrepo "*User" # Wildcard match - search for symbols containing "GetUser" abcoder cli search_symbol myrepo "*GetUser*" + +# Path filter - search symbols in specific directory +abcoder cli search_symbol myrepo "Graph" --path "src/main/java/com/uniast/parser" ``` ## Output Format diff --git a/internal/cmd/cli/list_repos.go b/internal/cmd/cli/list_repos.go index 4058ccf6..82368131 100644 --- a/internal/cmd/cli/list_repos.go +++ b/internal/cmd/cli/list_repos.go @@ -124,7 +124,7 @@ The repositories are loaded from *.json files in the --asts-dir directory.`, type ListReposOutput struct { RepoNames []string `json:"repo_names"` - CurrentRepos []string `json:"current_repos,omitempty"` + CurrentRepos []string `json:"current_repo,omitempty"` } resp := ListReposOutput{ RepoNames: repoNames, From 18495a188a21169c578a975d153a2168a9e59dca Mon Sep 17 00:00:00 2001 From: simuleite Date: Fri, 6 Mar 2026 15:39:19 +0800 Subject: [PATCH 16/21] AI: add output field --- internal/cmd/cli/get_file_structure.go | 5 +++++ internal/cmd/cli/get_file_symbol.go | 3 ++- internal/cmd/cli/search_symbol.go | 29 ++++++++++++++++---------- 3 files changed, 25 insertions(+), 12 deletions(-) diff --git a/internal/cmd/cli/get_file_structure.go b/internal/cmd/cli/get_file_structure.go index a01ba5f1..ca48fc37 100644 --- a/internal/cmd/cli/get_file_structure.go +++ b/internal/cmd/cli/get_file_structure.go @@ -67,6 +67,7 @@ Returns a list of functions, types, and variables defined in the file.`, Name string `json:"name"` Line int `json:"line"` Signature string `json:"signature,omitempty"` + TypeKind string `json:"typeKind,omitempty"` // class, typedef, struct, enum, interface } var nodes []Node @@ -78,6 +79,10 @@ Returns a list of functions, types, and variables defined in the file.`, if sig, ok := sym["Signature"].(string); ok { n.Signature = sig } + // 添加 TypeKind (class, typedef, struct, enum, interface) + if tk, ok := sym["TypeKind"].(string); ok && tk != "" { + n.TypeKind = tk + } nodes = append(nodes, n) } diff --git a/internal/cmd/cli/get_file_symbol.go b/internal/cmd/cli/get_file_symbol.go index f0d32f77..0a1cac6a 100644 --- a/internal/cmd/cli/get_file_symbol.go +++ b/internal/cmd/cli/get_file_symbol.go @@ -93,7 +93,8 @@ Returns the symbol's code, type, line number, and relationship with other symbol // 通过 ModPath + PkgPath + Name 反向查找 FilePath filePath := findSymbolFile(data, r["mod_path"], r["pkg_path"], r["name"]) - if r["kind"] == "Dependency" { + // Dependency, Inherit, Implement 都视为依赖关系 + if r["kind"] == "Dependency" || r["kind"] == "Inherit" || r["kind"] == "Implement" { depMap[filePath] = append(depMap[filePath], r["name"]) } else { refMap[filePath] = append(refMap[filePath], r["name"]) diff --git a/internal/cmd/cli/search_symbol.go b/internal/cmd/cli/search_symbol.go index de7805e5..f174c8ab 100644 --- a/internal/cmd/cli/search_symbol.go +++ b/internal/cmd/cli/search_symbol.go @@ -161,10 +161,19 @@ abcoder cli search_symbol myrepo "Graph" --path "src/main/java/com/uniast/parser } for name := range nameToLocs { if matchName(name, query) { + // 支持两种格式: + // 1. 数组格式: {"GetUser": ["src/user.rs"]} + // 2. 对象格式: {"GetUser": {"Files": ["src/user.rs"]}} locVal := nameToLocsVal.Get(name) + var files []interface{} filesVal := locVal.Get("Files") if filesVal.Exists() { - files, _ := filesVal.Array() + files, _ = filesVal.Array() + } else { + // 尝试数组格式 + files, _ = locVal.Array() + } + if len(files) > 0 { for _, f := range files { fileStr, _ := f.(string) // path 前缀过滤 @@ -184,17 +193,15 @@ abcoder cli search_symbol myrepo "Graph" --path "src/main/java/com/uniast/parser } } - // 如果有结果,直接返回 - if len(results) > 0 { - output := SearchResult{ - RepoName: repoName, - Query: query, - Results: results, - } - b, _ := json.MarshalIndent(output, "", " ") - fmt.Fprintf(os.Stdout, "%s\n", b) - return nil + // 无论是否有结果都直接返回 + output := SearchResult{ + RepoName: repoName, + Query: query, + Results: results, } + b, _ := json.MarshalIndent(output, "", " ") + fmt.Fprintf(os.Stdout, "%s\n", b) + return nil } } From 1f2af21c3ed2e8d7c74156871ee507e770f0772b Mon Sep 17 00:00:00 2001 From: simuleite Date: Sat, 7 Mar 2026 15:22:12 +0800 Subject: [PATCH 17/21] Update IDL --- idl/uniast.proto | 270 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 270 insertions(+) create mode 100644 idl/uniast.proto diff --git a/idl/uniast.proto b/idl/uniast.proto new file mode 100644 index 00000000..55a870b2 --- /dev/null +++ b/idl/uniast.proto @@ -0,0 +1,270 @@ +// uniast.proto - UniAST Universal AST Schema +// This file defines the unified AST format for multiple languages +// Currently used by: Go Parser, Rust Parser (via rust-analyzer) + +syntax = "proto3"; + +package uniast; + +option go_package = "github.com/cloudwego/abcoder/lang/uniast"; + +// ============ Core Types ============ +// Language is a simple string: "go", "rust", "cxx", "python", "typescript", "java", "kotlin" + +// ============ Identity System ============ + +// Identity uniquely identifies a node in the AST +// Format: {ModPath}?{PkgPath}#{Name} +// Example: "github.com/user/repo?path/to/pkg#FunctionName" +message Identity { + string mod_path = 1; // module id, unique within a repo + string pkg_path = 2; // path id, unique within a module + string name = 3; // symbol id, unique within a package +} + +// FileLine represents a filename and line number +message FileLine { + string file = 1; // file path relative to repo root + int32 line = 2; // start line number (1-based) + int32 end_line = 5; // end line number (1-based) [新增] + int32 start_offset = 3; // start byte offset in file + int32 end_offset = 4; // end byte offset in file +} + +// ============ Relation System ============ + +// RelationKind represents the type of relationship between nodes +// Using string for JSON compatibility: "Dependency", "Implement", "Inherit", "Group" +message RelationKind { + string value = 1; +} + +// Relation represents a relationship between two nodes +message Relation { + string kind = 1; // kind of relation as string: "Dependency", "Implement", "Inherit", "Group" + // Flat identity fields (for JSON compatibility with Go implementation) + // NOTE: Use uppercase first char so serde(camelCase) produces PascalCase + string ModPath = 6; + string PkgPath = 7; + string Name = 8; + int32 line = 3; // start line-offset relative to current node's codes + string desc = 4; // information about this relation + string codes = 5; // related codes representing this relation +} + +// ============ Repository ============ + +// Repository represents a parsed codebase +message Repository { + string id = 1; // repository name + string ast_version = 2; // uniast version + string tool_version = 3; // abcoder version + string path = 4; // repo absolute path + RepoVersion repo_version = 5; // repository version info + map modules = 6; // module name => module + map graph = 7; // node id => node + + // [新增] name → files 反向索引 + // 加速 search_symbol API,无需独立 .idx 文件 + // 从 File.function_names/type_names/var_names 推导,不冗余 + map name_to_locations = 8; +} + +// NameLocations represents all locations of a symbol name +// [新增] 用于反向索引 name → files +message NameLocations { + repeated string files = 1; // 包含该 name 的文件列表(去重) +} + +// Repository version info +// NOTE: Proto3 JSON conversion uses camelCase by default +// So commit_hash -> CommitHash, parse_time -> ParseTime +message RepoVersion { + string commit_hash = 1; // Git commit hash (JSON: CommitHash) + string parse_time = 2; // Parse timestamp RFC3339 (JSON: ParseTime) +} + +// ============ Module ============ + +// Module represents a single module/package (e.g., Go module, Rust crate) +message Module { + string language = 1; // language: "go", "rust", "cxx", "python", "typescript", "java", "kotlin" + string version = 2; // module version (e.g., "1.0.0") + string name = 3; // module name + string dir = 4; // relative path to repo root + map packages = 5; // package import path => package + map dependencies = 6; // module name => module_path@version + map files = 7; // relative path => file info + repeated string load_errors = 8; // loading errors + string compress_data = 9; // module compress info +} + +// Node represents a symbol node in the graph +// NOTE: For JSON compatibility with Go implementation, use flat format: +// - mod_path, pkg_path, name (扁平 Identity) +// - type (string: "FUNC", "TYPE", "VAR") +// - dependencies, references, implements, inherits, groups (relations) +message Node { + // Flat identity fields (matching Go's embedded Identity) + string mod_path = 1; + string pkg_path = 2; + string name = 3; + + // Node type as string: "FUNC", "TYPE", "VAR" + string type = 4; + + // Unified relation fields + repeated Relation dependencies = 10; + repeated Relation references = 11; + repeated Relation implements = 12; + repeated Relation inherits = 13; + repeated Relation groups = 14; + +} + +// ============ Package ============ + +message Package { + bool is_main = 1; + bool is_test = 2; + string pkg_path = 3; // package import path + map functions = 4; // function name => function + map types = 5; // type name => type + map vars = 6; // var name => var + string compress_data = 7; // package compress info +} + +// ============ File ============ + +// File represents a source file +// Lightweight index: only stores names, full data in Package/Graph +message File { + string path = 1; // relative path to repo root + repeated Import imports = 2; // import statements + + // Identity fields (matching Module/Package hierarchy) + string mod_path = 3; // module path + string pkg_path = 4; // package path + + // Lightweight symbol name index (reference only, full data in Package) + // [新增] Accelerates get_file_structure API + repeated string function_names = 5; + repeated string type_names = 6; + repeated string var_names = 7; +} + +// Import represents an import/use statement +message Import { + string alias = 1; // optional alias + string path = 2; // raw import path +} + +// ============ Function ============ + +// Function represents a function or method +// NOTE: Using flat fields for JSON compatibility with Go implementation +message Function { + bool exported = 1; // if the function is exported + bool is_method = 2; // if it's a method (has receiver) + bool is_interface_method = 3; // if it's an interface method stub + + // Flat identity fields (matching Go's embedded Identity) + string mod_path = 4; + string pkg_path = 5; + string name = 6; + + // Flat FileLine fields + string file = 7; + int32 line = 8; + + string content = 9; // full function source code + string signature = 10; // function signature + + Receiver receiver = 11; // method receiver (if is_method) + repeated Relation params = 12; // function parameters + repeated Relation results = 13; // function return values +} + +// Receiver represents a method receiver +message Receiver { + bool is_pointer = 1; + Identity type = 2; // receiver type identity +} + +// ============ Type ============ + +// Type represents a struct, enum, trait, or interface +message Type { + bool exported = 1; // if the type is exported + TypeKind type_kind = 2; // struct, interface, enum, typedef + Identity identity = 3; // unique identity + FileLine file_line = 4; // location in source + string content = 5; // type declaration source + + // For struct: field types + repeated Relation sub_struct = 6; // field types + repeated Relation inline_struct = 7; // inherited/anonymous fields + + // Methods defined on this type + map methods = 8; + + // Legacy: use implements relation instead + // repeated Identity implements = 9; + + // LLM compress result + string compress_data = 10; +} + +// TypeKind represents the kind of type +enum TypeKind { + STRUCT = 0; + INTERFACE = 1; + TYPEDEF = 2; + ENUM = 3; +} + +// ============ Variable ============ + +// Var represents a variable or constant +message Var { + bool exported = 1; // if the variable is exported + bool is_const = 2; // if it's a constant + bool is_pointer = 3; // if the type is a pointer + Identity identity = 4; // unique identity + FileLine file_line = 5; // location in source + Identity type = 6; // type of the variable + string content = 7; // variable declaration source + + // Legacy: use relations instead + // repeated Dependency dependencies = 8; + + // For enum variants or grouped constants + repeated Identity groups = 9; + + // LLM compress result + string compress_data = 10; +} + +// ============ Rust-Specific Extensions ============ + +// Rust only: Trait represents a Rust trait +message Trait { + Type base = 1; // embed Type + repeated Identity super_traits = 2; // supertraits + map associated_items = 3; // associated items +} + +// Rust only: Impl represents an impl block +message Impl { + bool is_trait_impl = 1; // if it's a trait impl + Identity trait = 2; // trait being implemented (if any) + Identity self_type = 3; // self type + repeated Identity items = 4; // items in the impl block +} + +// Rust only: Macro represents a macro definition +message Macro { + Identity identity = 1; + FileLine file_line = 2; + string body = 3; // macro body +} From 7f238233a8f4ac207535bd9cf2c3c5ace2c016d4 Mon Sep 17 00:00:00 2001 From: simuleite Date: Thu, 12 Mar 2026 20:53:04 +0800 Subject: [PATCH 18/21] remove uniast json data --- lang/golang/parser/golang.json | 3575 -------------------------------- 1 file changed, 3575 deletions(-) delete mode 100644 lang/golang/parser/golang.json diff --git a/lang/golang/parser/golang.json b/lang/golang/parser/golang.json deleted file mode 100644 index 6578d644..00000000 --- a/lang/golang/parser/golang.json +++ /dev/null @@ -1,3575 +0,0 @@ -{ - "id": "a.b/c", - "ASTVersion": "v0.1.5", - "ToolVersion": "", - "Path": "a.b/c", - "Modules": { - "../.@": { - "Language": "go", - "Version": "", - "Name": "../.", - "Dir": "", - "Packages": { - "a.b/c/pkg": { - "IsMain": false, - "IsTest": false, - "PkgPath": "a.b/c/pkg", - "Functions": { - "CaseStruct.CaseMethod": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "pkg/util.go", - "Line": 42, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer {\n\t_ = json.Unmarshal(in, x)\n\treturn Integer(0)\n}", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct" - } - } - }, - "Case_Func": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func", - "File": "pkg/util.go", - "Line": 25, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func Case_Func(in []byte, s *CaseStruct) error {\n\treturn sonic.Unmarshal(in, s)\n}" - } - }, - "Types": { - "CaseGenericStruct": { - "Exported": true, - "TypeKind": "", - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct", - "File": "pkg/generic.go", - "Line": 30, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type CaseGenericStruct struct{}" - }, - "CaseStruct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 29, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type CaseStruct struct {\n\tFieldPremitive string\n\tFieldType Integer\n\tFieldExternalType entity.MyStruct\n\tFieldInterface InterfaceA\n\tFieldExternalInterface entity.InterfaceB\n\tFieldClosuer func(in string) int\n}", - "Methods": { - "CaseMethod": { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod" - } - } - }, - "Obj": { - "Exported": true, - "TypeKind": "", - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 37, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type Obj struct{}" - } - }, - "Vars": {} - }, - "a.b/c/pkg/entity": { - "IsMain": false, - "IsTest": false, - "PkgPath": "a.b/c/pkg/entity", - "Functions": {}, - "Types": { - "MyStruct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/entity/entity.go", - "Line": 23, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type MyStruct struct {\n\ta string\n\tb string\n\tc MyStructC\n\tMyStructD\n\tEmbed struct {\n\t\t*MyStruct\n\t}\n}" - } - }, - "Vars": {} - } - } - }, - "a.b/c": { - "Language": "go", - "Version": "", - "Name": "a.b/c", - "Dir": ".", - "Packages": { - "a.b/c/merge": { - "IsMain": false, - "IsTest": false, - "PkgPath": "a.b/c/merge", - "Functions": { - "CaseMergeRef": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/merge", - "Name": "CaseMergeRef", - "File": "merge/merge_ref.go", - "Line": 25, - "StartOffset": 685, - "EndOffset": 777, - "Content": "func CaseMergeRef() MyStruct {\n\t_ = G1 + G2\n\treturn MyStruct{\n\t\tMyStructD: MyStructD{},\n\t}\n}", - "Signature": "func CaseMergeRef() MyStruct", - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "merge/merge_ref.go", - "Line": 25, - "StartOffset": 705, - "EndOffset": 713 - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "merge/merge_ref.go", - "Line": 27, - "StartOffset": 737, - "EndOffset": 745 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "merge/merge_ref.go", - "Line": 28, - "StartOffset": 760, - "EndOffset": 769 - } - ], - "GlobalVars": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "merge/merge_ref.go", - "Line": 26, - "StartOffset": 721, - "EndOffset": 723 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/merge", - "Name": "G2", - "File": "merge/merge_ref.go", - "Line": 26, - "StartOffset": 726, - "EndOffset": 728 - } - ] - } - }, - "Types": { - "S": { - "Exported": true, - "TypeKind": "typedef", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/merge", - "Name": "S", - "File": "merge/merge_ref.go", - "Line": 23, - "StartOffset": 667, - "EndOffset": 683, - "Content": "type S MyStructD", - "SubStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "merge/merge_ref.go", - "Line": 23, - "StartOffset": 674, - "EndOffset": 683 - } - ] - } - }, - "Vars": { - "G2": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/merge", - "Name": "G2", - "File": "merge/merge_ref.go", - "Line": 19, - "StartOffset": 642, - "EndOffset": 649, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var G2 = G1", - "Dependencies": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "merge/merge_ref.go", - "Line": 19, - "StartOffset": 647, - "EndOffset": 649 - } - ] - }, - "I1": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/merge", - "Name": "I1", - "File": "merge/merge_ref.go", - "Line": 21, - "StartOffset": 655, - "EndOffset": 665, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer" - }, - "Content": "var I1 Integer" - } - } - }, - "a.b/c/pkg": { - "IsMain": false, - "IsTest": false, - "PkgPath": "a.b/c/pkg", - "Functions": { - "CaseGenericFunc": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericFunc", - "File": "pkg/generic.go", - "Line": 35, - "StartOffset": 893, - "EndOffset": 1036, - "Content": "func CaseGenericFunc[U InterfaceA, T entity.InterfaceB, V any](a T, b U, c V) string {\n\treturn a.String() + fmt.Sprintf(\"%v\", c) + b.String()\n}", - "Signature": "func CaseGenericFunc[U InterfaceA, T entity.InterfaceB, V any](a T, b U, c V) string", - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/generic.go", - "Line": 35, - "StartOffset": 956, - "EndOffset": 959 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/generic.go", - "Line": 35, - "StartOffset": 961, - "EndOffset": 964 - } - ], - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB.String", - "File": "pkg/generic.go", - "Line": 36, - "StartOffset": 990, - "EndOffset": 996, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA.String", - "File": "pkg/generic.go", - "Line": 36, - "StartOffset": 1026, - "EndOffset": 1032, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/generic.go", - "Line": 35, - "StartOffset": 914, - "EndOffset": 926 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/generic.go", - "Line": 35, - "StartOffset": 928, - "EndOffset": 947 - } - ] - }, - "CaseGenericStruct.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct.String", - "File": "pkg/generic.go", - "Line": 31, - "StartOffset": 761, - "EndOffset": 891, - "Content": "func (s *CaseGenericStruct[_, _, _]) String() string {\n\treturn s.Prefix.String() + fmt.Sprintf(\"%v\", s.Data) + s.Subfix.String()\n}", - "Signature": "func (s *CaseGenericStruct[_, _, _]) String() string", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct" - } - }, - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB.String", - "File": "pkg/generic.go", - "Line": 32, - "StartOffset": 833, - "EndOffset": 839, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA.String", - "File": "pkg/generic.go", - "Line": 32, - "StartOffset": 881, - "EndOffset": 887, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/generic.go", - "Line": 31, - "StartOffset": 769, - "EndOffset": 796 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/generic.go", - "Line": 31, - "StartOffset": 769, - "EndOffset": 796 - } - ] - }, - "CaseInterface.CaseMethodDeps": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": true, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseInterface.CaseMethodDeps", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3404, - "EndOffset": 3452, - "Content": "CaseMethodDeps(a int, b entity.MyStruct) Integer", - "Signature": "CaseMethodDeps(a int, b entity.MyStruct) Integer", - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3426, - "EndOffset": 3443 - } - ], - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3445, - "EndOffset": 3452 - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3404, - "EndOffset": 3452 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3404, - "EndOffset": 3452 - } - ] - }, - "CaseStrucLiterMethod": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStrucLiterMethod", - "File": "pkg/util.go", - "Line": 146, - "StartOffset": 2920, - "EndOffset": 3193, - "Content": "func CaseStrucLiterMethod() {\n\t_ = (\u0026CaseStruct{\n\t\tFieldPremitive: \"a\",\n\t\tFieldType: 1,\n\t\tFieldExternalType: entity.MyStruct{},\n\t\tFieldInterface: nil,\n\t\tFieldExternalInterface: nil,\n\t\tFieldClosuer: nil,\n\t}).CaseMethod(nil, nil)\n}", - "Signature": "func CaseStrucLiterMethod()", - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "pkg/util.go", - "Line": 154, - "StartOffset": 3171, - "EndOffset": 3181, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 147, - "StartOffset": 2957, - "EndOffset": 2967 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 150, - "StartOffset": 3062, - "EndOffset": 3070 - } - ] - }, - "CaseStruct.CaseMethod": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "pkg/util.go", - "Line": 42, - "StartOffset": 1080, - "EndOffset": 1200, - "Content": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer {\n\t_ = json.Unmarshal(in, x)\n\treturn Integer(0)\n}", - "Signature": "func (s *CaseStruct) CaseMethod(in []byte, x *entity.MyStruct) Integer", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct" - } - }, - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 42, - "StartOffset": 1123, - "EndOffset": 1141 - } - ], - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 42, - "StartOffset": 1143, - "EndOffset": 1150 - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 44, - "StartOffset": 1188, - "EndOffset": 1195 - } - ] - }, - "CaseStruct.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.String", - "File": "pkg/util.go", - "Line": 47, - "StartOffset": 1202, - "EndOffset": 1279, - "Content": "func (s *CaseStruct) String() string {\n\treturn s.FieldExternalType.String()\n}", - "Signature": "func (s *CaseStruct) String() string", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct" - } - }, - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct.String", - "File": "pkg/util.go", - "Line": 48, - "StartOffset": 1269, - "EndOffset": 1275, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "Case_All": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_All", - "File": "pkg/util.go", - "Line": 77, - "StartOffset": 1668, - "EndOffset": 2120, - "Content": "func Case_All(in string, a entity.MyStruct, b CaseStruct) (int, Integer, entity.Integer) {\n\tvar x entity.Integer\n\tvar y Integer\n\t_ = int(x) + int(y)\n\tvar s CaseStruct\n\t_ = s.CaseMethod(nil, nil)\n\tvar a2 entity.MyStruct\n\t_ = a2.String()\n\tb.FieldClosuer = func(in string) int { return 0 }\n\t_ = b.CaseMethod(nil, nil)\n\ta.MyStructD = entity.MyStructD{}\n\t_ = a.String()\n\t_ = Case_Func(nil, nil)\n\t_ = entity.A(\"\")\n\t_ = GlobalVar + entity.G1\n\treturn 0, 0, 0\n}", - "Signature": "func Case_All(in string, a entity.MyStruct, b CaseStruct) (int, Integer, entity.Integer)", - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 77, - "StartOffset": 1693, - "EndOffset": 1710 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 77, - "StartOffset": 1712, - "EndOffset": 1724 - } - ], - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 77, - "StartOffset": 1732, - "EndOffset": 1739 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 77, - "StartOffset": 1741, - "EndOffset": 1755 - } - ], - "FunctionCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func", - "File": "pkg/util.go", - "Line": 89, - "StartOffset": 2038, - "EndOffset": 2047, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "A", - "File": "pkg/util.go", - "Line": 90, - "StartOffset": 2070, - "EndOffset": 2071, - "Extra": { - "IsInvoked": true - } - } - ], - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "pkg/util.go", - "Line": 82, - "StartOffset": 1842, - "EndOffset": 1852, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct.String", - "File": "pkg/util.go", - "Line": 84, - "StartOffset": 1895, - "EndOffset": 1901, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 78, - "StartOffset": 1773, - "EndOffset": 1780 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 79, - "StartOffset": 1788, - "EndOffset": 1795 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 81, - "StartOffset": 1824, - "EndOffset": 1834 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 83, - "StartOffset": 1878, - "EndOffset": 1886 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "pkg/util.go", - "Line": 87, - "StartOffset": 2005, - "EndOffset": 2014 - } - ], - "GlobalVars": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "GlobalVar", - "File": "pkg/util.go", - "Line": 91, - "StartOffset": 2081, - "EndOffset": 2090 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "pkg/util.go", - "Line": 91, - "StartOffset": 2100, - "EndOffset": 2102 - } - ], - "Extra": { - "AnonymousFunctions": [ - { - "File": "pkg/util.go", - "Line": 85, - "StartOffset": 1922, - "EndOffset": 1954 - } - ] - } - }, - "Case_Chain_Selector": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Chain_Selector", - "File": "pkg/refer.go", - "Line": 46, - "StartOffset": 994, - "EndOffset": 1056, - "Content": "func Case_Chain_Selector() {\n\tvar obj Obj\n\tobj.Call().Call()\n}", - "Signature": "func Case_Chain_Selector()", - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.Call", - "File": "pkg/refer.go", - "Line": 48, - "StartOffset": 1048, - "EndOffset": 1052, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 47, - "StartOffset": 1032, - "EndOffset": 1035 - } - ] - }, - "Case_Closure": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Closure", - "File": "pkg/refer.go", - "Line": 51, - "StartOffset": 1058, - "EndOffset": 1148, - "Content": "func Case_Closure() {\n\tvar obj Obj\n\tobj.CallFunc(func(o Obj) Obj {\n\t\treturn o.Call()\n\t})\n}", - "Signature": "func Case_Closure()", - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.CallFunc", - "File": "pkg/refer.go", - "Line": 53, - "StartOffset": 1098, - "EndOffset": 1106, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.Call", - "File": "pkg/refer.go", - "Line": 54, - "StartOffset": 1136, - "EndOffset": 1140, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 52, - "StartOffset": 1089, - "EndOffset": 1092 - } - ], - "Extra": { - "AnonymousFunctions": [ - { - "File": "pkg/refer.go", - "Line": 53, - "StartOffset": 1107, - "EndOffset": 1145 - } - ] - } - }, - "Case_Func": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func", - "File": "pkg/util.go", - "Line": 25, - "StartOffset": 697, - "EndOffset": 778, - "Content": "func Case_Func(in []byte, s *CaseStruct) error {\n\treturn sonic.Unmarshal(in, s)\n}", - "Signature": "func Case_Func(in []byte, s *CaseStruct) error", - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 25, - "StartOffset": 723, - "EndOffset": 736 - } - ], - "FunctionCalls": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Unmarshal", - "File": "pkg/util.go", - "Line": 26, - "StartOffset": 760, - "EndOffset": 769, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "Case_Func_Func": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func_Func", - "File": "pkg/util.go", - "Line": 72, - "StartOffset": 1598, - "EndOffset": 1666, - "Content": "func Case_Func_Func() {\n\t_ = Case_Func(nil, nil)\n\t_ = entity.A(\"\")\n}", - "Signature": "func Case_Func_Func()", - "FunctionCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func", - "File": "pkg/util.go", - "Line": 73, - "StartOffset": 1627, - "EndOffset": 1636, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "A", - "File": "pkg/util.go", - "Line": 74, - "StartOffset": 1659, - "EndOffset": 1660, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "Case_Func_GloabVar": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func_GloabVar", - "File": "pkg/util.go", - "Line": 53, - "StartOffset": 1300, - "EndOffset": 1363, - "Content": "func Case_Func_GloabVar() int {\n\treturn GlobalVar + entity.G1\n}", - "Signature": "func Case_Func_GloabVar() int", - "GlobalVars": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "GlobalVar", - "File": "pkg/util.go", - "Line": 54, - "StartOffset": 1340, - "EndOffset": 1349 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "pkg/util.go", - "Line": 54, - "StartOffset": 1359, - "EndOffset": 1361 - } - ] - }, - "Case_Func_Global": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func_Global", - "File": "pkg/util.go", - "Line": 111, - "StartOffset": 2453, - "EndOffset": 2634, - "Content": "func Case_Func_Global() {\n\t_ = Enum1\n\t_ = Enum2\n\t_ = Enum3\n\t_ = Enum4\n\t_ = Var1\n\t_ = Var2\n\t_ = Var3\n\t_ = Var4\n\t_ = Var5\n\t_ = Var6\n\t_ = Var7\n\t_ = Var8\n\t_ = entity.G1\n\t_ = entity.V1\n}", - "Signature": "func Case_Func_Global()", - "GlobalVars": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum1", - "File": "pkg/util.go", - "Line": 112, - "StartOffset": 2484, - "EndOffset": 2489 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum2", - "File": "pkg/util.go", - "Line": 113, - "StartOffset": 2495, - "EndOffset": 2500 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum3", - "File": "pkg/util.go", - "Line": 114, - "StartOffset": 2506, - "EndOffset": 2511 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum4", - "File": "pkg/util.go", - "Line": 115, - "StartOffset": 2517, - "EndOffset": 2522 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var1", - "File": "pkg/util.go", - "Line": 116, - "StartOffset": 2528, - "EndOffset": 2532 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var2", - "File": "pkg/util.go", - "Line": 117, - "StartOffset": 2538, - "EndOffset": 2542 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var3", - "File": "pkg/util.go", - "Line": 118, - "StartOffset": 2548, - "EndOffset": 2552 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var4", - "File": "pkg/util.go", - "Line": 119, - "StartOffset": 2558, - "EndOffset": 2562 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var5", - "File": "pkg/util.go", - "Line": 120, - "StartOffset": 2568, - "EndOffset": 2572 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var6", - "File": "pkg/util.go", - "Line": 121, - "StartOffset": 2578, - "EndOffset": 2582 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var7", - "File": "pkg/util.go", - "Line": 122, - "StartOffset": 2588, - "EndOffset": 2592 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var8", - "File": "pkg/util.go", - "Line": 123, - "StartOffset": 2598, - "EndOffset": 2602 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "pkg/util.go", - "Line": 124, - "StartOffset": 2615, - "EndOffset": 2617 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "V1", - "File": "pkg/util.go", - "Line": 125, - "StartOffset": 2630, - "EndOffset": 2632 - } - ] - }, - "Case_Func_Method": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func_Method", - "File": "pkg/util.go", - "Line": 65, - "StartOffset": 1478, - "EndOffset": 1596, - "Content": "func Case_Func_Method() {\n\ts := \u0026CaseStruct{}\n\t_ = s.CaseMethod(nil, nil)\n\ts2 := \u0026entity.MyStruct{}\n\t_ = s2.String()\n}", - "Signature": "func Case_Func_Method()", - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "pkg/util.go", - "Line": 67, - "StartOffset": 1531, - "EndOffset": 1541, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct.String", - "File": "pkg/util.go", - "Line": 69, - "StartOffset": 1586, - "EndOffset": 1592, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 66, - "StartOffset": 1511, - "EndOffset": 1521 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 68, - "StartOffset": 1567, - "EndOffset": 1575 - } - ] - }, - "Case_Func_RefType": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func_RefType", - "File": "pkg/util.go", - "Line": 59, - "StartOffset": 1383, - "EndOffset": 1476, - "Content": "func Case_Func_RefType() int {\n\tvar x entity.Integer\n\tvar y Integer\n\treturn int(x) + int(y)\n}", - "Signature": "func Case_Func_RefType() int", - "Types": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 60, - "StartOffset": 1428, - "EndOffset": 1435 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 61, - "StartOffset": 1443, - "EndOffset": 1450 - } - ] - }, - "Case_Refer_Func": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Refer_Func", - "File": "pkg/refer.go", - "Line": 24, - "StartOffset": 706, - "EndOffset": 773, - "Content": "func Case_Refer_Func() {\n\tsonic.Get(nil, \"\")\n\tsonic.Pretouch(nil)\n}", - "Signature": "func Case_Refer_Func()", - "FunctionCalls": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Get", - "File": "pkg/refer.go", - "Line": 25, - "StartOffset": 738, - "EndOffset": 741, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Pretouch", - "File": "pkg/refer.go", - "Line": 26, - "StartOffset": 758, - "EndOffset": 766, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "Case_Refer_Method": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Refer_Method", - "File": "pkg/refer.go", - "Line": 29, - "StartOffset": 775, - "EndOffset": 835, - "Content": "func Case_Refer_Method() {\n\tn := sonic.Config{}\n\tn.Froze()\n}", - "Signature": "func Case_Refer_Method()", - "MethodCalls": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config.Froze", - "File": "pkg/refer.go", - "Line": 31, - "StartOffset": 826, - "EndOffset": 831, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "pkg/refer.go", - "Line": 30, - "StartOffset": 814, - "EndOffset": 820 - } - ] - }, - "InterfaceA.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": true, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA.String", - "File": "pkg/util.go", - "Line": 39, - "StartOffset": 1061, - "EndOffset": 1076, - "Content": "String() string", - "Signature": "String() string" - }, - "Obj.Call": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.Call", - "File": "pkg/refer.go", - "Line": 38, - "StartOffset": 894, - "EndOffset": 931, - "Content": "func (o Obj) Call() Obj {\n\treturn o\n}", - "Signature": "func (o Obj) Call() Obj", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj" - } - }, - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 38, - "StartOffset": 914, - "EndOffset": 917 - } - ] - }, - "Obj.CallFunc": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.CallFunc", - "File": "pkg/refer.go", - "Line": 42, - "StartOffset": 933, - "EndOffset": 992, - "Content": "func (o Obj) CallFunc(f func(Obj) Obj) Obj {\n\treturn f(o)\n}", - "Signature": "func (o Obj) CallFunc(f func(Obj) Obj) Obj", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj" - } - }, - "Params": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 42, - "StartOffset": 955, - "EndOffset": 970 - } - ], - "Results": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 42, - "StartOffset": 972, - "EndOffset": 975 - } - ] - } - }, - "Types": { - "CaseGenericStruct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct", - "File": "pkg/generic.go", - "Line": 25, - "StartOffset": 654, - "EndOffset": 759, - "Content": "type CaseGenericStruct[T entity.InterfaceB, U InterfaceA, V any] struct {\n\tPrefix T\n\tSubfix U\n\tData V\n}", - "SubStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/generic.go", - "Line": 26, - "StartOffset": 736, - "EndOffset": 737 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/generic.go", - "Line": 27, - "StartOffset": 746, - "EndOffset": 747 - } - ], - "Methods": { - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct.String" - } - }, - "Implements": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA" - } - ] - }, - "CaseInterface": { - "Exported": true, - "TypeKind": "interface", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseInterface", - "File": "pkg/util.go", - "Line": 165, - "StartOffset": 3372, - "EndOffset": 3454, - "Content": "type CaseInterface interface {\n\tCaseMethodDeps(a int, b entity.MyStruct) Integer\n}", - "SubStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3418, - "EndOffset": 3452 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 166, - "StartOffset": 3418, - "EndOffset": 3452 - } - ], - "Methods": { - "CaseMethodDeps": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseInterface.CaseMethodDeps" - } - } - }, - "CaseStruct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 29, - "StartOffset": 780, - "EndOffset": 1030, - "Content": "type CaseStruct struct {\n\tFieldPremitive string\n\tFieldType Integer\n\tFieldExternalType entity.MyStruct\n\tFieldInterface InterfaceA\n\tFieldExternalInterface entity.InterfaceB\n\tFieldClosuer func(in string) int\n}", - "SubStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 31, - "StartOffset": 860, - "EndOffset": 867 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 32, - "StartOffset": 892, - "EndOffset": 907 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/util.go", - "Line": 33, - "StartOffset": 932, - "EndOffset": 942 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/util.go", - "Line": 34, - "StartOffset": 967, - "EndOffset": 984 - } - ], - "Methods": { - "CaseMethod": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod" - }, - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.String" - } - }, - "Implements": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA" - } - ] - }, - "Case_Annoy_Struct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Annoy_Struct", - "File": "pkg/refer.go", - "Line": 58, - "StartOffset": 1150, - "EndOffset": 1213, - "Content": "type Case_Annoy_Struct struct {\n\tA struct {\n\t\tB int\n\t}\n\tC int\n}" - }, - "Case_Refer_Type": { - "Exported": true, - "TypeKind": "typedef", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Refer_Type", - "File": "pkg/refer.go", - "Line": 22, - "StartOffset": 671, - "EndOffset": 704, - "Content": "type Case_Refer_Type sonic.Config", - "SubStruct": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "pkg/refer.go", - "Line": 22, - "StartOffset": 692, - "EndOffset": 704 - } - ] - }, - "Integer": { - "Exported": true, - "TypeKind": "typedef", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 57, - "StartOffset": 1365, - "EndOffset": 1381, - "Content": "type Integer int" - }, - "InterfaceA": { - "Exported": true, - "TypeKind": "interface", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/util.go", - "Line": 38, - "StartOffset": 1032, - "EndOffset": 1078, - "Content": "type InterfaceA interface {\n\tString() string\n}", - "Methods": { - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA.String" - } - } - }, - "Obj": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj", - "File": "pkg/refer.go", - "Line": 36, - "StartOffset": 875, - "EndOffset": 892, - "Content": "type Obj struct{}", - "Methods": { - "Call": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.Call" - }, - "CallFunc": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Obj.CallFunc" - } - } - }, - "Type": { - "Exported": true, - "TypeKind": "typedef", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type", - "File": "pkg/util.go", - "Line": 129, - "StartOffset": 2659, - "EndOffset": 2672, - "Content": "type Type int" - } - }, - "Vars": { - "CaseGenericVar": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericVar", - "File": "pkg/generic.go", - "Line": 39, - "StartOffset": 1042, - "EndOffset": 1110, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseGenericStruct" - }, - "Content": "var CaseGenericVar CaseGenericStruct[entity.InterfaceB, InterfaceA, int]", - "Dependencies": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/generic.go", - "Line": 39, - "StartOffset": 1057, - "EndOffset": 1110 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA", - "File": "pkg/generic.go", - "Line": 39, - "StartOffset": 1057, - "EndOffset": 1110 - } - ] - }, - "CaseVarFunc": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseVarFunc", - "File": "pkg/util.go", - "Line": 157, - "StartOffset": 3199, - "EndOffset": 3370, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct" - }, - "Content": "var CaseVarFunc CaseStruct = func() CaseStruct {\n\treturn CaseStruct{\n\t\tFieldPremitive: Var4,\n\t\tFieldType: Integer(1),\n\t\tFieldExternalType: entity.MyStruct{},\n\t}\n}()", - "Dependencies": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var4", - "File": "pkg/util.go", - "Line": 159, - "StartOffset": 3285, - "EndOffset": 3289 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "pkg/util.go", - "Line": 157, - "StartOffset": 3231, - "EndOffset": 3241 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Integer", - "File": "pkg/util.go", - "Line": 160, - "StartOffset": 3312, - "EndOffset": 3319, - "Extra": { - "IsInvoked": true - } - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/util.go", - "Line": 161, - "StartOffset": 3352, - "EndOffset": 3360 - } - ], - "Extra": { - "AnonymousFunctions": [ - { - "File": "pkg/util.go", - "Line": 157, - "StartOffset": 3224, - "EndOffset": 3368 - } - ] - } - }, - "Case_Ref_Const": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Ref_Const", - "File": "pkg/refer.go", - "Line": 65, - "StartOffset": 1221, - "EndOffset": 1247, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const Case_Ref_Const = entity.G1", - "Dependencies": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "pkg/refer.go", - "Line": 65, - "StartOffset": 1238, - "EndOffset": 1247 - } - ] - }, - "Case_Refer_Var": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Refer_Var", - "File": "pkg/refer.go", - "Line": 34, - "StartOffset": 841, - "EndOffset": 873, - "Type": { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "API" - }, - "Content": "var Case_Refer_Var = sonic.ConfigStd", - "Dependencies": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "ConfigStd", - "File": "pkg/refer.go", - "Line": 34, - "StartOffset": 864, - "EndOffset": 873 - } - ] - }, - "Enum1": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum1", - "File": "pkg/util.go", - "Line": 96, - "StartOffset": 2131, - "EndOffset": 2154, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const Enum1 = 1", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum3" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum4" - } - ] - }, - "Enum2": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum2", - "File": "pkg/util.go", - "Line": 97, - "StartOffset": 2156, - "EndOffset": 2182, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const Enum2, Enum3 = 2, 3" - }, - "Enum3": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum3", - "File": "pkg/util.go", - "Line": 97, - "StartOffset": 2156, - "EndOffset": 2182, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const Enum2, Enum3 = 2, 3", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum1" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum4" - } - ] - }, - "Enum4": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum4", - "File": "pkg/util.go", - "Line": 98, - "StartOffset": 2184, - "EndOffset": 2209, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "string" - }, - "Content": "const Enum4 string = \"4\"", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum1" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Enum3" - } - ] - }, - "False": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False", - "File": "pkg/util.go", - "Line": 135, - "StartOffset": 2765, - "EndOffset": 2770, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const False = 1", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON" - } - ] - }, - "GlobalVar": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "GlobalVar", - "File": "pkg/util.go", - "Line": 51, - "StartOffset": 1285, - "EndOffset": 1298, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var GlobalVar int" - }, - "JSON": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON", - "File": "pkg/util.go", - "Line": 143, - "StartOffset": 2912, - "EndOffset": 2916, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const JSON = 5", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True" - } - ] - }, - "Null": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null", - "File": "pkg/util.go", - "Line": 133, - "StartOffset": 2713, - "EndOffset": 2729, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const Null Type = iota", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON" - } - ] - }, - "Number": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number", - "File": "pkg/util.go", - "Line": 137, - "StartOffset": 2798, - "EndOffset": 2804, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const Number = 2", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON" - } - ] - }, - "String": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String", - "File": "pkg/util.go", - "Line": 139, - "StartOffset": 2834, - "EndOffset": 2840, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const String = 3", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON" - } - ] - }, - "True": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "True", - "File": "pkg/util.go", - "Line": 141, - "StartOffset": 2874, - "EndOffset": 2878, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Type" - }, - "Content": "const True = 4", - "Groups": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Null" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "False" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Number" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "String" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "JSON" - } - ] - }, - "Var1": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var1", - "File": "pkg/util.go", - "Line": 102, - "StartOffset": 2220, - "EndOffset": 2241, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var Var1 = 1" - }, - "Var2": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var2", - "File": "pkg/util.go", - "Line": 103, - "StartOffset": 2243, - "EndOffset": 2267, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var Var2, Var3 = 2, 3" - }, - "Var3": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var3", - "File": "pkg/util.go", - "Line": 103, - "StartOffset": 2243, - "EndOffset": 2267, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var Var2, Var3 = 2, 3" - }, - "Var4": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var4", - "File": "pkg/util.go", - "Line": 104, - "StartOffset": 2269, - "EndOffset": 2292, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "string" - }, - "Content": "var Var4 string = \"4\"" - }, - "Var5": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var5", - "File": "pkg/util.go", - "Line": 105, - "StartOffset": 2294, - "EndOffset": 2327, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "[]string" - }, - "Content": "var Var5 = []string{\"a\"}" - }, - "Var6": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var6", - "File": "pkg/util.go", - "Line": 106, - "StartOffset": 2329, - "EndOffset": 2358, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "func()" - }, - "Content": "var Var6 = func() {}", - "Extra": { - "AnonymousFunctions": [ - { - "File": "pkg/util.go", - "Line": 106, - "StartOffset": 2349, - "EndOffset": 2358 - } - ] - } - }, - "Var7": { - "IsExported": true, - "IsConst": false, - "IsPointer": true, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var7", - "File": "pkg/util.go", - "Line": 107, - "StartOffset": 2360, - "EndOffset": 2413, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "*bool" - }, - "Content": "var Var7 = flag.Bool(\"flag\", false, \"usage\")" - }, - "Var8": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "Var8", - "File": "pkg/util.go", - "Line": 108, - "StartOffset": 2415, - "EndOffset": 2449, - "Type": { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config" - }, - "Content": "var Var8 = sonic.Config{}", - "Dependencies": [ - { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "pkg/util.go", - "Line": 108, - "StartOffset": 2441, - "EndOffset": 2447 - } - ] - } - } - }, - "a.b/c/pkg/entity": { - "IsMain": false, - "IsTest": false, - "PkgPath": "a.b/c/pkg/entity", - "Functions": { - "A": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "A", - "File": "pkg/entity/entity.go", - "Line": 55, - "StartOffset": 1132, - "EndOffset": 1173, - "Content": "func A(in string) int {\n\treturn len(in)\n}", - "Signature": "func A(in string) int" - }, - "InterfaceB.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": true, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB.String", - "File": "pkg/entity/entity.go", - "Line": 34, - "StartOffset": 796, - "EndOffset": 811, - "Content": "String() string", - "Signature": "String() string" - }, - "MyStruct.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct.String", - "File": "pkg/entity/entity.go", - "Line": 37, - "StartOffset": 815, - "EndOffset": 929, - "Content": "func (a MyStruct) String() string {\n\t_ = a.Embed.MyStruct\n\t_ = a.MyStructD\n\treturn \"base struct\" + a.DFunction()\n}", - "Signature": "func (a MyStruct) String() string", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct" - } - }, - "MethodCalls": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD.DFunction", - "File": "pkg/entity/entity.go", - "Line": 40, - "StartOffset": 916, - "EndOffset": 925, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "MyStructC.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructC.String", - "File": "pkg/entity/entity.go", - "Line": 47, - "StartOffset": 1006, - "EndOffset": 1067, - "Content": "func (c MyStructC) String() string {\n\treturn \"I'm struct c\"\n}", - "Signature": "func (c MyStructC) String() string", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructC" - } - } - }, - "MyStructD.DFunction": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD.DFunction", - "File": "pkg/entity/entity.go", - "Line": 43, - "StartOffset": 931, - "EndOffset": 1004, - "Content": "func (c MyStructD) DFunction() string {\n\treturn \"I'm struct d function\"\n}", - "Signature": "func (c MyStructD) DFunction() string", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD" - } - } - }, - "MyStructD.String": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD.String", - "File": "pkg/entity/entity.go", - "Line": 51, - "StartOffset": 1069, - "EndOffset": 1130, - "Content": "func (c MyStructD) String() string {\n\treturn \"I'm struct d\"\n}", - "Signature": "func (c MyStructD) String() string", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD" - } - } - } - }, - "Types": { - "Integer": { - "Exported": true, - "TypeKind": "typedef", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer", - "File": "pkg/entity/entity.go", - "Line": 61, - "StartOffset": 1189, - "EndOffset": 1205, - "Content": "type Integer int" - }, - "InterfaceB": { - "Exported": true, - "TypeKind": "interface", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB", - "File": "pkg/entity/entity.go", - "Line": 33, - "StartOffset": 767, - "EndOffset": 813, - "Content": "type InterfaceB interface {\n\tString() string\n}", - "Methods": { - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB.String" - } - } - }, - "MyStruct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/entity/entity.go", - "Line": 23, - "StartOffset": 666, - "EndOffset": 765, - "Content": "type MyStruct struct {\n\ta string\n\tb string\n\tc MyStructC\n\tMyStructD\n\tEmbed struct {\n\t\t*MyStruct\n\t}\n}", - "SubStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "pkg/entity/entity.go", - "Line": 27, - "StartOffset": 723, - "EndOffset": 732 - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "pkg/entity/entity.go", - "Line": 29, - "StartOffset": 751, - "EndOffset": 760 - } - ], - "InlineStruct": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "pkg/entity/entity.go", - "Line": 27, - "StartOffset": 723, - "EndOffset": 732 - } - ], - "Methods": { - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct.String" - } - }, - "Implements": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA" - } - ] - }, - "MyStructC": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructC", - "File": "pkg/entity/entity.go", - "Line": 17, - "StartOffset": 612, - "EndOffset": 637, - "Content": "type MyStructC struct {\n}", - "Methods": { - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructC.String" - } - }, - "Implements": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB" - } - ] - }, - "MyStructD": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD", - "File": "pkg/entity/entity.go", - "Line": 20, - "StartOffset": 639, - "EndOffset": 664, - "Content": "type MyStructD struct {\n}", - "Methods": { - "DFunction": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD.DFunction" - }, - "String": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStructD.String" - } - }, - "Implements": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "InterfaceB" - }, - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg", - "Name": "InterfaceA" - } - ] - } - }, - "Vars": { - "G1": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "G1", - "File": "pkg/entity/entity.go", - "Line": 59, - "StartOffset": 1181, - "EndOffset": 1187, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const G1 = 1" - }, - "V1": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "V1", - "File": "pkg/entity/entity.go", - "Line": 63, - "StartOffset": 1211, - "EndOffset": 1226, - "Type": { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer" - }, - "Content": "var V1 = Integer(1)", - "Dependencies": [ - { - "ModPath": "a.b/c", - "PkgPath": "a.b/c/pkg/entity", - "Name": "Integer", - "File": "pkg/entity/entity.go", - "Line": 63, - "StartOffset": 1216, - "EndOffset": 1223, - "Extra": { - "IsInvoked": true - } - } - ] - } - } - } - }, - "Dependencies": { - "a.b/c": "a.b/c@7361f67ef606a7ab7dcf1b6d7ebcf1e0188b00f8", - "github.com/bytedance/sonic": "github.com/bytedance/sonic@v1.10.2", - "golang.org/x/arch": "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670" - }, - "Files": { - "cmd/go.mod": { - "Path": "cmd/go.mod" - }, - "cmd/go.sum": { - "Path": "cmd/go.sum" - }, - "cmd/main.go": { - "Path": "cmd/main.go" - }, - "cmd/serdes.go": { - "Path": "cmd/serdes.go" - }, - "go.mod": { - "Path": "go.mod" - }, - "go.sum": { - "Path": "go.sum" - }, - "merge/merge_ref.go": { - "Path": "merge/merge_ref.go", - "Imports": [ - { - "Alias": ".", - "Path": "\"a.b/c/pkg/entity\"" - } - ], - "Package": "a.b/c/merge" - }, - "pkg/entity/entity.go": { - "Path": "pkg/entity/entity.go", - "Package": "a.b/c/pkg/entity" - }, - "pkg/generic.go": { - "Path": "pkg/generic.go", - "Imports": [ - { - "Path": "\"fmt\"" - }, - { - "Path": "\"a.b/c/pkg/entity\"" - } - ], - "Package": "a.b/c/pkg" - }, - "pkg/refer.go": { - "Path": "pkg/refer.go", - "Imports": [ - { - "Path": "\"a.b/c/pkg/entity\"" - }, - { - "Path": "\"github.com/bytedance/sonic\"" - } - ], - "Package": "a.b/c/pkg" - }, - "pkg/util.go": { - "Path": "pkg/util.go", - "Imports": [ - { - "Path": "\"encoding/json\"" - }, - { - "Path": "\"flag\"" - }, - { - "Path": "\"a.b/c/pkg/entity\"" - }, - { - "Path": "\"github.com/bytedance/sonic\"" - } - ], - "Package": "a.b/c/pkg" - } - } - }, - "a.b/c/cmdx": { - "Language": "go", - "Version": "", - "Name": "a.b/c/cmdx", - "Dir": "cmd", - "Packages": { - "a.b/c/cmdx": { - "IsMain": true, - "IsTest": false, - "PkgPath": "a.b/c/cmdx", - "Functions": { - "DuplicateName": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "DuplicateName", - "File": "cmd/serdes.go", - "Line": 36, - "StartOffset": 912, - "EndOffset": 936, - "Content": "func DuplicateName() {\n}", - "Signature": "func DuplicateName()" - }, - "InternalFunc": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "InternalFunc", - "File": "cmd/serdes.go", - "Line": 25, - "StartOffset": 692, - "EndOffset": 910, - "Content": "func InternalFunc(in []byte) {\n\tvar s = new(pkg.CaseStruct)\n\tif err := pkg.Case_Func(in, s); err != nil {\n\t\tprintln(err.Error())\n\t}\n\tvar x = new(entity.MyStruct)\n\tif v := s.CaseMethod(in, x); v != 0 {\n\t\tprintln(v)\n\t}\n}", - "Signature": "func InternalFunc(in []byte)", - "FunctionCalls": [ - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "Case_Func", - "File": "cmd/serdes.go", - "Line": 27, - "StartOffset": 767, - "EndOffset": 776, - "Extra": { - "IsInvoked": true - } - } - ], - "MethodCalls": [ - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "cmd/serdes.go", - "Line": 31, - "StartOffset": 865, - "EndOffset": 875, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "cmd/serdes.go", - "Line": 26, - "StartOffset": 740, - "EndOffset": 750 - }, - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg/entity", - "Name": "MyStruct", - "File": "cmd/serdes.go", - "Line": 30, - "StartOffset": 844, - "EndOffset": 852 - } - ] - }, - "Struct.DuplicateName": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct.DuplicateName", - "File": "cmd/serdes.go", - "Line": 55, - "StartOffset": 1238, - "EndOffset": 1283, - "Content": "func (s *Struct) DuplicateName(in []byte) {\n}", - "Signature": "func (s *Struct) DuplicateName(in []byte)", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct" - } - } - }, - "Struct.InternalMethod": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct.InternalMethod", - "File": "cmd/serdes.go", - "Line": 46, - "StartOffset": 1045, - "EndOffset": 1236, - "Content": "func (s *Struct) InternalMethod(in []byte) {\n\tif err := sonic.Unmarshal(in, \u0026s); err != nil {\n\t\tprintln(err.Error())\n\t}\n\tif err := s.Field2.CaseMethod(in, nil); err != 0 {\n\t\tprintln(err)\n\t}\n}", - "Signature": "func (s *Struct) InternalMethod(in []byte)", - "Receiver": { - "IsPointer": true, - "Type": { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct" - } - }, - "FunctionCalls": [ - { - "ModPath": "github.com/bytedance/sonic@v1.11.3", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Unmarshal", - "File": "cmd/serdes.go", - "Line": 47, - "StartOffset": 1107, - "EndOffset": 1116, - "Extra": { - "IsInvoked": true - } - } - ], - "MethodCalls": [ - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct.CaseMethod", - "File": "cmd/serdes.go", - "Line": 50, - "StartOffset": 1185, - "EndOffset": 1195, - "Extra": { - "IsInvoked": true - } - } - ] - }, - "main": { - "Exported": false, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "main", - "File": "cmd/main.go", - "Line": 24, - "StartOffset": 667, - "EndOffset": 981, - "Content": "func main() {\n\tif len(os.Args) \u003c 2 {\n\t\tprintln(\"missing argument\")\n\t\tos.Exit(1)\n\t}\n\t// content, err := readFile(os.Args[1])\n\t// if err != nil {\n\t// \tprintln(err.Error())\n\t// \tos.Exit(1)\n\t// }\n\tcontent := []byte(\"{}\")\n\tInternalFunc(content)\n\tvar s = new(Struct)\n\ts.Field4 = InternalFunc\n\ts.InternalMethod(content)\n}", - "Signature": "func main()", - "FunctionCalls": [ - { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "InternalFunc", - "File": "cmd/main.go", - "Line": 35, - "StartOffset": 885, - "EndOffset": 897, - "Extra": { - "IsInvoked": true - } - } - ], - "MethodCalls": [ - { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct.InternalMethod", - "File": "cmd/main.go", - "Line": 38, - "StartOffset": 956, - "EndOffset": 970, - "Extra": { - "IsInvoked": true - } - } - ], - "Types": [ - { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct", - "File": "cmd/main.go", - "Line": 36, - "StartOffset": 920, - "EndOffset": 926 - } - ] - }, - "readFile": { - "Exported": false, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "readFile", - "File": "cmd/main.go", - "Line": 41, - "StartOffset": 983, - "EndOffset": 1181, - "Content": "func readFile(path string) ([]byte, error) {\n\tfile, err := os.Open(path)\n\tif err != nil {\n\t\treturn nil, errors.Wrap(err, \"failed to open file\")\n\t}\n\tdefer file.Close()\n\n\treturn ioutil.ReadAll(file)\n}", - "Signature": "func readFile(path string) ([]byte, error)", - "FunctionCalls": [ - { - "ModPath": "github.com/pkg/errors@v0.9.1", - "PkgPath": "github.com/pkg/errors", - "Name": "Wrap", - "File": "cmd/main.go", - "Line": 44, - "StartOffset": 1094, - "EndOffset": 1098, - "Extra": { - "IsInvoked": true - } - } - ] - } - }, - "Types": { - "Struct": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct", - "File": "cmd/serdes.go", - "Line": 39, - "StartOffset": 938, - "EndOffset": 1043, - "Content": "type Struct struct {\n\tField1 string\n\tField2 pkg.CaseStruct\n\tField3 sonic.Config\n\tField4 func(in []byte)\n}", - "SubStruct": [ - { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct", - "File": "cmd/serdes.go", - "Line": 41, - "StartOffset": 982, - "EndOffset": 996 - }, - { - "ModPath": "github.com/bytedance/sonic@v1.11.3", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "cmd/serdes.go", - "Line": 42, - "StartOffset": 1005, - "EndOffset": 1017 - } - ], - "Methods": { - "DuplicateName": { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct.DuplicateName" - }, - "InternalMethod": { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct.InternalMethod" - } - } - } - }, - "Vars": { - "Con1": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Con1", - "File": "cmd/serdes.go", - "Line": 72, - "StartOffset": 1464, - "EndOffset": 1482, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped int" - }, - "Content": "const Con1, Con2 = 1, \"\"" - }, - "Con2": { - "IsExported": true, - "IsConst": true, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Con2", - "File": "cmd/serdes.go", - "Line": 72, - "StartOffset": 1464, - "EndOffset": 1482, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "untyped string" - }, - "Content": "const Con1, Con2 = 1, \"\"" - }, - "Var1": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Var1", - "File": "cmd/serdes.go", - "Line": 70, - "StartOffset": 1438, - "EndOffset": 1456, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var Var1, Var2 = 1, \"\"" - }, - "Var2": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Var2", - "File": "cmd/serdes.go", - "Line": 70, - "StartOffset": 1438, - "EndOffset": 1456, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "string" - }, - "Content": "var Var1, Var2 = 1, \"\"" - }, - "VarFunc": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarFunc", - "File": "cmd/serdes.go", - "Line": 64, - "StartOffset": 1359, - "EndOffset": 1376, - "Type": { - "ModPath": "", - "PkgPath": "io", - "Name": "Reader" - }, - "Content": "var VarFunc io.Reader" - }, - "VarInt": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarInt", - "File": "cmd/serdes.go", - "Line": 60, - "StartOffset": 1312, - "EndOffset": 1322, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "int" - }, - "Content": "var VarInt = 1" - }, - "VarSlice": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarSlice", - "File": "cmd/serdes.go", - "Line": 62, - "StartOffset": 1328, - "EndOffset": 1353, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "[]int" - }, - "Content": "var VarSlice = []int{1, 2, 3}" - }, - "VarString": { - "IsExported": true, - "IsConst": false, - "IsPointer": true, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarString", - "File": "cmd/serdes.go", - "Line": 58, - "StartOffset": 1289, - "EndOffset": 1306, - "Type": { - "ModPath": "", - "PkgPath": "", - "Name": "*string" - }, - "Content": "var VarString *string" - }, - "VarStruct": { - "IsExported": true, - "IsConst": false, - "IsPointer": true, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarStruct", - "File": "cmd/serdes.go", - "Line": 68, - "StartOffset": 1415, - "EndOffset": 1432, - "Type": { - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "Struct" - }, - "Content": "var VarStruct *Struct" - }, - "VarpkgStruct": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "a.b/c/cmdx", - "PkgPath": "a.b/c/cmdx", - "Name": "VarpkgStruct", - "File": "cmd/serdes.go", - "Line": 66, - "StartOffset": 1382, - "EndOffset": 1409, - "Type": { - "ModPath": "../.@", - "PkgPath": "a.b/c/pkg", - "Name": "CaseStruct" - }, - "Content": "var VarpkgStruct pkg.CaseStruct" - } - } - } - }, - "Dependencies": { - "a.b/c": "../.@", - "a.b/c/cmdx": "a.b/c/cmdx@7361f67ef606a7ab7dcf1b6d7ebcf1e0188b00f8", - "github.com/bytedance/sonic": "github.com/bytedance/sonic@v1.11.3", - "github.com/pkg/errors": "github.com/pkg/errors@v0.9.1", - "golang.org/x/arch": "golang.org/x/arch@v0.0.0-20210923205945-b76863e36670" - }, - "Files": { - "cmd/go.mod": { - "Path": "cmd/go.mod" - }, - "cmd/go.sum": { - "Path": "cmd/go.sum" - }, - "cmd/main.go": { - "Path": "cmd/main.go", - "Imports": [ - { - "Path": "\"io/ioutil\"" - }, - { - "Path": "\"os\"" - }, - { - "Path": "\"github.com/pkg/errors\"" - } - ], - "Package": "a.b/c/cmdx" - }, - "cmd/serdes.go": { - "Path": "cmd/serdes.go", - "Imports": [ - { - "Path": "\"io\"" - }, - { - "Path": "\"a.b/c/pkg\"" - }, - { - "Path": "\"a.b/c/pkg/entity\"" - }, - { - "Path": "\"github.com/bytedance/sonic\"" - } - ], - "Package": "a.b/c/cmdx" - } - } - }, - "github.com/bytedance/sonic@v1.10.2": { - "Language": "go", - "Version": "v1.10.2", - "Name": "github.com/bytedance/sonic", - "Dir": "", - "Packages": { - "github.com/bytedance/sonic": { - "IsMain": false, - "IsTest": false, - "PkgPath": "github.com/bytedance/sonic", - "Functions": { - "Config.Froze": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config.Froze", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", - "Line": 35, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func (cfg Config) Froze() API {\n api := \u0026frozenConfig{Config: cfg}\n return api\n}", - "Receiver": { - "IsPointer": false, - "Type": { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config" - } - } - }, - "Get": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Get", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", - "Line": 183, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func Get(src []byte, path ...interface{}) (ast.Node, error) {\n return GetFromString(string(src), path...)\n}" - }, - "Pretouch": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Pretouch", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", - "Line": 128, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func Pretouch(vt reflect.Type, opts ...option.CompileOption) error {\n return nil\n}" - }, - "Unmarshal": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Unmarshal", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", - "Line": 92, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error {\n return cfg.UnmarshalFromString(string(buf), val)\n}" - } - }, - "Types": { - "Config": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", - "Line": 26, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type Config struct {\n // EscapeHTML indicates encoder to escape all HTML characters \n // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n EscapeHTML bool\n\n // SortMapKeys indicates encoder that the keys of a map needs to be sorted \n // before serializing into JSON.\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n SortMapKeys bool\n\n // CompactMarshaler indicates encoder that the output JSON from json.Marshaler \n // is always compact and needs no validation \n CompactMarshaler bool\n\n // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler \n // is always escaped string and needs no quoting\n NoQuoteTextMarshaler bool\n\n // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',\n // instead of 'null'\n NoNullSliceOrMap bool\n\n // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an\n // int64 instead of as a float64.\n UseInt64 bool\n\n // UseNumber indicates decoder to unmarshal a number into an interface{} as a\n // json.Number instead of as a float64.\n UseNumber bool\n\n // UseUnicodeErrors indicates decoder to return an error when encounter invalid\n // UTF-8 escape sequences.\n UseUnicodeErrors bool\n\n // DisallowUnknownFields indicates decoder to return an error when the destination\n // is a struct and the input contains object keys which do not match any\n // non-ignored, exported fields in the destination.\n DisallowUnknownFields bool\n\n // CopyString indicates decoder to decode string values by copying instead of referring.\n CopyString bool\n\n // ValidateString indicates decoder and encoder to valid string values: decoder will return errors \n // when unescaped control chars(\\u0000-\\u001f) in the string value of JSON.\n ValidateString bool\n\n // NoValidateJSONMarshaler indicates that the encoder should not validate the output string\n // after encoding the JSONMarshaler to JSON.\n NoValidateJSONMarshaler bool\n}", - "Methods": { - "Froze": { - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config.Froze" - } - } - }, - "frozenConfig": { - "Exported": false, - "TypeKind": "", - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "frozenConfig", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/compat.go", - "Line": 39, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type frozenConfig struct{}" - } - }, - "Vars": { - "ConfigStd": { - "IsExported": true, - "IsConst": false, - "IsPointer": false, - "ModPath": "github.com/bytedance/sonic@v1.10.2", - "PkgPath": "github.com/bytedance/sonic", - "Name": "ConfigStd", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.10.2/api.go", - "Line": 83, - "StartOffset": 0, - "EndOffset": 0, - "Content": "ConfigStd = Config{\n EscapeHTML : true,\n SortMapKeys: true,\n CompactMarshaler: true,\n CopyString : true,\n ValidateString : true,\n }.Froze()" - } - } - } - } - }, - "github.com/bytedance/sonic@v1.11.3": { - "Language": "go", - "Version": "v1.11.3", - "Name": "github.com/bytedance/sonic", - "Dir": "", - "Packages": { - "github.com/bytedance/sonic": { - "IsMain": false, - "IsTest": false, - "PkgPath": "github.com/bytedance/sonic", - "Functions": { - "Unmarshal": { - "Exported": true, - "IsMethod": true, - "IsInterfaceMethod": false, - "ModPath": "github.com/bytedance/sonic@v1.11.3", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Unmarshal", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.11.3/compat.go", - "Line": 92, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func (cfg frozenConfig) Unmarshal(buf []byte, val interface{}) error {\n return cfg.UnmarshalFromString(string(buf), val)\n}" - } - }, - "Types": { - "Config": { - "Exported": true, - "TypeKind": "struct", - "ModPath": "github.com/bytedance/sonic@v1.11.3", - "PkgPath": "github.com/bytedance/sonic", - "Name": "Config", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/bytedance/sonic@v1.11.3/api.go", - "Line": 27, - "StartOffset": 0, - "EndOffset": 0, - "Content": "type Config struct {\n // EscapeHTML indicates encoder to escape all HTML characters \n // after serializing into JSON (see https://pkg.go.dev/encoding/json#HTMLEscape).\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n EscapeHTML bool\n\n // SortMapKeys indicates encoder that the keys of a map needs to be sorted \n // before serializing into JSON.\n // WARNING: This hurts performance A LOT, USE WITH CARE.\n SortMapKeys bool\n\n // CompactMarshaler indicates encoder that the output JSON from json.Marshaler \n // is always compact and needs no validation \n CompactMarshaler bool\n\n // NoQuoteTextMarshaler indicates encoder that the output text from encoding.TextMarshaler \n // is always escaped string and needs no quoting\n NoQuoteTextMarshaler bool\n\n // NoNullSliceOrMap indicates encoder that all empty Array or Object are encoded as '[]' or '{}',\n // instead of 'null'\n NoNullSliceOrMap bool\n\n // UseInt64 indicates decoder to unmarshal an integer into an interface{} as an\n // int64 instead of as a float64.\n UseInt64 bool\n\n // UseNumber indicates decoder to unmarshal a number into an interface{} as a\n // json.Number instead of as a float64.\n UseNumber bool\n\n // UseUnicodeErrors indicates decoder to return an error when encounter invalid\n // UTF-8 escape sequences.\n UseUnicodeErrors bool\n\n // DisallowUnknownFields indicates decoder to return an error when the destination\n // is a struct and the input contains object keys which do not match any\n // non-ignored, exported fields in the destination.\n DisallowUnknownFields bool\n\n // CopyString indicates decoder to decode string values by copying instead of referring.\n CopyString bool\n\n // ValidateString indicates decoder and encoder to valid string values: decoder will return errors \n // when unescaped control chars(\\u0000-\\u001f) in the string value of JSON.\n ValidateString bool\n\n // NoValidateJSONMarshaler indicates that the encoder should not validate the output string\n // after encoding the JSONMarshaler to JSON.\n NoValidateJSONMarshaler bool\n \n // NoEncoderNewline indicates that the encoder should not add a newline after every message\n NoEncoderNewline bool\n}" - } - }, - "Vars": {} - } - } - }, - "github.com/pkg/errors@v0.9.1": { - "Language": "go", - "Version": "v0.9.1", - "Name": "github.com/pkg/errors", - "Dir": "", - "Packages": { - "github.com/pkg/errors": { - "IsMain": false, - "IsTest": false, - "PkgPath": "github.com/pkg/errors", - "Functions": { - "Wrap": { - "Exported": true, - "IsMethod": false, - "IsInterfaceMethod": false, - "ModPath": "github.com/pkg/errors@v0.9.1", - "PkgPath": "github.com/pkg/errors", - "Name": "Wrap", - "File": "../../../../../../go/1.24.3/pkg/mod/github.com/pkg/errors@v0.9.1/errors.go", - "Line": 184, - "StartOffset": 0, - "EndOffset": 0, - "Content": "func Wrap(err error, message string) error {\n\tif err == nil {\n\t\treturn nil\n\t}\n\terr = \u0026withMessage{\n\t\tcause: err,\n\t\tmsg: message,\n\t}\n\treturn \u0026withStack{\n\t\terr,\n\t\tcallers(),\n\t}\n}" - } - }, - "Types": {}, - "Vars": {} - } - } - } - }, - "Graph": {} -} \ No newline at end of file From 433dc7e87a090bc1243caed02a2b30c0f7b4e14d Mon Sep 17 00:00:00 2001 From: simuleite Date: Thu, 12 Mar 2026 21:05:33 +0800 Subject: [PATCH 19/21] Update README --- README.md | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) diff --git a/README.md b/README.md index eab158ee..e09d8d1b 100644 --- a/README.md +++ b/README.md @@ -118,6 +118,45 @@ Start coding(sub-agent) ─────────→ Execute Implementation > Watch the demo video [here](https://github.com/cloudwego/abcoder/pull/141) +## Use ABCoder as a Skill + +The **Skill** interface provides native Claude Code integration without MCP protocol overhead. It uses Claude Code's built-in skill system for a more streamlined workflow. + +### Setup + +The Skill is automatically configured when you run `abcoder init-spec`. The skill definitions are located in `internal/cmd/assets/.claude/skills/`. + +### Available Tools + +| Tool | Description | +|------|-------------| +| `list_repos` | List all available repositories | +| `tree_repo` | Get repository file structure | +| `get_file_structure` | Get all symbols in a file | +| `get_file_symbol` | Get symbol details with dependencies and references | +| `search_symbol` | Search symbols by name pattern | + +### Usage Example + +```bash +# List all repositories +abcoder cli list_repos + +# Get repository file tree +abcoder cli tree_repo 'repo_name' + +# Get file structure +abcoder cli get_file_structure 'repo_name' 'path/to/file.go' + +# Get symbol details +abcoder cli get_file_symbol 'repo_name' 'path/to/file.go' 'SymbolName' + +# Search symbols +abcoder cli search_symbol 'repo_name' 'Pattern*' +``` + +For Claude Code integration, the skill tools are invoked directly via slash commands like `/abcoder:schedule`. + ## Use ABCoder as a MCP server 1. Install ABCoder: @@ -177,6 +216,44 @@ Start coding(sub-agent) ─────────→ Execute Implementation - Try to use [the recommended prompt](llm/prompt/analyzer.md) and combine planning/memory tools like [sequential-thinking](https://github.com/modelcontextprotocol/servers/tree/main/src/sequentialthinking) in your AI agent. +### Skill vs MCP + +ABCoder provides two integration methods with Claude Code: + +| Feature | MCP (mcp__abcoder) | Skill (skill__abcoder) | +|---------|-------------------|----------------------| +| **Invocation** | `mcp__abcoder__tool_name` | `skill__abcoder__tool_name` | +| **Definition** | MCP protocol | .claude/skills/ | +| **Use Case** | General AI agents | Claude Code workflow | +| **Auto Detection** | - | Auto-detect `current_repo` from cwd | +| **Memory Efficient** | - | Sonic lazy-load, on-demand parsing | +| **Pipeline Support** | - | `rg` filter, `jq` extract | +| **Symbol Search** | - | Regex pattern support | +| **Example** | `mcp__abcoder__get_file_symbol` | `skill__abcoder__get_file_symbol` | + +The **Skill** interface is the recommended approach for Claude Code users, providing a more streamlined workflow: + +- **Auto-detect current repo**: `list_repos` automatically detects repos that match current working directory +- **Memory efficient**: Uses Sonic for lazy JSON parsing, only loads needed data +- **Pipeline friendly**: Output can be piped to `rg` for filtering or `jq` for extraction +- **Regex search**: `search_symbol` supports regex patterns to precisely locate symbols + +**Pipeline Examples:** +```bash +# Filter current repo(s) only +abcoder cli list_repos | jq '.current_repo' + +# Search with regex +abcoder cli search_symbol myrepo "^Get.*User$" + +# Filter related file +abcoder cli tree_repo myrepo | rg 'related-file' + +# Filter dependencies only +abcoder cli get_file_symbol myrepo src/main.go MyFunc | jq '.node.dependencies' +``` + +For detailed usage, see [Skill Definitions](internal/cmd/assets/.claude/skills/). ## Use ABCoder as an Agent (WIP) From 717c063b65326a27f7c9d3655e40ef4f904a3cee Mon Sep 17 00:00:00 2001 From: simuleite Date: Fri, 13 Mar 2026 10:20:18 +0800 Subject: [PATCH 20/21] Fix License --- internal/cmd/cli/cli.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/cmd/cli/cli.go b/internal/cmd/cli/cli.go index 15b0287e..8aa8908e 100644 --- a/internal/cmd/cli/cli.go +++ b/internal/cmd/cli/cli.go @@ -8,8 +8,8 @@ // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,. -// See the License either express or implied for the specific language governing permissions and +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and // limitations under the License. package cli From 615fbda2afb5fa45bb004e3767e78bd113f3ef5d Mon Sep 17 00:00:00 2001 From: simuleite Date: Fri, 13 Mar 2026 10:29:42 +0800 Subject: [PATCH 21/21] Solve CI Problems --- .github/workflows/regression.yml | 24 ++++++++++++------------ lang/golang/parser/pkg.go | 3 --- 2 files changed, 12 insertions(+), 15 deletions(-) diff --git a/.github/workflows/regression.yml b/.github/workflows/regression.yml index 36edd03e..7030d53d 100644 --- a/.github/workflows/regression.yml +++ b/.github/workflows/regression.yml @@ -22,22 +22,24 @@ jobs: ['ASTVersion'] ['Modules']['a.b/c']['Dependencies']['a.b/c'] ['Modules']['a.b/c/cmdx']['Dependencies']['a.b/c/cmdx'] + ['NameToFile'] + ['NameToLocations'] steps: - name: Checkout pull request code uses: actions/checkout@v4 with: - path: 'pr_repo' + path: "pr_repo" - name: Checkout main branch code uses: actions/checkout@v4 with: - ref: 'main' - path: 'main_repo' + ref: "main" + path: "main_repo" - name: Setup Go environment uses: actions/setup-go@v5 with: - go-version: '1.22' + go-version: "1.22" cache-dependency-path: | main_repo/go.sum pr_repo/go.sum @@ -51,18 +53,18 @@ jobs: - name: Setup Python environment uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: "3.11" - name: Setup JDK 21 uses: actions/setup-java@v4 with: - java-version: '21' - distribution: 'temurin' + java-version: "21" + distribution: "temurin" - name: Setup Node.js uses: actions/setup-node@v4 with: - node-version: '22' + node-version: "22" - name: Compile both binaries run: | @@ -82,8 +84,7 @@ jobs: echo "JDTLS_ROOT_PATH=$(realpath ./main_repo/lang/java/lsp/jdtls/jdt-language-server-*)" >> $GITHUB_ENV - name: Run OLD abcoder - run: - OUTDIR=out_old ABCEXE=./abcoder_old ./main_repo/script/run_testdata.sh all + run: OUTDIR=out_old ABCEXE=./abcoder_old ./main_repo/script/run_testdata.sh all - name: Reset dependencies run: | @@ -95,8 +96,7 @@ jobs: OUTDIR=out_new ABCEXE=./abcoder_new ./pr_repo/script/run_testdata.sh first - name: Run NEW abcoder - run: - OUTDIR=out_new ABCEXE=./abcoder_new ./pr_repo/script/run_testdata.sh all + run: OUTDIR=out_new ABCEXE=./abcoder_new ./pr_repo/script/run_testdata.sh all - name: Upload output directories uses: actions/upload-artifact@v4 diff --git a/lang/golang/parser/pkg.go b/lang/golang/parser/pkg.go index 32eaee09..a577f060 100644 --- a/lang/golang/parser/pkg.go +++ b/lang/golang/parser/pkg.go @@ -276,9 +276,6 @@ func (p *GoParser) loadPackages(mod *Module, dir string, pkgPath PkgPath) (err e if f.Package == "" { f.Package = pkg.ID f.Imports = imports.Origins - // [新增] 填充 ModPath 和 PkgPath - f.ModPath = mod.Name - f.PkgPath = pkg.ID } if err := p.parseFile(ctx, file); err != nil { return err