1
0
mirror of https://github.com/golang/go synced 2024-11-18 16:14:46 -07:00

internal/lsp: add comment completions for exported vars

This should provide simple name completions for comments
above exported variables.

Can be activated with `ctrl+space` within a comment.

Pretty new, so all help is welcome.

Fixes #34010

Change-Id: I1c8f71baa3beaa22ec5fd9fd4a531284a8d125f3
GitHub-Last-Rev: a9868eb69dc587cb4579268b2c3ae46932702641
GitHub-Pull-Request: golang/tools#166
Reviewed-on: https://go-review.googlesource.com/c/tools/+/197879
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
Clint J Edwards 2019-12-10 21:40:37 +00:00 committed by Rebecca Stambler
parent fe93f4a7d4
commit 98df123772
3 changed files with 63 additions and 15 deletions

View File

@ -417,12 +417,7 @@ func Completion(ctx context.Context, snapshot Snapshot, f File, pos protocol.Pos
if path == nil {
return nil, nil, errors.Errorf("cannot find node enclosing position")
}
// Skip completion inside comments.
for _, g := range file.Comments {
if g.Pos() <= rng.Start && rng.Start <= g.End() {
return nil, nil, nil
}
}
// Skip completion inside any kind of literal.
if _, ok := path[0].(*ast.BasicLit); ok {
return nil, nil, nil
@ -460,6 +455,14 @@ func Completion(ctx context.Context, snapshot Snapshot, f File, pos protocol.Pos
c.expectedType = expectedType(c)
// If we're inside a comment return comment completions
for _, comment := range file.Comments {
if comment.Pos() <= rng.Start && rng.Start <= comment.End() {
c.populateCommentCompletions(comment)
return c.items, c.getSurrounding(), nil
}
}
// Struct literals are handled entirely separately.
if c.wantStructFieldCompletions() {
if err := c.structLiteralFieldName(); err != nil {
@ -534,6 +537,48 @@ func Completion(ctx context.Context, snapshot Snapshot, f File, pos protocol.Pos
return c.items, c.getSurrounding(), nil
}
// populateCommentCompletions returns completions for an exported variable immediately preceeding comment
func (c *completer) populateCommentCompletions(comment *ast.CommentGroup) {
// Using the comment position find the line after
fset := c.snapshot.View().Session().Cache().FileSet()
file := fset.File(comment.Pos())
if file == nil {
return
}
line := file.Line(comment.Pos())
nextLinePos := file.LineStart(line + 1)
if !nextLinePos.IsValid() {
return
}
// Using the next line pos, grab and parse the exported variable on that line
for _, n := range c.file.Decls {
if n.Pos() != nextLinePos {
continue
}
switch node := n.(type) {
case *ast.GenDecl:
if node.Tok != token.VAR {
return
}
for _, spec := range node.Specs {
if value, ok := spec.(*ast.ValueSpec); ok {
for _, name := range value.Names {
if name.Name == "_" || !name.IsExported() {
continue
}
exportedVar := c.pkg.GetTypesInfo().ObjectOf(name)
c.found(exportedVar, stdScore, nil)
}
}
}
}
}
}
func (c *completer) wantStructFieldCompletions() bool {
clInfo := c.enclosingCompositeLiteral
if clInfo == nil {

View File

@ -1,12 +1,15 @@
package complit
// //@complete(" ", cVar)
var C string //@item(cVar, "C", "string", "var")
type position struct { //@item(structPosition, "position", "struct{...}", "struct")
X, Y int //@item(fieldX, "X", "int", "field"),item(fieldY, "Y", "int", "field")
}
func _() {
_ = position{
//@complete("", fieldX, fieldY, structPosition)
//@complete("", fieldX, fieldY, cVar, structPosition)
}
_ = position{
X: 1,
@ -18,7 +21,7 @@ func _() {
}
_ = []*position{
{
//@complete("", fieldX, fieldY, structPosition)
//@complete("", fieldX, fieldY, cVar, structPosition)
},
}
}
@ -34,7 +37,7 @@ func _() {
}
_ = map[int]int{
//@complete("", abVar, aaVar, structPosition)
//@complete("", abVar, aaVar, cVar, structPosition)
}
_ = []string{a: ""} //@complete(":", abVar, aaVar)
@ -42,10 +45,10 @@ func _() {
_ = position{X: a} //@complete("}", abVar, aaVar)
_ = position{a} //@complete("}", abVar, aaVar)
_ = position{a, } //@complete("}", abVar, aaVar, structPosition)
_ = position{a, } //@complete("}", abVar, aaVar, cVar, structPosition)
_ = []int{a} //@complete("a", abVar, aaVar, structPosition)
_ = [1]int{a} //@complete("a", abVar, aaVar, structPosition)
_ = []int{a} //@complete("a", abVar, aaVar, cVar, structPosition)
_ = [1]int{a} //@complete("a", abVar, aaVar, cVar, structPosition)
type myStruct struct {
AA int //@item(fieldAA, "AA", "int", "field")
@ -70,7 +73,7 @@ func _() {
func _() {
_ := position{
X: 1, //@complete("X", fieldX),complete(" 1", structPosition)
Y: , //@complete(":", fieldY),complete(" ,", structPosition)
X: 1, //@complete("X", fieldX),complete(" 1", cVar, structPosition)
Y: , //@complete(":", fieldY),complete(" ,", cVar, structPosition)
}
}

View File

@ -1,5 +1,5 @@
-- summary --
CompletionsCount = 219
CompletionsCount = 220
CompletionSnippetCount = 51
UnimportedCompletionsCount = 4
DeepCompletionsCount = 5