Skip to content

Commit 19e8b53

Browse files
committed
fix: cgo file length calculate wrong
1 parent 964a648 commit 19e8b53

File tree

3 files changed

+83
-21
lines changed

3 files changed

+83
-21
lines changed

lang/golang/parser/ctx.go

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,21 @@ func (p *GoParser) referCodes(ctx *fileContext, id *Identity, depth int) (err er
8686
if pkg == nil {
8787
return fmt.Errorf("cannot find package %s", id.PkgPath)
8888
}
89-
for _, fpath := range pkg.GoFiles {
89+
90+
var files []string
91+
if p.cgoPkgs != nil {
92+
for _, v := range p.cgoPkgs {
93+
if v {
94+
files = pkg.CompiledGoFiles
95+
break
96+
}
97+
}
98+
}
99+
if len(files) == 0 {
100+
files = pkg.GoFiles
101+
}
102+
103+
for _, fpath := range files {
90104
bs := p.getFileBytes(fpath)
91105
file, err := parser.ParseFile(pkg.Fset, fpath, bs, parser.ParseComments)
92106
if err != nil {

lang/golang/parser/parser.go

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ type GoParser struct {
4747
types map[types.Type]Identity
4848
files map[string][]byte
4949
exclues []*regexp.Regexp
50+
cgoPkgs map[string]bool // CGO packages
5051
}
5152

5253
type moduleInfo struct {
@@ -98,6 +99,7 @@ func newGoParser(name string, homePageDir string, opts Options) *GoParser {
9899
func (p *GoParser) collectGoMods(startDir string) error {
99100
hasGoWork := false
100101
deps := map[string]string{}
102+
var cgoPkgs map[string]bool
101103
err := filepath.Walk(startDir, func(path string, info fs.FileInfo, err error) error {
102104
if err != nil || !strings.HasSuffix(path, "go.mod") {
103105
return nil
@@ -115,10 +117,18 @@ func (p *GoParser) collectGoMods(startDir string) error {
115117
p.repo.Modules[name] = newModule(name, rel)
116118
p.modules = append(p.modules, newModuleInfo(name, rel, name))
117119

118-
deps, hasGoWork, err = getDeps(filepath.Dir(path), hasGoWork)
120+
deps, hasGoWork, cgoPkgs, err = getDeps(filepath.Dir(path), hasGoWork)
119121
if err != nil {
120122
return err
121123
}
124+
if p.cgoPkgs == nil {
125+
p.cgoPkgs = make(map[string]bool)
126+
}
127+
for pkgPath := range cgoPkgs {
128+
if strings.HasPrefix(pkgPath, name) {
129+
p.cgoPkgs[pkgPath] = true
130+
}
131+
}
122132
for k, v := range deps {
123133
p.repo.Modules[name].Dependencies[k] = v
124134
p.modules = append(p.modules, newModuleInfo(k, "", v))
@@ -148,18 +158,20 @@ type dep struct {
148158
Dir string `json:"Dir"`
149159
GoMod string `json:"GoMod"`
150160
} `json:"Module"`
161+
CgoFiles []string `json:"CgoFiles"`
151162
}
152163

153-
func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err error) {
164+
func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, cgoPkgs map[string]bool, err error) {
165+
cgoPkgs = make(map[string]bool)
154166
// run go mod tidy first to ensure all dependencies are resolved
155167
cmd := exec.Command("go", "mod", "tidy", "-e")
156168
cmd.Dir = dir
157169
output, err := cmd.CombinedOutput()
158170
if err != nil {
159-
return nil, hasGoWork, fmt.Errorf("failed to execute 'go mod tidy', err: %v, output: %s", err, string(output))
171+
return nil, hasGoWork, cgoPkgs, fmt.Errorf("failed to execute 'go mod tidy', err: %v, output: %s", err, string(output))
160172
}
161173
if hasNoDeps(filepath.Join(dir, "go.mod")) {
162-
return map[string]string{}, hasGoWork, nil
174+
return map[string]string{}, hasGoWork, cgoPkgs, nil
163175
}
164176
// -mod=mod to use go mod when go mod is inconsistent with go vendor
165177
// if go.work exist, it's no need to set -mod=mod
@@ -172,12 +184,12 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
172184
cmd.Dir = dir
173185
output, err = cmd.CombinedOutput()
174186
if err != nil {
175-
return nil, hasGoWork, fmt.Errorf("failed to execute 'go list -json all', err: %v, output: %s, cmd string: %s, dir: %s", err, string(output), cmd.String(), dir)
187+
return nil, hasGoWork, 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)
176188
}
177189
// ignore content until first open
178190
index := strings.Index(string(output), "{")
179191
if index == -1 {
180-
return nil, hasGoWork, fmt.Errorf("failed to find '{' in output, output: %s", string(output))
192+
return nil, hasGoWork, cgoPkgs, fmt.Errorf("failed to find '{' in output, output: %s", string(output))
181193
}
182194
if index > 0 {
183195
log.Info("go list skip prefix, output: %s", string(output[:index]))
@@ -191,13 +203,16 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
191203
if err.Error() == "EOF" {
192204
break
193205
}
194-
return nil, hasGoWork, fmt.Errorf("failed to decode json: %v, output: %s", err, string(output))
206+
return nil, hasGoWork, cgoPkgs, fmt.Errorf("failed to decode json: %v, output: %s", err, string(output))
195207
}
196208
module := mod.Module
197209
// golang internal package, ignore it.
198210
if module.Path == "" {
199211
continue
200212
}
213+
if len(mod.CgoFiles) > 0 {
214+
cgoPkgs[module.Path] = true
215+
}
201216
if module.Replace != nil {
202217
deps[module.Path] = module.Replace.Path + "@" + module.Replace.Version
203218
} else {
@@ -214,8 +229,7 @@ func getDeps(dir string, goWork bool) (a map[string]string, hasGoWork bool, err
214229
}
215230
}
216231
}
217-
218-
return deps, hasGoWork, nil
232+
return deps, hasGoWork, cgoPkgs, nil
219233
}
220234

221235
// ParseRepo parse the entiry repo from homePageDir recursively until end

lang/golang/parser/pkg.go

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -172,24 +172,49 @@ func (p *GoParser) loadPackages(mod *Module, dir string, pkgPath PkgPath) (err e
172172
fmt.Fprintf(os.Stderr, "[loadPackages] mod: %s, dir: %s, pkgPath: %s\n", mod.Name, dir, pkgPath)
173173
fset := token.NewFileSet()
174174
loadCount++
175-
// slow-path: load packages in the dir, including sub pakcages
176-
opts := packages.NeedFiles | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports
175+
176+
baseOpts := packages.NeedFiles | packages.NeedSyntax | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedImports
177+
if p.opts.ReferCodeDepth != 0 {
178+
baseOpts |= packages.NeedDeps
179+
}
180+
if p.opts.NeedTest {
181+
baseOpts |= packages.NeedForTest
182+
}
183+
177184
cfg := &packages.Config{
178-
Mode: opts,
185+
Mode: baseOpts,
179186
Fset: fset,
180187
Dir: dir,
181188
}
182-
if p.opts.ReferCodeDepth != 0 {
183-
opts |= packages.NeedDeps
184-
}
189+
185190
if p.opts.NeedTest {
186-
opts |= packages.NeedForTest
187191
cfg.Tests = true
188192
}
193+
189194
pkgs, err := packages.Load(cfg, pkgPath)
190195
if err != nil {
191196
return fmt.Errorf("load path '%s' failed: %v", dir, err)
192197
}
198+
199+
hasCGO := false
200+
if p.cgoPkgs != nil {
201+
for _, v := range p.cgoPkgs {
202+
if v {
203+
hasCGO = true
204+
break
205+
}
206+
}
207+
}
208+
fmt.Fprintf(os.Stderr, "[loadPackages] mod: %s, dir: %s, pkgPath: %s, hasCGO: %v\n", mod.Name, dir, pkgPath, hasCGO)
209+
if hasCGO {
210+
baseOpts |= packages.NeedCompiledGoFiles
211+
cfg.Mode = baseOpts
212+
pkgs, err = packages.Load(cfg, pkgPath)
213+
if err != nil {
214+
return fmt.Errorf("load path '%s' with CGO failed: %v", dir, err)
215+
}
216+
}
217+
193218
for _, pkg := range pkgs {
194219
if mm := p.repo.Modules[mod.Name]; mm != nil && (*mm).Packages[pkg.ID] != nil {
195220
continue
@@ -198,11 +223,20 @@ func (p *GoParser) loadPackages(mod *Module, dir string, pkgPath PkgPath) (err e
198223
continue
199224
}
200225
for idx, file := range pkg.Syntax {
201-
if idx >= len(pkg.GoFiles) {
202-
fmt.Fprintf(os.Stderr, "skip file %s by loader\n", file.Name)
203-
continue
226+
var filePath string
227+
if hasCGO {
228+
if idx >= len(pkg.CompiledGoFiles) {
229+
fmt.Fprintf(os.Stderr, "skip file %s by loader\n", file.Name)
230+
continue
231+
}
232+
filePath = pkg.CompiledGoFiles[idx]
233+
} else {
234+
if idx >= len(pkg.GoFiles) {
235+
fmt.Fprintf(os.Stderr, "skip file %s by loader\n", file.Name)
236+
continue
237+
}
238+
filePath = pkg.GoFiles[idx]
204239
}
205-
filePath := pkg.GoFiles[idx]
206240
var skip bool
207241
for _, exclude := range p.exclues {
208242
if exclude.MatchString(filePath) {

0 commit comments

Comments
 (0)