feat: 添加tree-sitter调用逻辑

This commit is contained in:
曹宇航
2025-07-24 16:14:07 +08:00
parent b5ecb92371
commit e2ac6cb3b6
5 changed files with 89 additions and 0 deletions

12
backend/domain/ast.go Normal file
View File

@@ -0,0 +1,12 @@
package domain
type ParseResult struct {
FilePath string `json:"file_path"`
Definition string `json:"definition"`
Error string `json:"error,omitempty"`
Success bool `json:"success"`
}
type SaveAstReq struct {
UserID string `json:"user_id" validate:"required"`
ProjectID string `json:"project_id" validate:"required"`
Files []string `json:"files" validate:"required"`
}

View File

@@ -14,6 +14,7 @@ type WorkspaceFileUsecase interface {
Create(ctx context.Context, req *CreateWorkspaceFileReq) (*WorkspaceFile, error)
Update(ctx context.Context, req *UpdateWorkspaceFileReq) (*WorkspaceFile, error)
Delete(ctx context.Context, id string) error
GetAndSave(ctx context.Context, req *SaveAstReq) error
GetByID(ctx context.Context, id string) (*WorkspaceFile, error)
GetByPath(ctx context.Context, userID, workspaceID, path string) (*WorkspaceFile, error)
List(ctx context.Context, req *ListWorkspaceFileReq) (*ListWorkspaceFileResp, error)
@@ -22,6 +23,7 @@ type WorkspaceFileUsecase interface {
Sync(ctx context.Context, req *SyncWorkspaceFileReq) (*SyncWorkspaceFileResp, error)
}
// WorkspaceFileRepo 定义 WorkspaceFile 数据访问接口
type WorkspaceFileRepo interface {
Create(ctx context.Context, req *CreateWorkspaceFileReq) (*db.WorkspaceFile, error)

View File

@@ -92,6 +92,21 @@ func (h *WorkspaceFileHandler) GetByID(c *web.Context, req struct {
return c.Success(file)
}
// GetAndSave
// @Tags WorkspaceFile
// @Summary 获取并保存工作区文件
// @param ctx
// @param req
// @return error
func (h *WorkspaceFileHandler) GetAndSave(ctx *web.Context, req *domain.SaveAstReq) error {
err := h.usecase.GetAndSave(ctx.Request().Context(), req)
if err != nil {
h.logger.Error("failed to get and save workspace files", "error", err, "count", len(req.Files))
return err
}
return ctx.Success(nil)
}
// Update 更新工作区文件
//
// @Tags WorkspaceFile

View File

@@ -4,6 +4,7 @@ import (
"context"
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"log/slog"
"strings"
@@ -11,6 +12,7 @@ import (
"github.com/chaitin/MonkeyCode/backend/config"
"github.com/chaitin/MonkeyCode/backend/db"
"github.com/chaitin/MonkeyCode/backend/domain"
"github.com/chaitin/MonkeyCode/backend/pkg/cli"
"github.com/chaitin/MonkeyCode/backend/pkg/cvt"
)
@@ -121,6 +123,31 @@ func (u *WorkspaceFileUsecase) GetByID(ctx context.Context, id string) (*domain.
return cvt.From(file, &domain.WorkspaceFile{}), nil
}
func (u *WorkspaceFileUsecase) GetAndSave(ctx context.Context, req *domain.SaveAstReq) (error) {
results, err := cli.RunParseCLI("parse", "", req.Files...)
if err != nil {
return err
}
for _, res := range results {
file, err := u.repo.GetByPath(ctx, req.UserID, req.ProjectID, res.FilePath)
if err != nil {
return err
}
astData, err := json.Marshal(res.Definition)
if err != nil {
return err
}
_, err = u.repo.Update(ctx, file.ID.String(), func(up *db.WorkspaceFileUpdateOne) error {
return up.SetContent(string(astData)).Exec(ctx)
})
if err != nil {
return err
}
}
return nil
}
func (u *WorkspaceFileUsecase) GetByPath(ctx context.Context, userID, workspaceID, path string) (*domain.WorkspaceFile, error) {
file, err := u.repo.GetByPath(ctx, userID, workspaceID, path)
if err != nil {

33
backend/pkg/cli/cli.go Normal file
View File

@@ -0,0 +1,33 @@
package cli
import (
"encoding/json"
"fmt"
"os"
"os/exec"
"strings"
"github.com/chaitin/MonkeyCode/backend/domain"
)
// RunParseCLI
// @Description ctcode-cli 支持通过 CLI 的方式获取文件的 AST 信息
// @param command ["parse"] - 解析文件为 AST 树
// @param flag ["-s", "--successOnly"] - 是否只返回成功的结果
// @param paths 要解析的文件路径
// @return []ParseResult 解析结果数组
// @return error 错误信息
func RunParseCLI(command string, flag string, paths ...string) ([]domain.ParseResult, error) {
cmd := exec.Command("ctcode-cli", command, flag, strings.Join(paths, " "))
cmd.Env = os.Environ()
output, err := cmd.CombinedOutput()
fmt.Printf(`err: %s, output: %s\n`, fmt.Sprint(err), string(output))
if err != nil {
return []domain.ParseResult{}, err
}
var results []domain.ParseResult
if err := json.Unmarshal(output, &results); err != nil {
panic(err)
}
return results, nil
}