2019-09-20 14:01:33 -06:00
|
|
|
package source
|
|
|
|
|
|
|
|
import (
|
|
|
|
"go/ast"
|
|
|
|
|
|
|
|
"golang.org/x/tools/internal/lsp/protocol"
|
|
|
|
)
|
|
|
|
|
|
|
|
const (
|
|
|
|
BREAK = "break"
|
|
|
|
CASE = "case"
|
|
|
|
CHAN = "chan"
|
|
|
|
CONST = "const"
|
|
|
|
CONTINUE = "continue"
|
|
|
|
DEFAULT = "default"
|
|
|
|
DEFER = "defer"
|
|
|
|
ELSE = "else"
|
|
|
|
FALLTHROUGH = "fallthrough"
|
|
|
|
FOR = "for"
|
|
|
|
FUNC = "func"
|
|
|
|
GO = "go"
|
|
|
|
GOTO = "goto"
|
|
|
|
IF = "if"
|
|
|
|
IMPORT = "import"
|
|
|
|
INTERFACE = "interface"
|
|
|
|
MAP = "map"
|
|
|
|
PACKAGE = "package"
|
|
|
|
RANGE = "range"
|
|
|
|
RETURN = "return"
|
|
|
|
SELECT = "select"
|
|
|
|
STRUCT = "struct"
|
|
|
|
SWITCH = "switch"
|
|
|
|
TYPE = "type"
|
|
|
|
VAR = "var"
|
|
|
|
)
|
|
|
|
|
2020-02-02 22:21:07 -07:00
|
|
|
// addKeywordCompletions offers keyword candidates appropriate at the position.
|
|
|
|
func (c *completer) addKeywordCompletions() {
|
|
|
|
seen := make(map[string]bool)
|
|
|
|
|
|
|
|
// addKeywords dedupes and adds completion items for the specified
|
|
|
|
// keywords with the specified score.
|
|
|
|
addKeywords := func(score float64, kws ...string) {
|
|
|
|
for _, kw := range kws {
|
|
|
|
if seen[kw] {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
seen[kw] = true
|
|
|
|
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
if matchScore := c.matcher.Score(kw); matchScore > 0 {
|
2020-02-02 22:21:07 -07:00
|
|
|
c.items = append(c.items, CompletionItem{
|
|
|
|
Label: kw,
|
|
|
|
Kind: protocol.KeywordCompletion,
|
|
|
|
InsertText: kw,
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
Score: score * float64(matchScore),
|
2020-02-02 22:21:07 -07:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
if c.wantTypeName() {
|
|
|
|
// If we expect a type name, include "interface", "struct",
|
|
|
|
// "func", "chan", and "map".
|
|
|
|
|
|
|
|
// "interface" and "struct" are more common declaring named types.
|
|
|
|
// Give them a higher score if we are in a type declaration.
|
|
|
|
structIntf, funcChanMap := stdScore, highScore
|
|
|
|
if len(c.path) > 1 {
|
|
|
|
if _, namedDecl := c.path[1].(*ast.TypeSpec); namedDecl {
|
|
|
|
structIntf, funcChanMap = highScore, stdScore
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
addKeywords(structIntf, STRUCT, INTERFACE)
|
|
|
|
addKeywords(funcChanMap, FUNC, CHAN, MAP)
|
|
|
|
}
|
|
|
|
|
2020-02-02 22:21:07 -07:00
|
|
|
// If we are at the file scope, only offer decl keywords. We don't
|
|
|
|
// get *ast.Idents at the file scope because non-keyword identifiers
|
|
|
|
// turn into *ast.BadDecl, not *ast.Ident.
|
|
|
|
if len(c.path) == 1 || isASTFile(c.path[1]) {
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, TYPE, CONST, VAR, FUNC, IMPORT)
|
2020-02-02 22:21:07 -07:00
|
|
|
return
|
|
|
|
} else if _, ok := c.path[0].(*ast.Ident); !ok {
|
|
|
|
// Otherwise only offer keywords if the client is completing an identifier.
|
|
|
|
return
|
2019-09-20 14:01:33 -06:00
|
|
|
}
|
|
|
|
|
2020-02-21 22:29:08 -07:00
|
|
|
if len(c.path) > 2 {
|
|
|
|
// Offer "range" if we are in ast.ForStmt.Init. This is what the
|
|
|
|
// AST looks like before "range" is typed, e.g. "for i := r<>".
|
|
|
|
if loop, ok := c.path[2].(*ast.ForStmt); ok && nodeContains(loop.Init, c.pos) {
|
|
|
|
addKeywords(stdScore, RANGE)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-02-02 22:21:07 -07:00
|
|
|
// Only suggest keywords if we are beginning a statement.
|
2019-09-20 14:01:33 -06:00
|
|
|
switch c.path[1].(type) {
|
|
|
|
case *ast.BlockStmt, *ast.CommClause, *ast.CaseClause, *ast.ExprStmt:
|
|
|
|
default:
|
2020-02-02 22:21:07 -07:00
|
|
|
return
|
2019-09-20 14:01:33 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
// Filter out keywords depending on scope
|
|
|
|
// Skip the first one because we want to look at the enclosing scopes
|
2019-12-07 13:22:42 -07:00
|
|
|
path := c.path[1:]
|
|
|
|
for i, n := range path {
|
2019-09-20 14:01:33 -06:00
|
|
|
switch node := n.(type) {
|
|
|
|
case *ast.CaseClause:
|
|
|
|
// only recommend "fallthrough" and "break" within the bodies of a case clause
|
|
|
|
if c.pos > node.Colon {
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, BREAK)
|
2019-12-07 13:22:42 -07:00
|
|
|
// "fallthrough" is only valid in switch statements.
|
|
|
|
// A case clause is always nested within a block statement in a switch statement,
|
|
|
|
// that block statement is nested within either a TypeSwitchStmt or a SwitchStmt.
|
|
|
|
if i+2 >= len(path) {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if _, ok := path[i+2].(*ast.SwitchStmt); ok {
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, FALLTHROUGH)
|
2019-12-07 13:22:42 -07:00
|
|
|
}
|
2019-09-20 14:01:33 -06:00
|
|
|
}
|
|
|
|
case *ast.CommClause:
|
|
|
|
if c.pos > node.Colon {
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, BREAK)
|
2019-09-20 14:01:33 -06:00
|
|
|
}
|
|
|
|
case *ast.TypeSwitchStmt, *ast.SelectStmt, *ast.SwitchStmt:
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, CASE, DEFAULT)
|
2019-09-20 14:01:33 -06:00
|
|
|
case *ast.ForStmt:
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, BREAK, CONTINUE)
|
2019-09-20 14:01:33 -06:00
|
|
|
// This is a bit weak, functions allow for many keywords
|
|
|
|
case *ast.FuncDecl:
|
|
|
|
if node.Body != nil && c.pos > node.Body.Lbrace {
|
internal/lsp/source: complete keywords as types
Offer "struct", "interface", "map", "chan", and "func" keywords when
we expect a type. For example "var foo i<>" will offer "interface".
Because "struct" and "interface" are more often used when declaring
named types, they get a higher score in type declarations. Otherwise,
"map", "chan" and "func" get a higher score.
I also got rid of the special keyword scoring. Now keywords just use
stdScore and highScore. This makes the interplay with other types of
candidates more predictable. Keywords are offered in pretty limited
contexts, so I don't think they will be annoying.
Finally, keyword candidate score is now to be scaled properly based on
how well they match the prefix. Previously they weren't penalized for
not matching well, so there were probably some situations where
keywords were ranked too high.
Updates golang/go#34009.
Change-Id: I0b659c00a8503cd72da28853dfe54fcb67f734ae
Reviewed-on: https://go-review.googlesource.com/c/tools/+/220503
Run-TryBot: Muir Manders <muir@mnd.rs>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
2020-02-21 21:55:54 -07:00
|
|
|
addKeywords(stdScore, DEFER, RETURN, FOR, GO, SWITCH, SELECT, IF, ELSE, VAR, CONST, GOTO, TYPE)
|
2019-09-20 14:01:33 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|