Skip to content

Commit c35f8eb

Browse files
authored
opt: collect Var.Dependencies in go; Omit redundant std-symbols in rust (#38)
* opt: not collect std * fix: fileline starts from 1 * fix: var collect complex initializer's dependencies * fix
1 parent 53a57d4 commit c35f8eb

File tree

7 files changed

+210
-160
lines changed

7 files changed

+210
-160
lines changed

lang/collect/export.go

Lines changed: 35 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -77,10 +77,7 @@ func (c *Collector) Export(ctx context.Context) (*uniast.Repository, error) {
7777
// export symbols
7878
for _, symbol := range c.syms {
7979
visited := make(map[*lsp.DocumentSymbol]*uniast.Identity)
80-
_, err := c.exportSymbol(&repo, symbol, "", visited)
81-
if err != nil {
82-
log.Info("export symbol %s failed: %v\n", symbol, err)
83-
}
80+
_, _ = c.exportSymbol(&repo, symbol, "", visited)
8481
}
8582

8683
// patch module
@@ -96,6 +93,11 @@ func (c *Collector) Export(ctx context.Context) (*uniast.Repository, error) {
9693
return &repo, nil
9794
}
9895

96+
var (
97+
ErrStdSymbol = errors.New("std symbol")
98+
ErrExternalSymbol = errors.New("external symbol")
99+
)
100+
99101
// NOTICE: for rust and golang, each entity has separate location
100102
// TODO: some language may allow local symbols inside another symbol,
101103
func (c *Collector) filterLocalSymbols() {
@@ -113,9 +115,16 @@ func (c *Collector) filterLocalSymbols() {
113115
}
114116
}
115117

116-
func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol, refName string, visited map[*DocumentSymbol]*uniast.Identity) (*uniast.Identity, error) {
118+
func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol, refName string, visited map[*DocumentSymbol]*uniast.Identity) (id *uniast.Identity, e error) {
119+
defer func() {
120+
if e != nil && e != ErrStdSymbol && e != ErrExternalSymbol {
121+
log.Info("export symbol %s failed: %v\n", symbol, e)
122+
}
123+
}()
124+
117125
if symbol == nil {
118-
return nil, errors.New("symbol is nil")
126+
e = errors.New("symbol is nil")
127+
return
119128
}
120129
if id, ok := visited[symbol]; ok {
121130
return id, nil
@@ -124,22 +133,32 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
124133
name := symbol.Name
125134
if name == "" {
126135
if refName == "" {
127-
return nil, fmt.Errorf("both symbol %v name and refname is empty", symbol)
136+
e = fmt.Errorf("both symbol %v name and refname is empty", symbol)
137+
return
128138
}
129139
// NOTICE: use refName as id when symbol name is missing
130140
name = refName
131141
}
132142
file := symbol.Location.URI.File()
133143
mod, path, err := c.spec.NameSpace(file)
134144
if err != nil {
135-
return nil, err
145+
e = err
146+
return
136147
}
137-
id := uniast.NewIdentity(mod, path, name)
138-
visited[symbol] = &id
148+
149+
if !c.NeedStdSymbol && mod == "" {
150+
e = ErrStdSymbol
151+
return
152+
}
153+
154+
tmp := uniast.NewIdentity(mod, path, name)
155+
id = &tmp
156+
visited[symbol] = id
139157

140158
// Load eternal symbol on demands
141159
if !c.LoadExternalSymbol && (!c.internal(symbol.Location) || symbol.Kind == SKUnknown) {
142-
return &id, nil
160+
e = ErrExternalSymbol
161+
return
143162
}
144163

145164
if repo.Modules[mod] == nil {
@@ -196,7 +215,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
196215
tok, _ := c.cli.Locate(input.Location)
197216
tyid, err := c.exportSymbol(repo, input.Symbol, tok, visited)
198217
if err != nil {
199-
log.Error("export input symbol %s failed: %v\n", input.Symbol, err)
200218
continue
201219
}
202220
dep := uniast.NewDependency(*tyid, c.fileLine(input.Location))
@@ -208,7 +226,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
208226
tok, _ := c.cli.Locate(input.Location)
209227
tyid, err := c.exportSymbol(repo, input.Symbol, tok, visited)
210228
if err != nil {
211-
log.Error("export input symbol %s failed: %v\n", input.Symbol, err)
212229
continue
213230
}
214231
dep := uniast.NewDependency(*tyid, c.fileLine(input.Location))
@@ -220,7 +237,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
220237
tok, _ := c.cli.Locate(output.Location)
221238
tyid, err := c.exportSymbol(repo, output.Symbol, tok, visited)
222239
if err != nil {
223-
log.Error("export output symbol %s failed: %v\n", output.Symbol, err)
224240
continue
225241
}
226242
dep := uniast.NewDependency(*tyid, c.fileLine(output.Location))
@@ -242,9 +258,7 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
242258
if info.Method.Interface != nil {
243259
itok, _ := c.cli.Locate(info.Method.Interface.Location)
244260
iid, err := c.exportSymbol(repo, info.Method.Interface.Symbol, itok, visited)
245-
if err != nil {
246-
log.Error("export interface symbol %s failed: %v\n", info.Method.Interface.Symbol, err)
247-
} else {
261+
if err == nil {
248262
id.Name = iid.Name + "<" + id.Name + ">"
249263
}
250264
}
@@ -259,8 +273,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
259273
if info.Method.ImplHead != "" {
260274
obj.Content = info.Method.ImplHead + obj.Content + "\n}"
261275
}
262-
} else {
263-
log.Error("export receiver symbol %s failed: %v\n", info.Method.Receiver.Symbol, err)
264276
}
265277
}
266278
// collect deps
@@ -269,7 +281,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
269281
tok, _ := c.cli.Locate(dep.Location)
270282
depid, err := c.exportSymbol(repo, dep.Symbol, tok, visited)
271283
if err != nil {
272-
log.Error("export dep symbol %s failed: %v\n", dep.Symbol, err)
273284
continue
274285
}
275286
pdep := uniast.NewDependency(*depid, c.fileLine(dep.Location))
@@ -297,7 +308,7 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
297308
}
298309
}
299310
}
300-
obj.Identity = id
311+
obj.Identity = *id
301312
pkg.Functions[id.Name] = obj
302313

303314
// Type
@@ -314,7 +325,6 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
314325
tok, _ := c.cli.Locate(dep.Location)
315326
depid, err := c.exportSymbol(repo, dep.Symbol, tok, visited)
316327
if err != nil {
317-
log.Error("export dep symbol %s failed: %v\n", dep.Symbol, err)
318328
continue
319329
}
320330
switch dep.Symbol.Kind {
@@ -332,14 +342,13 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
332342
tok, _ := c.cli.Locate(method.Location)
333343
mid, err := c.exportSymbol(repo, method, tok, visited)
334344
if err != nil {
335-
log.Error("export method symbol %s failed: %v\n", method, err)
336345
continue
337346
}
338347
// NOTICE: use method name as key here
339348
obj.Methods[method.Name] = *mid
340349
}
341350
}
342-
obj.Identity = id
351+
obj.Identity = *id
343352
pkg.Types[id.Name] = obj
344353
// Vars
345354
case lsp.SKConstant, lsp.SKVariable:
@@ -354,17 +363,15 @@ func (c *Collector) exportSymbol(repo *uniast.Repository, symbol *DocumentSymbol
354363
tyid, err := c.exportSymbol(repo, ty.Symbol, tok, visited)
355364
if err == nil {
356365
obj.Type = tyid
357-
} else {
358-
log.Error("export var type symbol %s failed: %v\n", ty.Symbol, err)
359366
}
360367
}
361-
obj.Identity = id
368+
obj.Identity = *id
362369
pkg.Vars[id.Name] = obj
363370
default:
364371
log.Error("symbol %s not collected\n", symbol)
365372
}
366373

367-
return &id, nil
374+
return
368375
}
369376

370377
func mapKind(kind lsp.SymbolKind) uniast.TypeKind {

lang/golang/parser/ctx.go

Lines changed: 35 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,7 @@ func GetRawContent(fset *token.FileSet, file []byte, node ast.Node, collectComme
249249

250250
type typeInfo struct {
251251
Id Identity
252+
IsNamed bool
252253
IsPointer bool
253254
IsStdOrBuiltin bool
254255
Deps []Identity
@@ -266,17 +267,17 @@ func (ctx *fileContext) GetTypeInfo(typ ast.Expr) typeInfo {
266267
}
267268
}
268269

269-
func (ctx *fileContext) mockType(typ ast.Expr) typeInfo {
270+
func (ctx *fileContext) mockType(typ ast.Expr) (ti typeInfo) {
270271
switch ty := typ.(type) {
271272
case *ast.StarExpr:
272-
ti := ctx.mockType(ty.X)
273+
ti = ctx.mockType(ty.X)
273274
ti.IsPointer = true
274-
return ti
275+
return
275276
case *ast.CallExpr:
276277
// try get func type
277-
ti := ctx.mockType(ty.Fun)
278+
ti = ctx.mockType(ty.Fun)
278279
ti.IsPointer = false
279-
return ti
280+
return
280281
case *ast.SelectorExpr:
281282
// try get import path
282283
switch xx := ty.X.(type) {
@@ -285,18 +286,21 @@ func (ctx *fileContext) mockType(typ ast.Expr) typeInfo {
285286
if err != nil {
286287
goto fallback
287288
}
288-
return typeInfo{NewIdentity(mod, PkgPath(impt), ty.Sel.Name), false, false, nil, nil}
289+
ti.Id = NewIdentity(mod, PkgPath(impt), ty.Sel.Name)
290+
return
289291
case *ast.SelectorExpr:
290292
// recurse
291-
ti := ctx.mockType(xx)
293+
ti = ctx.mockType(xx)
292294
ti.Id.Name = ty.Sel.Name
293295
ti.IsPointer = false
294296
return ti
295297
}
296298
}
297299

298300
fallback:
299-
return typeInfo{NewIdentity("UNLOADED", ctx.pkgPath, string(ctx.GetRawContent(typ))), false, true, nil, nil}
301+
ti.Id = NewIdentity("UNLOADED", ctx.pkgPath, string(ctx.GetRawContent(typ)))
302+
ti.IsStdOrBuiltin = true
303+
return
300304
}
301305

302306
func (ctx *fileContext) collectFields(fields []*ast.Field, m *[]Dependency) {
@@ -442,20 +446,18 @@ func (p *GoParser) collectTypes(ctx *fileContext, typ ast.Expr, st *Type, inline
442446
if err := p.referCodes(ctx, &dep, p.opts.ReferCodeDepth); err != nil {
443447
fmt.Fprintf(os.Stderr, "failed to get refer code for %s: %v\n", dep, err)
444448
}
445-
if inlined {
446-
st.InlineStruct = InsertDependency(st.InlineStruct, NewDependency(dep, ctx.FileLine(typ)))
447-
} else {
448-
st.SubStruct = InsertDependency(st.SubStruct, NewDependency(dep, ctx.FileLine(typ)))
449-
}
449+
st.SubStruct = InsertDependency(st.SubStruct, NewDependency(dep, ctx.FileLine(typ)))
450450
}
451451
}
452452

453453
// get type id and tells if it is std or builtin
454454
func (ctx *fileContext) getTypeinfo(typ types.Type) (ti typeInfo) {
455-
tobjs, isPointer := getNamedTypes(typ)
455+
tobjs, isPointer, isNamed := getNamedTypes(typ)
456456
ti.IsPointer = isPointer
457457
ti.Ty = typ
458-
if len(tobjs) > 0 {
458+
ti.IsNamed = isNamed
459+
// NOTICE: only get full id for Named type
460+
if isNamed {
459461
tobj := tobjs[0]
460462
if tp := tobj.Pkg(); tp != nil {
461463
mod, err := ctx.GetMod(tp.Path())
@@ -480,27 +482,28 @@ func (ctx *fileContext) getTypeinfo(typ types.Type) (ti typeInfo) {
480482
ti.IsStdOrBuiltin = false
481483
}
482484
}
483-
// NOTICE: only extract Named type here
484-
for i := 1; i < len(tobjs); i++ {
485-
tobj := tobjs[i]
486-
if isGoBuiltins(tobj.Name()) {
487-
continue
488-
}
489-
// get mod and pkg from tobj.Pkg()
490-
tp := tobj.Pkg()
491-
if tp == nil {
492-
continue
493-
}
494-
mod, err := ctx.GetMod(tp.Path())
495-
if err != nil || mod == "" {
496-
continue
497-
}
498-
ti.Deps = append(ti.Deps, NewIdentity(mod, tp.Path(), tobj.Name()))
499-
}
500485
} else {
486+
// Notice: for Composite type like map, slice, regard it as builtin
501487
ti.Id = Identity{"", "", typ.String()}
502488
ti.IsStdOrBuiltin = true
503489
}
490+
// collect sub Named type here
491+
for i := 1; i < len(tobjs); i++ {
492+
tobj := tobjs[i]
493+
if isGoBuiltins(tobj.Name()) {
494+
continue
495+
}
496+
// get mod and pkg from tobj.Pkg()
497+
tp := tobj.Pkg()
498+
if tp == nil {
499+
continue
500+
}
501+
mod, err := ctx.GetMod(tp.Path())
502+
if err != nil || mod == "" {
503+
continue
504+
}
505+
ti.Deps = append(ti.Deps, NewIdentity(mod, tp.Path(), tobj.Name()))
506+
}
504507
return
505508
}
506509

0 commit comments

Comments
 (0)