Skip to content

Commit

Permalink
gopls/internal/lsp/source/completion: unimport check gop index overload
Browse files Browse the repository at this point in the history
  • Loading branch information
visualfc committed Feb 3, 2024
1 parent c06876b commit a438af6
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 16 deletions.
37 changes: 23 additions & 14 deletions gopls/internal/lsp/source/completion/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -3310,7 +3310,7 @@ func forEachPackageMember(content []byte, f func(tok token.Token, id *ast.Ident,
}

// goxls: quickParse
func (c *gopCompleter) quickParse(ctx context.Context, cMu *sync.Mutex, enough *int32, selName string, relevances map[string]float64, needImport bool) func(uri span.URI, m *source.Metadata) error {
func (c *gopCompleter) quickParse(ctx context.Context, cMu *sync.Mutex, enough *int32, selName string, relevances map[string]float64, needImport bool, recheck *unimportChecked) func(uri span.URI, m *source.Metadata) error {
return func(uri span.URI, m *source.Metadata) error {
if atomic.LoadInt32(enough) != 0 {
return nil
Expand Down Expand Up @@ -3420,23 +3420,32 @@ func (c *gopCompleter) quickParse(ctx context.Context, cMu *sync.Mutex, enough *
}

cMu.Lock()
c.items = append(c.items, item)
// goxls func alias
if tok == token.CONST && id.Name == "GopPackage" {
recheck.pkgs[m.PkgPath] = true
}
if tok == token.FUNC {
if alias, ok := hasAliasName(id.Name); ok {
var noSnip bool
switch len(fn.Type.Params.List) {
case 0:
noSnip = true
case 1:
if fn.Recv != nil {
if _, ok := fn.Type.Params.List[0].Type.(*ast.Ellipsis); ok {
noSnip = true
}
var noSnip bool
switch len(fn.Type.Params.List) {
case 0:
noSnip = true
case 1:
if fn.Recv != nil {
if _, ok := fn.Type.Params.List[0].Type.(*ast.Ellipsis); ok {
noSnip = true
}
}
c.items = append(c.items, cloneAliasItem(item, id.Name, alias, 0.0001, noSnip))
}
if maybleIndexOverload(id.Name) {
recheck.items[m.PkgPath] = append(recheck.items[m.PkgPath], recheckItem{item, noSnip})
} else {
c.items = append(c.items, item)
// goxls func alias
if alias, ok := hasAliasName(id.Name); ok {
c.items = append(c.items, cloneAliasItem(item, id.Name, alias, 0.0001, noSnip))
}
}
} else {
c.items = append(c.items, item)
}
if len(c.items) >= unimportedMemberTarget {
atomic.StoreInt32(enough, 1)
Expand Down
49 changes: 47 additions & 2 deletions gopls/internal/lsp/source/completion/completion_gox.go
Original file line number Diff line number Diff line change
Expand Up @@ -1313,12 +1313,20 @@ func (c *gopCompleter) selector(ctx context.Context, sel *ast.SelectorExpr) erro
return nil
}

// recheck is gop index overload check
recheck := &unimportChecked{
make(map[source.PackagePath]bool),
make(map[source.PackagePath][]recheckItem),
}
for _, path := range paths {
recheck.pkgs[source.PackagePath(path)] = true
}
// Extract the package-level candidates using a quick parse.
quickParseGo := c.quickParse(ctx, &cMu, &enough, sel.Sel.Name, relevances, needImport)
quickParseGo := c.quickParse(ctx, &cMu, &enough, sel.Sel.Name, relevances, needImport, recheck)
var g errgroup.Group
for _, path := range paths {
m := known[source.PackagePath(path)]
for _, uri := range m.CompiledGopFiles { // goxls: TODO - how to handle Go files?
for _, uri := range m.CompiledGopFiles {
uri := uri
g.Go(func() error {
return quickParse(uri, m)
Expand All @@ -1334,6 +1342,33 @@ func (c *gopCompleter) selector(ctx context.Context, sel *ast.SelectorExpr) erro
if err := g.Wait(); err != nil {
return err
}
// check gop packages index overload
for pkg, items := range recheck.items {
if recheck.pkgs[pkg] {
names := make(map[string]bool)
sort.Slice(items, func(i, j int) bool {
return items[i].Label < items[j].Label
})
for _, item := range items {
id := item.Label[:len(item.Label)-3]
if !names[id] {
names[id] = true
item.isOverload = true
c.items = append(c.items, cloneAliasItem(item.CompletionItem, item.Label, id, 0, false))
if alias, ok := hasAliasName(id); ok {
c.items = append(c.items, cloneAliasItem(item.CompletionItem, item.Label, alias, 0.0001, item.noSnip))
}
}
}
} else {
for _, item := range items {
c.items = append(c.items, item.CompletionItem)
if alias, ok := hasAliasName(item.Label); ok {
c.items = append(c.items, cloneAliasItem(item.CompletionItem, item.Label, alias, 0.0001, item.noSnip))
}
}
}
}

// In addition, we search in the module cache using goimports.
ctx, cancel := context.WithCancel(ctx)
Expand Down Expand Up @@ -1371,6 +1406,16 @@ func (c *gopCompleter) selector(ctx context.Context, sel *ast.SelectorExpr) erro
return nil
}

type recheckItem struct {
CompletionItem
noSnip bool
}

type unimportChecked struct {
pkgs map[source.PackagePath]bool // gop package
items map[source.PackagePath][]recheckItem
}

func (c *gopCompleter) packageMembers(pkg *types.Package, score float64, imp *importInfo, cb func(candidate)) {
scope := pkg.Scope()
for _, name := range scope.Names() {
Expand Down
11 changes: 11 additions & 0 deletions gopls/internal/lsp/source/completion/format_gox.go
Original file line number Diff line number Diff line change
Expand Up @@ -293,6 +293,17 @@ func isIndexOverload(fn string, name string) bool {
return false
}

func maybleIndexOverload(fn string) bool {
n := len(fn)
if (n > 3) && (fn[n-3] == '_') && (fn[n-2] == '_') {
c := fn[n-1]
if (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') {
return true
}
}
return false
}

func (c *gopCompleter) formatBuiltin(ctx context.Context, cand candidate) (CompletionItem, error) {
obj := cand.obj
item := CompletionItem{
Expand Down

0 comments on commit a438af6

Please sign in to comment.