Skip to content

Commit 219a729

Browse files
authored
Merge pull request #25 from cloudwego/fix/remove_flags
fix:(go) fix bugs
2 parents aaa32a8 + 56d8293 commit 219a729

File tree

5 files changed

+221
-111
lines changed

5 files changed

+221
-111
lines changed

lang/golang/parser/ctx.go

Lines changed: 121 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -247,27 +247,73 @@ func GetRawContent(fset *token.FileSet, file []byte, node ast.Node, collectComme
247247
// return ctx.bs[ctx.fset.Position(from).Offset:ctx.fset.Position(to).Offset]
248248
// }
249249

250+
type typeInfo struct {
251+
Id Identity
252+
IsPointer bool
253+
IsStdOrBuiltin bool
254+
Deps []Identity
255+
}
256+
250257
// FIXME: for complex type like map[XX]YY , we only extract first-meet type here
251-
func (ctx *fileContext) GetTypeId(typ ast.Expr) (x Identity, isPointer bool, isStdOrBuiltin bool) {
258+
func (ctx *fileContext) GetTypeInfo(typ ast.Expr) typeInfo {
252259
if tinfo, ok := ctx.pkgTypeInfo.Types[typ]; ok {
253-
return ctx.getIdFromType(tinfo.Type)
260+
return ctx.getTypeinfo(tinfo.Type)
254261
} else {
255-
panic("cannot find type info for " + string(ctx.GetRawContent(typ)))
262+
// NOTICE: for unloaded type, we only mock the type name
263+
fmt.Fprintf(os.Stderr, "cannot find type info for %s\n", ctx.GetRawContent(typ))
264+
return ctx.mockType(typ)
256265
}
257266
}
258267

268+
func (ctx *fileContext) mockType(typ ast.Expr) typeInfo {
269+
switch ty := typ.(type) {
270+
case *ast.StarExpr:
271+
ti := ctx.mockType(ty.X)
272+
ti.IsPointer = true
273+
return ti
274+
case *ast.CallExpr:
275+
// try get func type
276+
ti := ctx.mockType(ty.Fun)
277+
ti.IsPointer = false
278+
return ti
279+
case *ast.SelectorExpr:
280+
// try get import path
281+
switch xx := ty.X.(type) {
282+
case *ast.Ident:
283+
impt, mod, err := ctx.imports.GetImportPath(xx.Name, "")
284+
if err != nil {
285+
goto fallback
286+
}
287+
return typeInfo{NewIdentity(mod, PkgPath(impt), ty.Sel.Name), false, false, nil}
288+
case *ast.SelectorExpr:
289+
// recurse
290+
ti := ctx.mockType(xx)
291+
ti.Id.Name = ty.Sel.Name
292+
ti.IsPointer = false
293+
return ti
294+
}
295+
}
296+
297+
fallback:
298+
return typeInfo{NewIdentity("UNLOADED", ctx.pkgPath, string(ctx.GetRawContent(typ))), false, true, nil}
299+
}
300+
259301
func (ctx *fileContext) collectFields(fields []*ast.Field, m *[]Dependency) {
260302
for _, fieldDecl := range fields {
261-
id, _, isStdOrBuiltin := ctx.GetTypeId(fieldDecl.Type)
262-
if isStdOrBuiltin || id.PkgPath == "" {
263-
continue
303+
ti := ctx.GetTypeInfo(fieldDecl.Type)
304+
if !ti.IsStdOrBuiltin && ti.Id.ModPath != "" {
305+
*m = InsertDependency(*m, Dependency{
306+
Identity: ti.Id,
307+
FileLine: ctx.FileLine(fieldDecl),
308+
})
309+
}
310+
for _, dep := range ti.Deps {
311+
*m = InsertDependency(*m, Dependency{
312+
Identity: dep,
313+
FileLine: ctx.FileLine(fieldDecl),
314+
})
264315
}
265-
*m = append(*m, Dependency{
266-
Identity: id,
267-
FileLine: ctx.FileLine(fieldDecl),
268-
})
269316
}
270-
return
271317
}
272318

273319
type importInfo struct {
@@ -379,74 +425,81 @@ func getTypeName(fset *token.FileSet, file []byte, typ ast.Expr) (ret []Identity
379425
}
380426

381427
func (p *GoParser) collectTypes(ctx *fileContext, typ ast.Expr, st *Type, inlined bool) {
382-
id, _, isGoBuiltins := ctx.GetTypeId(typ)
383-
dep := NewDependency(id, ctx.FileLine(typ))
384-
if isGoBuiltins || id.PkgPath == "" {
385-
return
386-
}
387-
if err := p.referCodes(ctx, &id, p.opts.ReferCodeDepth); err != nil {
388-
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", id.Name, err)
428+
ti := ctx.GetTypeInfo(typ)
429+
if !ti.IsStdOrBuiltin && ti.Id.ModPath != "" {
430+
dep := NewDependency(ti.Id, ctx.FileLine(typ))
431+
if err := p.referCodes(ctx, &ti.Id, p.opts.ReferCodeDepth); err != nil {
432+
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", ti.Id, err)
433+
}
434+
if inlined {
435+
st.InlineStruct = InsertDependency(st.InlineStruct, dep)
436+
} else {
437+
st.SubStruct = InsertDependency(st.SubStruct, dep)
438+
}
389439
}
390-
if inlined {
391-
st.InlineStruct = append(st.InlineStruct, dep)
392-
} else {
393-
st.SubStruct = append(st.SubStruct, dep)
440+
for _, dep := range ti.Deps {
441+
if err := p.referCodes(ctx, &dep, p.opts.ReferCodeDepth); err != nil {
442+
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", dep, err)
443+
}
444+
if inlined {
445+
st.InlineStruct = InsertDependency(st.InlineStruct, NewDependency(dep, ctx.FileLine(typ)))
446+
} else {
447+
st.SubStruct = InsertDependency(st.SubStruct, NewDependency(dep, ctx.FileLine(typ)))
448+
}
394449
}
395450
}
396451

397-
var compositeTypePrefixs = []string{"[]", "map[", "chan ", "<-chan", "chan<-", "func("}
398-
399452
// get type id and tells if it is std or builtin
400-
func (ctx *fileContext) getIdFromType(typ types.Type) (x Identity, isPointer bool, isStrOrBuiltin bool) {
401-
if tobj, isPointer := getNamedType(typ); tobj != nil {
402-
if isGoBuiltins(tobj.Name()) {
403-
return Identity{Name: tobj.Name()}, isPointer, true
404-
}
405-
name := tobj.Name()
406-
// NOTICE: filter composite type (map[] slice func chan ...)
407-
// TODO: support extract sub named type
408-
for _, prefix := range compositeTypePrefixs {
409-
if strings.HasPrefix(name, prefix) {
410-
return Identity{Name: name}, isPointer, true
453+
func (ctx *fileContext) getTypeinfo(typ types.Type) (ti typeInfo) {
454+
tobjs, isPointer := getNamedTypes(typ)
455+
ti.IsPointer = isPointer
456+
if len(tobjs) > 0 {
457+
tobj := tobjs[0]
458+
if tp := tobj.Pkg(); tp != nil {
459+
mod, err := ctx.GetMod(tp.Path())
460+
if err == errSysImport {
461+
ti.Id = Identity{"", tp.Path(), tobj.Name()}
462+
ti.IsStdOrBuiltin = true
463+
} else if err != nil || mod == "" {
464+
// unloaded type, mark it
465+
ti.Id = Identity{"", tp.Path(), tobj.Name()}
466+
ti.IsStdOrBuiltin = false
467+
} else {
468+
ti.Id = NewIdentity(mod, tp.Path(), tobj.Name())
469+
ti.IsStdOrBuiltin = false
411470
}
412-
}
413-
// get mod and pkg from tobj.Pkg()
414-
tp := tobj.Pkg()
415-
if tp == nil {
416-
return NewIdentity(ctx.module.Name, ctx.pkgPath, name), isPointer, false
417-
}
418-
mod, err := ctx.GetMod(tp.Path())
419-
if err == errSysImport {
420-
return Identity{Name: name, PkgPath: tp.Path()}, isPointer, true
421-
} else if err != nil {
422-
return Identity{Name: name}, isPointer, false
423-
}
424-
return NewIdentity(mod, tp.Path(), tobj.Name()), isPointer, false
425-
} else {
426-
typStr := typ.String()
427-
isPointer := strings.HasPrefix(typStr, "*")
428-
typStr = strings.TrimPrefix(typStr, "*")
429-
if isGoBuiltins(typStr) {
430-
return Identity{Name: typStr}, isPointer, true
431-
}
432-
for _, prefix := range compositeTypePrefixs {
433-
if strings.HasPrefix(typStr, prefix) {
434-
return Identity{Name: typStr}, isPointer, true
471+
} else {
472+
if isGoBuiltins(tobj.Name()) {
473+
ti.Id = Identity{Name: tobj.Name()}
474+
ti.IsStdOrBuiltin = true
475+
} else {
476+
// unloaded type, mark it
477+
ti.Id = Identity{"", ctx.pkgPath, tobj.Name()}
478+
ti.IsStdOrBuiltin = false
435479
}
436480
}
437-
if idx := strings.LastIndex(typStr, "."); idx > 0 {
438-
pkg := typStr[:idx]
439-
if isSysPkg(pkg) {
440-
return Identity{Name: typStr[idx+1:], PkgPath: pkg}, isPointer, true
481+
// NOTICE: only extract Named type here
482+
for i := 1; i < len(tobjs); i++ {
483+
tobj := tobjs[i]
484+
if isGoBuiltins(tobj.Name()) {
485+
continue
441486
}
442-
// FIXME: some types (ex: return type of a func-calling) cannot be found go mod here.
443-
// Ignore empty mod for now.
444-
mod, _ := ctx.GetMod(pkg)
445-
return NewIdentity(mod, pkg, typStr[idx+1:]), isPointer, false
446-
} else {
447-
return NewIdentity(ctx.module.Name, ctx.pkgPath, typStr), isPointer, false
487+
// get mod and pkg from tobj.Pkg()
488+
tp := tobj.Pkg()
489+
if tp == nil {
490+
continue
491+
}
492+
mod, err := ctx.GetMod(tp.Path())
493+
if err != nil || mod == "" {
494+
continue
495+
}
496+
ti.Deps = append(ti.Deps, NewIdentity(mod, tp.Path(), tobj.Name()))
448497
}
498+
} else {
499+
ti.Id = Identity{"", "", typ.String()}
500+
ti.IsStdOrBuiltin = true
449501
}
502+
return
450503
}
451504

452505
func (ctx *fileContext) IsSysImport(alias string) bool {

lang/golang/parser/file.go

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -101,13 +101,19 @@ func (p *GoParser) parseVar(ctx *fileContext, vspec *ast.ValueSpec, isConst bool
101101
v := p.newVar(ctx.module.Name, ctx.pkgPath, name.Name, isConst)
102102
v.FileLine = ctx.FileLine(vspec)
103103
if vspec.Type != nil {
104-
id, isPointer, _ := ctx.GetTypeId(vspec.Type)
105-
v.Type = &id
106-
v.IsPointer = isPointer
104+
ti := ctx.GetTypeInfo(vspec.Type)
105+
v.Type = &ti.Id
106+
v.IsPointer = ti.IsPointer
107+
for _, dep := range ti.Deps {
108+
v.Dependencies = InsertDependency(v.Dependencies, NewDependency(dep, ctx.FileLine(vspec.Type)))
109+
}
107110
} else if val != nil && !isConst {
108-
id, isPointer, _ := ctx.GetTypeId(*val)
109-
v.Type = &id
110-
v.IsPointer = isPointer
111+
ti := ctx.GetTypeInfo(*val)
112+
v.Type = &ti.Id
113+
v.IsPointer = ti.IsPointer
114+
for _, dep := range ti.Deps {
115+
v.Dependencies = InsertDependency(v.Dependencies, NewDependency(dep, ctx.FileLine(*val)))
116+
}
111117
} else {
112118
v.Type = typ
113119
}
@@ -277,19 +283,19 @@ func (p *GoParser) parseSelector(ctx *fileContext, expr *ast.SelectorExpr, infos
277283
}
278284
// callName := string(ctx.GetRawContent(expr))
279285
// get receiver type name
280-
var rname string
281-
rev, _ := getNamedType(sel.Recv())
282-
if rev == nil {
283-
rname = extractName(sel.Recv().String())
284-
} else {
285-
rname = rev.Name()
286-
}
287-
id := NewIdentity(mod, pkg, rname+"."+expr.Sel.Name)
288-
dep := NewDependency(id, ctx.FileLine(expr.Sel))
289-
if err := p.referCodes(ctx, &id, p.opts.ReferCodeDepth); err != nil {
290-
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", id.Name, err)
286+
// var rname string
287+
rev := ctx.getTypeinfo(sel.Recv())
288+
// if rev == nil {
289+
// rname = extractName(sel.Recv().String())
290+
// } else {
291+
if !rev.IsStdOrBuiltin && rev.Id.ModPath != "" {
292+
id := NewIdentity(mod, pkg, rev.Id.Name+"."+expr.Sel.Name)
293+
dep := NewDependency(id, ctx.FileLine(expr.Sel))
294+
if err := p.referCodes(ctx, &id, p.opts.ReferCodeDepth); err != nil {
295+
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", id.Name, err)
296+
}
297+
*infos.methodCalls = InsertDependency(*infos.methodCalls, dep)
291298
}
292-
*infos.methodCalls = InsertDependency(*infos.methodCalls, dep)
293299
return false
294300
}
295301

@@ -308,14 +314,14 @@ func (p *GoParser) parseFunc(ctx *fileContext, funcDecl *ast.FuncDecl) (*Functio
308314
isMethod := funcDecl.Recv != nil
309315
if isMethod {
310316
// TODO: reserve the pointer message?
311-
id, isPointer, _ := ctx.GetTypeId(funcDecl.Recv.List[0].Type)
317+
ti := ctx.GetTypeInfo(funcDecl.Recv.List[0].Type)
312318
// name := "self"
313319
// if len(funcDecl.Recv.List[0].Names) > 0 {
314320
// name = funcDecl.Recv.List[0].Names[0].Name
315321
// }
316322
receiver = &Receiver{
317-
Type: id,
318-
IsPointer: isPointer,
323+
Type: ti.Id,
324+
IsPointer: ti.IsPointer,
319325
// Name: name,
320326
}
321327
}

lang/golang/parser/parser.go

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -143,16 +143,16 @@ func (p *GoParser) ParseRepo() (Repository, error) {
143143
}
144144

145145
func (p *GoParser) ParseModule(mod *Module, dir string) (err error) {
146-
filepath.Walk(dir, func(path string, info fs.FileInfo, e error) error {
147-
// run go mod tidy before parse
148-
cmd := exec.Command("go", "mod", "tidy")
149-
cmd.Dir = dir
150-
buf := bytes.NewBuffer(nil)
151-
cmd.Stderr = buf
152-
if err := cmd.Run(); err != nil {
153-
return fmt.Errorf("run go mod tidy failed in %s: %v", dir, buf.String())
154-
}
146+
// run go mod tidy before parse
147+
cmd := exec.Command("go", "mod", "tidy")
148+
cmd.Dir = dir
149+
buf := bytes.NewBuffer(nil)
150+
cmd.Stderr = buf
151+
if err := cmd.Run(); err != nil {
152+
fmt.Fprintf(os.Stderr, "run go mod tidy failed in %s: %v\n", dir, buf.String())
153+
}
155154

155+
filepath.Walk(dir, func(path string, info fs.FileInfo, e error) error {
156156
if info != nil && info.IsDir() && filepath.Base(path) == ".git" {
157157
return filepath.SkipDir
158158
}
@@ -163,6 +163,7 @@ func (p *GoParser) ParseModule(mod *Module, dir string) (err error) {
163163
mod.Files[rel] = NewFile(rel)
164164
return nil
165165
})
166+
166167
return p.loadPackages(mod, dir, "./...")
167168
}
168169

0 commit comments

Comments
 (0)