tools/gopls: argument in function bodies marked as parameter by semantic tokens

In func f(x int) int {return x;} the second x used to be marked as a
variable, but now is marked as a parameter, visually tying it to its
definition.

Fixes golang/go#56257

Change-Id: I8aa506b1ddff5ed9a3d2716d48c64521bdea0fd5
Reviewed-on: https://go-review.googlesource.com/c/tools/+/445095
Reviewed-by: Robert Findley <rfindley@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Peter Weinberger <pjw@google.com>
gopls-CI: kokoro <noreply+kokoro@google.com>
This commit is contained in:
pjw 2022-10-23 15:54:03 -04:00 committed by Peter Weinberger
parent 3e1371fd13
commit de675d5479
2 changed files with 33 additions and 4 deletions

View File

@ -526,9 +526,14 @@ func (e *encoded) ident(x *ast.Ident) {
tok(x.Pos(), len(x.Name), tokFunction, nil)
} else if _, ok := y.Type().(*typeparams.TypeParam); ok {
tok(x.Pos(), len(x.Name), tokTypeParam, nil)
} else if e.isParam(use.Pos()) {
// variable, unless use.pos is the pos of a Field in an ancestor FuncDecl
// or FuncLit and then it's a parameter
tok(x.Pos(), len(x.Name), tokParameter, nil)
} else {
tok(x.Pos(), len(x.Name), tokVariable, nil)
}
default:
// can't happen
if use == nil {
@ -543,6 +548,30 @@ func (e *encoded) ident(x *ast.Ident) {
}
}
func (e *encoded) isParam(pos token.Pos) bool {
for i := len(e.stack) - 1; i >= 0; i-- {
switch n := e.stack[i].(type) {
case *ast.FuncDecl:
for _, f := range n.Type.Params.List {
for _, id := range f.Names {
if id.Pos() == pos {
return true
}
}
}
case *ast.FuncLit:
for _, f := range n.Type.Params.List {
for _, id := range f.Names {
if id.Pos() == pos {
return true
}
}
}
}
}
return false
}
func isSignature(use types.Object) bool {
if true {
return false //PJW: fix after generics seem ok
@ -640,7 +669,7 @@ func (e *encoded) unkIdent(x *ast.Ident) (tokenType, []string) {
if nd.Tok != token.DEFINE {
def = nil
}
return tokVariable, def
return tokVariable, def // '_' in _ = ...
}
}
// RHS, = x

View File

@ -65,7 +65,7 @@
/*⇒2,variable,[definition]*/ff /*⇒2,operator,[]*/:= /*⇒4,keyword,[]*/func() {}
/*⇒5,keyword,[]*/defer /*⇒2,variable,[]*/ff()
/*⇒2,keyword,[]*/go /*⇒3,namespace,[]*/utf./*⇒9,function,[]*/RuneCount(/*⇒2,string,[]*/"")
/*⇒2,keyword,[]*/go /*⇒4,namespace,[]*/utf8./*⇒9,function,[]*/RuneCount(/*⇒2,variable,[]*/vv.(/*⇒6,type,[]*/string))
/*⇒2,keyword,[]*/go /*⇒4,namespace,[]*/utf8./*⇒9,function,[]*/RuneCount(/*⇒2,parameter,[]*/vv.(/*⇒6,type,[]*/string))
/*⇒2,keyword,[]*/if /*⇒4,variable,[readonly]*/true {
} /*⇒4,keyword,[]*/else {
}
@ -73,9 +73,9 @@
/*⇒3,keyword,[]*/for /*⇒1,variable,[definition]*/i /*⇒2,operator,[]*/:= /*⇒1,number,[]*/0; /*⇒1,variable,[]*/i /*⇒1,operator,[]*/< /*⇒2,number,[]*/10; {
/*⇒5,keyword,[]*/break Never
}
_, /*⇒2,variable,[definition]*/ok /*⇒2,operator,[]*/:= /*⇒2,variable,[]*/vv[/*⇒1,number,[]*/0].(/*⇒1,type,[]*/A)
_, /*⇒2,variable,[definition]*/ok /*⇒2,operator,[]*/:= /*⇒2,parameter,[]*/vv[/*⇒1,number,[]*/0].(/*⇒1,type,[]*/A)
/*⇒2,keyword,[]*/if /*⇒1,operator,[]*/!/*⇒2,variable,[]*/ok {
/*⇒6,keyword,[]*/switch /*⇒1,variable,[definition]*/x /*⇒2,operator,[]*/:= /*⇒2,variable,[]*/vv[/*⇒1,number,[]*/0].(/*⇒4,keyword,[]*/type) {
/*⇒6,keyword,[]*/switch /*⇒1,variable,[definition]*/x /*⇒2,operator,[]*/:= /*⇒2,parameter,[]*/vv[/*⇒1,number,[]*/0].(/*⇒4,keyword,[]*/type) {
}
/*⇒4,keyword,[]*/goto Never
}