Skip to content

Commit 872313a

Browse files
committed
refactor: move out main
1 parent ea8b3c2 commit 872313a

7 files changed

Lines changed: 269 additions & 231 deletions

File tree

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,3 +74,4 @@ src/lang/testdata
7474
*.json
7575

7676
tools
77+
abcoder

go.go

Lines changed: 0 additions & 45 deletions
This file was deleted.

lang/collect/collect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ import (
2929
)
3030

3131
type CollectOption struct {
32+
Language lsp.Language
3233
LoadExternalSymbol bool
3334
NeedStdSymbol bool
3435
NoNeedComment bool
3536
NeedTest bool
36-
Language lsp.Language
3737
Excludes []string
3838
}
3939

lang/lsp/client.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ func NewLSPClient(repo string, openfile string, wait time.Duration, opts ClientO
5050
return nil, err
5151
}
5252

53-
cli, err := initLSPClient(context.Background(), svr, lsp.DocumentURI(NewURI(repo)), opts.Verbose)
53+
cli, err := initLSPClient(context.Background(), svr, NewURI(repo), opts.Verbose)
5454
if err != nil {
5555
return nil, err
5656
}
@@ -110,7 +110,7 @@ type initializeResult struct {
110110
Capabilities interface{} `json:"capabilities,omitempty"`
111111
}
112112

113-
func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir lsp.DocumentURI, verbose bool) (*LSPClient, error) {
113+
func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir DocumentURI, verbose bool) (*LSPClient, error) {
114114
h := newLSPHandler()
115115
stream := jsonrpc2.NewBufferedStream(svr, jsonrpc2.VSCodeObjectCodec{})
116116
conn := jsonrpc2.NewConn(ctx, stream, h)
@@ -131,7 +131,7 @@ func initLSPClient(ctx context.Context, svr io.ReadWriteCloser, dir lsp.Document
131131

132132
initParams := initializeParams{
133133
ProcessID: os.Getpid(),
134-
RootURI: dir,
134+
RootURI: lsp.DocumentURI(dir),
135135
Capabilities: cs,
136136
Trace: lsp.Trace(trace),
137137
ClientInfo: lsp.ClientInfo{Name: "vscode"},

lang/lsp/spec.go

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,15 +14,31 @@
1414

1515
package lsp
1616

17-
import "github.com/cloudwego/abcoder/lang/uniast"
17+
import (
18+
"strings"
19+
20+
"github.com/cloudwego/abcoder/lang/uniast"
21+
)
1822

1923
type Language string
2024

2125
const (
22-
Rust Language = "rust"
23-
Golang Language = "golang"
26+
Rust Language = "rust"
27+
Golang Language = "golang"
28+
Unknown Language = ""
2429
)
2530

31+
func NewLanguage(l string) Language {
32+
switch strings.ToLower(l) {
33+
case "rust":
34+
return Rust
35+
case "go", "golang":
36+
return Golang
37+
default:
38+
return Unknown
39+
}
40+
}
41+
2642
func (l Language) String() string {
2743
switch l {
2844
case Rust:

lang/parse.go

Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
/**
2+
* Copyright 2025 ByteDance Inc.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package lang
18+
19+
import (
20+
"context"
21+
"encoding/json"
22+
"fmt"
23+
"os"
24+
"os/exec"
25+
"path/filepath"
26+
"time"
27+
28+
"github.com/cloudwego/abcoder/lang/collect"
29+
"github.com/cloudwego/abcoder/lang/golang/parser"
30+
"github.com/cloudwego/abcoder/lang/log"
31+
"github.com/cloudwego/abcoder/lang/lsp"
32+
"github.com/cloudwego/abcoder/lang/rust"
33+
"github.com/cloudwego/abcoder/lang/uniast"
34+
)
35+
36+
type ParseOptions struct {
37+
LSP string
38+
Verbose bool
39+
collect.CollectOption
40+
}
41+
42+
func Parse(ctx context.Context, uri string, args ParseOptions) ([]byte, error) {
43+
if !filepath.IsAbs(uri) {
44+
uri, _ = filepath.Abs(uri)
45+
}
46+
l, lspPath := checkLSP(args.Language, args.LSP)
47+
openfile, opentime, err := checkRepoPath(uri, l)
48+
if err != nil {
49+
return nil, err
50+
}
51+
52+
var client *lsp.LSPClient
53+
if lspPath != "" {
54+
// Initialize the LSP client
55+
log.Info("start initialize LSP server %s...\n", lspPath)
56+
var err error
57+
client, err = lsp.NewLSPClient(uri, openfile, opentime, lsp.ClientOptions{
58+
Server: lspPath,
59+
Language: l,
60+
Verbose: args.Verbose,
61+
})
62+
if err != nil {
63+
log.Error("failed to initialize LSP server: %v\n", err)
64+
return nil, err
65+
}
66+
log.Info("end initialize LSP server")
67+
}
68+
69+
repo, err := collectSymbol(ctx, client, uri, args.CollectOption)
70+
if err != nil {
71+
log.Error("Failed to collect symbols: %v\n", err)
72+
return nil, err
73+
}
74+
log.Info("all symbols collected, start writing to stdout...\n")
75+
out, err := json.Marshal(repo)
76+
if err != nil {
77+
log.Error("Failed to marshal repository: %v\n", err)
78+
return nil, err
79+
}
80+
return out, nil
81+
}
82+
83+
func checkRepoPath(repoPath string, language lsp.Language) (openfile string, wait time.Duration, err error) {
84+
if _, err := os.Stat(repoPath); os.IsNotExist(err) {
85+
return "", 0, fmt.Errorf("repository not found: %s", repoPath)
86+
}
87+
switch language {
88+
case lsp.Rust:
89+
// NOTICE: open the Cargo.toml file is required for Rust projects
90+
openfile, wait = rust.CheckRepo(repoPath)
91+
default:
92+
openfile = ""
93+
wait = 0
94+
}
95+
96+
log.Info("open file '%s' and wait for %d seconds for initialize workspace\n", openfile, wait/time.Second)
97+
return
98+
}
99+
100+
func checkVerbose(verbose bool, debug bool) {
101+
if debug {
102+
103+
} else if verbose {
104+
log.SetLogLevel(log.InfoLevel)
105+
} else {
106+
log.SetLogLevel(log.ErrorLevel)
107+
}
108+
}
109+
110+
func checkLSP(language lsp.Language, lspPath string) (l lsp.Language, s string) {
111+
switch language {
112+
case lsp.Rust:
113+
l, s = rust.GetDefaultLSP()
114+
case lsp.Golang:
115+
l = lsp.Golang
116+
s = ""
117+
if _, err := exec.LookPath("go"); err != nil {
118+
if _, err := os.Stat(lspPath); os.IsNotExist(err) {
119+
log.Error("Go compiler not found, please make it excutable!\n", lspPath)
120+
os.Exit(1)
121+
}
122+
}
123+
return
124+
default:
125+
log.Error("Unsupported language: %s\n", language)
126+
os.Exit(1)
127+
}
128+
// check if lsp excutable
129+
if lspPath != "" {
130+
if _, err := exec.LookPath(lspPath); err != nil {
131+
if _, err := os.Stat(lspPath); os.IsNotExist(err) {
132+
log.Error("Language server %s not found, please make it excutable!\n", lspPath)
133+
os.Exit(1)
134+
}
135+
}
136+
s = lspPath
137+
}
138+
139+
return
140+
}
141+
142+
func collectSymbol(ctx context.Context, cli *lsp.LSPClient, repoPath string, opts collect.CollectOption) (repo *uniast.Repository, err error) {
143+
if opts.Language == lsp.Golang {
144+
repo, err = callGoParser(ctx, repoPath, opts)
145+
if err != nil {
146+
return nil, err
147+
}
148+
} else {
149+
collector := collect.NewCollector(repoPath, cli)
150+
collector.CollectOption = opts
151+
log.Info("start collecting symbols...\n")
152+
err = collector.Collect(ctx)
153+
if err != nil {
154+
return nil, err
155+
}
156+
log.Info("all symbols collected.\n")
157+
log.Info("start exporting symbols...\n")
158+
repo, err = collector.Export(ctx)
159+
if err != nil {
160+
return nil, err
161+
}
162+
}
163+
164+
if err := repo.BuildGraph(); err != nil {
165+
return nil, err
166+
}
167+
return repo, nil
168+
}
169+
170+
func callGoParser(ctx context.Context, repoPath string, opts collect.CollectOption) (*uniast.Repository, error) {
171+
goopts := parser.Options{}
172+
if opts.LoadExternalSymbol {
173+
goopts.ReferCodeDepth = 1
174+
}
175+
if !opts.NoNeedComment {
176+
goopts.CollectComment = true
177+
}
178+
if opts.NeedTest {
179+
goopts.NeedTest = true
180+
}
181+
goopts.Excludes = opts.Excludes
182+
p := parser.NewParser(repoPath, repoPath, goopts)
183+
repo, err := p.ParseRepo()
184+
if err != nil {
185+
return nil, err
186+
}
187+
return &repo, nil
188+
}

0 commit comments

Comments
 (0)