Skip to content

Commit

Permalink
Merge pull request #463 from antifuchs/emit-package-name-and-importpath
Browse files Browse the repository at this point in the history
Pass through package names, use it for godoc in emacs-company
  • Loading branch information
nsf authored Aug 25, 2017
2 parents f1eef9a + 6316a78 commit abcc7f1
Show file tree
Hide file tree
Showing 8 changed files with 100 additions and 39 deletions.
50 changes: 33 additions & 17 deletions autocompletecontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,10 @@ import (

// fields must be exported for RPC
type candidate struct {
Name string
Type string
Class decl_class
Name string
Type string
Class decl_class
Package string
}

type out_buffers struct {
Expand All @@ -43,7 +44,7 @@ func new_out_buffers(ctx *auto_complete_context) *out_buffers {
b.ctx = ctx
b.canonical_aliases = make(map[string]string)
for _, imp := range b.ctx.current.packages {
b.canonical_aliases[imp.path] = imp.alias
b.canonical_aliases[imp.abspath] = imp.alias
}
return b
}
Expand All @@ -65,7 +66,7 @@ func (b *out_buffers) Swap(i, j int) {
b.candidates[i], b.candidates[j] = b.candidates[j], b.candidates[i]
}

func (b *out_buffers) append_decl(p, name string, decl *decl, class decl_class) {
func (b *out_buffers) append_decl(p, name, pkg string, decl *decl, class decl_class) {
c1 := !g_config.ProposeBuiltins && decl.scope == g_universe_scope && decl.name != "Error"
c2 := class != decl_invalid && decl.class != class
c3 := class == decl_invalid && !has_prefix(name, p, b.ignorecase)
Expand All @@ -78,14 +79,15 @@ func (b *out_buffers) append_decl(p, name string, decl *decl, class decl_class)

decl.pretty_print_type(b.tmpbuf, b.canonical_aliases)
b.candidates = append(b.candidates, candidate{
Name: name,
Type: b.tmpbuf.String(),
Class: decl.class,
Name: name,
Type: b.tmpbuf.String(),
Class: decl.class,
Package: pkg,
})
b.tmpbuf.Reset()
}

func (b *out_buffers) append_embedded(p string, decl *decl, class decl_class) {
func (b *out_buffers) append_embedded(p string, decl *decl, pkg string, class decl_class) {
if decl.embedded == nil {
return
}
Expand Down Expand Up @@ -119,10 +121,10 @@ func (b *out_buffers) append_embedded(p string, decl *decl, class decl_class) {
if _, has := b.tmpns[c.name]; has {
continue
}
b.append_decl(p, c.name, c, class)
b.append_decl(p, c.name, pkg, c, class)
b.tmpns[c.name] = true
}
b.append_embedded(p, typedecl, class)
b.append_embedded(p, typedecl, pkg, class)
}

if first_level {
Expand Down Expand Up @@ -208,7 +210,11 @@ func (c *auto_complete_context) get_candidates_from_set(set map[string]*decl, pa
continue
}
value.infer_type()
b.append_decl(partial, key, value, class)
pkgname := ""
if pkg, ok := c.pcache[value.name]; ok {
pkgname = pkg.import_name
}
b.append_decl(partial, key, pkgname, value, class)
}
}

Expand All @@ -229,6 +235,16 @@ func (c *auto_complete_context) get_candidates_from_decl_alias(cc cursor_context
return
}

func (c *auto_complete_context) decl_package_import_path(decl *decl) string {
if decl == nil || decl.scope == nil {
return ""
}
if pkg, ok := c.pcache[decl.scope.pkgname]; ok {
return pkg.import_name
}
return ""
}

func (c *auto_complete_context) get_candidates_from_decl(cc cursor_context, class decl_class, b *out_buffers) {
if cc.decl.is_alias() {
c.get_candidates_from_decl_alias(cc, class, b)
Expand All @@ -246,19 +262,19 @@ func (c *auto_complete_context) get_candidates_from_decl(cc cursor_context, clas
continue
}
}
b.append_decl(cc.partial, decl.name, decl, class)
b.append_decl(cc.partial, decl.name, c.decl_package_import_path(decl), decl, class)
}
// propose all children of an underlying struct/interface type
adecl := advance_to_struct_or_interface(cc.decl)
if adecl != nil && adecl != cc.decl {
for _, decl := range adecl.children {
if decl.class == decl_var {
b.append_decl(cc.partial, decl.name, decl, class)
b.append_decl(cc.partial, decl.name, c.decl_package_import_path(decl), decl, class)
}
}
}
// propose all children of its embedded types
b.append_embedded(cc.partial, cc.decl, class)
b.append_embedded(cc.partial, cc.decl, c.decl_package_import_path(cc.decl), class)
}

func (c *auto_complete_context) get_import_candidates(partial string, b *out_buffers) {
Expand Down Expand Up @@ -482,7 +498,7 @@ func merge_decls(filescope *scope, pkg *scope, decls map[string]*decl) {

func merge_decls_from_packages(pkgscope *scope, pkgs []package_import, pcache package_cache) {
for _, p := range pkgs {
path, alias := p.path, p.alias
path, alias := p.abspath, p.alias
if alias != "." {
continue
}
Expand All @@ -500,7 +516,7 @@ func merge_decls_from_packages(pkgscope *scope, pkgs []package_import, pcache pa

func fixup_packages(filescope *scope, pkgs []package_import, pcache package_cache) {
for _, p := range pkgs {
path, alias := p.path, p.alias
path, alias := p.abspath, p.alias
if alias == "" {
alias = pcache[path].defalias
}
Expand Down
2 changes: 1 addition & 1 deletion cursorcontext.go
Original file line number Diff line number Diff line change
Expand Up @@ -413,7 +413,7 @@ func resolveKnownPackageIdent(ident string, filename string, context *package_lo
return nil
}

p := new_package_file_cache(path)
p := new_package_file_cache(path, path)
p.update_cache()
return p.main
}
Expand Down
9 changes: 5 additions & 4 deletions declcache.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ import (
//-------------------------------------------------------------------------

type package_import struct {
alias string
path string
alias string
abspath string
path string
}

// Parses import declarations until the first non-import declaration and fills
Expand All @@ -32,9 +33,9 @@ func collect_package_imports(filename string, decls []ast.Decl, context *package
for _, spec := range gd.Specs {
imp := spec.(*ast.ImportSpec)
path, alias := path_and_alias(imp)
path, ok := abs_path_for_package(filename, path, context)
abspath, ok := abs_path_for_package(filename, path, context)
if ok && alias != "_" {
pi = append(pi, package_import{alias, path})
pi = append(pi, package_import{alias, abspath, path})
}
}
} else {
Expand Down
33 changes: 32 additions & 1 deletion emacs-company/company-go.el
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,16 @@ symbol is preceded by a \".\", ignoring `company-minimum-prefix-length'."
:group 'company-go
:type '(repeat string))

(defcustom company-go-godoc-command "go doc"
"The command to invoke `go doc' with."
:group 'company-go
:type 'string)

(defcustom company-go-godoc-args "-u"
"Arguments to pass to `go doc'."
:group 'company-go
:type 'string)

(defun company-go--invoke-autocomplete ()
(let ((code-buffer (current-buffer))
(gocode-args (append company-go-gocode-args
Expand Down Expand Up @@ -90,7 +100,10 @@ symbol is preceded by a \".\", ignoring `company-minimum-prefix-length'."
(defun company-go--get-candidates (strings)
(mapcar (lambda (str)
(let ((candidate (split-string str ",,")))
(propertize (nth 1 candidate) 'meta (company-go--format-meta candidate)))) strings))
(propertize (nth 1 candidate)
'meta (company-go--format-meta candidate)
'package (nth 3 candidate))))
strings))

(defun company-go--candidates ()
(let ((candidates (company-go--get-candidates (split-string (company-go--invoke-autocomplete) "\n" t))))
Expand Down Expand Up @@ -207,6 +220,22 @@ triggers a completion immediately."
(buffer-string))
str))

(defun company-go--godoc-as-buffer (arg)
"Return Go documentation for QUERY as a buffer."
(unless (string= arg "")
(let* ((package (get-text-property 0 'package arg))
(query (if (string= package "")
arg
(format "%s.%s" package arg)))
(buf (godoc--get-buffer query))
(exit-code (call-process-shell-command
(concat company-go-godoc-command " " company-go-godoc-args " " query)
nil buf nil)))
(if (zerop exit-code)
buf
(kill-buffer buf)
nil))))

;;;###autoload
(defun company-go (command &optional arg &rest ignored)
(interactive (list 'interactive))
Expand All @@ -223,6 +252,8 @@ triggers a completion immediately."
(when company-go-show-annotation
(company-go--extract-annotation (get-text-property 0 'meta arg))))
(location (company-go--location arg))
(doc-buffer
(company-go--godoc-as-buffer arg))
(sorted t)
(post-completion
(when (and company-go-insert-arguments
Expand Down
6 changes: 3 additions & 3 deletions formatters.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ type csv_formatter struct{}

func (*csv_formatter) write_candidates(candidates []candidate, num int) {
for _, c := range candidates {
fmt.Printf("%s,,%s,,%s\n", c.Class, c.Name, c.Type)
fmt.Printf("%s,,%s,,%s,,%s\n", c.Class, c.Name, c.Type, c.Package)
}
}

Expand All @@ -145,8 +145,8 @@ func (*json_formatter) write_candidates(candidates []candidate, num int) {
if i != 0 {
fmt.Printf(", ")
}
fmt.Printf(`{"class": "%s", "name": "%s", "type": "%s"}`,
c.Class, c.Name, c.Type)
fmt.Printf(`{"class": "%s", "name": "%s", "type": "%s", "package": "%s"}`,
c.Class, c.Name, c.Type, c.Package)
}
fmt.Print("]]")
}
Expand Down
26 changes: 14 additions & 12 deletions package.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ type package_parser interface {
//-------------------------------------------------------------------------

type package_file_cache struct {
name string // file name
mtime int64
defalias string
name string // file name
import_name string
mtime int64
defalias string

scope *scope
main *decl // package declaration
others map[string]*decl
}

func new_package_file_cache(name string) *package_file_cache {
func new_package_file_cache(absname, name string) *package_file_cache {
m := new(package_file_cache)
m.name = name
m.name = absname
m.import_name = name
m.mtime = 0
m.defalias = ""
return m
Expand Down Expand Up @@ -92,7 +94,7 @@ func (m *package_file_cache) update_cache() {
}

func (m *package_file_cache) process_package_data(data []byte) {
m.scope = new_scope(g_universe_scope)
m.scope = new_named_scope(g_universe_scope, m.name)

// find import section
i := bytes.Index(data, []byte{'\n', '$', '$'})
Expand Down Expand Up @@ -219,16 +221,16 @@ func new_package_cache() package_cache {
// In case if package is not in the cache, it creates one and adds one to the cache.
func (c package_cache) append_packages(ps map[string]*package_file_cache, pkgs []package_import) {
for _, m := range pkgs {
if _, ok := ps[m.path]; ok {
if _, ok := ps[m.abspath]; ok {
continue
}

if mod, ok := c[m.path]; ok {
ps[m.path] = mod
if mod, ok := c[m.abspath]; ok {
ps[m.abspath] = mod
} else {
mod = new_package_file_cache(m.path)
ps[m.path] = mod
c[m.path] = mod
mod = new_package_file_cache(m.abspath, m.path)
ps[m.abspath] = mod
c[m.abspath] = mod
}
}
}
Expand Down
11 changes: 11 additions & 0 deletions scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,23 @@ package main
//-------------------------------------------------------------------------

type scope struct {
// the package name that this scope resides in
pkgname string
parent *scope // nil for universe scope
entities map[string]*decl
}

func new_named_scope(outer *scope, name string) *scope {
s := new_scope(outer)
s.pkgname = name
return s
}

func new_scope(outer *scope) *scope {
s := new(scope)
if outer != nil {
s.pkgname = outer.pkgname
}
s.parent = outer
s.entities = make(map[string]*decl)
return s
Expand Down
2 changes: 1 addition & 1 deletion server.go
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ func server_auto_complete(file []byte, filename string, cursor int, context_pack
if err := recover(); err != nil {
print_backtrace(err)
c = []candidate{
{"PANIC", "PANIC", decl_invalid},
{"PANIC", "PANIC", decl_invalid, "panic"},
}

// drop cache
Expand Down

0 comments on commit abcc7f1

Please sign in to comment.