From 2db0265cb232de198930fbc1b52c1021eabe0fc9 Mon Sep 17 00:00:00 2001 From: pjw Date: Tue, 11 May 2021 07:33:51 -0400 Subject: [PATCH] internal/lsp: in semantic tokens, better distinguish between types and variables If A is a type, then in type B { A } it is a type, but in type C { A int } it is a variable (and similarly in function types). The old code got this wrong. Fixes: golang/go#46068 Change-Id: Ib7320914de81d2b7377214f53f99f4fea25e00fb Reviewed-on: https://go-review.googlesource.com/c/tools/+/318749 Run-TryBot: Peter Weinberger gopls-CI: kokoro TryBot-Result: Go Bot Trust: Peter Weinberger Reviewed-by: Robert Findley --- internal/lsp/semantic.go | 9 +++++++-- internal/lsp/testdata/semantic/README.md | 2 ++ internal/lsp/testdata/semantic/b.go | 9 +++++++++ internal/lsp/testdata/semantic/b.go.golden | 9 +++++++++ 4 files changed, 27 insertions(+), 2 deletions(-) create mode 100644 internal/lsp/testdata/semantic/README.md diff --git a/internal/lsp/semantic.go b/internal/lsp/semantic.go index b7746bf6eb5..8ef30ffb8b0 100644 --- a/internal/lsp/semantic.go +++ b/internal/lsp/semantic.go @@ -511,9 +511,14 @@ func (e *encoded) definitionFor(x *ast.Ident) (tokenType, []string) { // (type A func(b uint64)) (err error) // b and err should not be tokType, but tokVaraible // and in GenDecl/TpeSpec/StructType/FieldList/Field/Ident - // (type A struct{b uint64}) + // (type A struct{b uint64} + // but on type B struct{C}), C is a type, but is not being defined. fldm := e.stack[len(e.stack)-2] - if _, ok := fldm.(*ast.Field); ok { + if fld, ok := fldm.(*ast.Field); ok { + // if len(fld.names) == 0 this is a tokType, being used + if len(fld.Names) == 0 { + return tokType, nil + } return tokVariable, mods } return tokType, mods diff --git a/internal/lsp/testdata/semantic/README.md b/internal/lsp/testdata/semantic/README.md new file mode 100644 index 00000000000..00ec19af170 --- /dev/null +++ b/internal/lsp/testdata/semantic/README.md @@ -0,0 +1,2 @@ +The golden files are the output of `gopls semtok `, with `-- semantic --` +inserted as the first line (the spaces are mandatory) and an extra newline at the end. diff --git a/internal/lsp/testdata/semantic/b.go b/internal/lsp/testdata/semantic/b.go index e633f4e8d6f..a536f97bfe5 100644 --- a/internal/lsp/testdata/semantic/b.go +++ b/internal/lsp/testdata/semantic/b.go @@ -23,3 +23,12 @@ func weirⰀd() { /*😀*/ // comment multiline */ /* multiline */ +type AA int +type BB struct { + AA +} +type CC struct { + AA int +} +type D func(aa AA) (BB error) +type E func(AA) BB diff --git a/internal/lsp/testdata/semantic/b.go.golden b/internal/lsp/testdata/semantic/b.go.golden index 48be5ea196e..863a68cc8f2 100644 --- a/internal/lsp/testdata/semantic/b.go.golden +++ b/internal/lsp/testdata/semantic/b.go.golden @@ -24,4 +24,13 @@ /*⇒12,comment,[]*/multiline */ /*⇒2,comment,[]*//* /*⇒9,comment,[]*/multiline /*⇒2,comment,[]*/*/ +/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/AA /*⇒3,type,[defaultLibrary]*/int +/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/BB /*⇒6,keyword,[]*/struct { + /*⇒2,type,[]*/AA +} +/*⇒4,keyword,[]*/type /*⇒2,type,[definition]*/CC /*⇒6,keyword,[]*/struct { + /*⇒2,variable,[definition]*/AA /*⇒3,type,[defaultLibrary]*/int +} +/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/D /*⇒4,keyword,[]*/func(/*⇒2,variable,[definition]*/aa /*⇒2,type,[]*/AA) (/*⇒2,variable,[definition]*/BB /*⇒5,type,[]*/error) +/*⇒4,keyword,[]*/type /*⇒1,type,[definition]*/E /*⇒4,keyword,[]*/func(/*⇒2,type,[]*/AA) /*⇒2,type,[]*/BB