@@ -12,6 +12,7 @@ import (
1212 "go/token"
1313 "go/types"
1414 "log"
15+ "path/filepath"
1516 "sort"
1617 "strings"
1718 "time"
@@ -93,7 +94,7 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
9394 if err != nil {
9495 return nil , err
9596 }
96- // don't return errors on pgf.ParseErr. Do what we can.
97+ // ignore pgf.ParseErr. Do what we can.
9798 if rng == nil && len (pgf .Src ) > maxFullFileSize {
9899 err := fmt .Errorf ("semantic tokens: file %s too large for full (%d>%d)" ,
99100 fh .URI ().Filename (), len (pgf .Src ), maxFullFileSize )
@@ -122,6 +123,7 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
122123
123124func (e * encoded ) semantics () {
124125 f := e .pgf .File
126+ // may not be in range, but harmless
125127 e .token (f .Package , len ("package" ), tokKeyword , nil )
126128 e .token (f .Name .NamePos , len (f .Name .Name ), tokNamespace , nil )
127129 inspect := func (n ast.Node ) bool {
@@ -166,8 +168,11 @@ const (
166168)
167169
168170func (e * encoded ) token (start token.Pos , leng int , typ tokenType , mods []string ) {
169- if start == 0 {
170- e .unexpected ("token at token.NoPos" )
171+
172+ if start == token .NoPos {
173+ // This is not worth reporting
174+ //e.unexpected("token at token.NoPos")
175+ return
171176 }
172177 if start >= e .end || start + token .Pos (leng ) <= e .start {
173178 return
@@ -186,10 +191,7 @@ func (e *encoded) token(start token.Pos, leng int, typ tokenType, mods []string)
186191 return
187192 }
188193 if lspRange .End .Line != lspRange .Start .Line {
189- // abrupt end of file, without \n. TODO(pjw): fix?
190- pos := e .fset .PositionFor (start , false )
191- msg := fmt .Sprintf ("token at %s:%d.%d overflows" , pos .Filename , pos .Line , pos .Column )
192- event .Log (e .ctx , msg )
194+ // this happens if users are typing at the end of the file, but report nothing
193195 return
194196 }
195197 // token is all on one line
@@ -236,12 +238,22 @@ func (e *encoded) strStack() string {
236238 if len (e .stack ) > 0 {
237239 loc := e .stack [len (e .stack )- 1 ].Pos ()
238240 add := e .pgf .Tok .PositionFor (loc , false )
239- msg = append (msg , fmt .Sprintf ("(line:%d,col:%d)" , add .Line , add .Column ))
241+ nm := filepath .Base (add .Filename )
242+ msg = append (msg , fmt .Sprintf ("(%s:%d,col:%d)" , nm , add .Line , add .Column ))
240243 }
241244 msg = append (msg , "]" )
242245 return strings .Join (msg , " " )
243246}
244247
248+ func (e * encoded ) srcLine (x ast.Node ) string {
249+ file := e .pgf .Tok
250+ line := file .Line (x .Pos ())
251+ start := file .Offset (file .LineStart (line ))
252+ end := file .Offset (file .LineStart (line + 1 )) // and hope it's not the last line of the file
253+ ans := e .pgf .Src [start : end - 1 ]
254+ return string (ans )
255+ }
256+
245257func (e * encoded ) inspector (n ast.Node ) bool {
246258 pop := func () {
247259 e .stack = e .stack [:len (e .stack )- 1 ]
@@ -409,6 +421,26 @@ func (e *encoded) ident(x *ast.Ident) {
409421 use := e .ti .Uses [x ]
410422 switch y := use .(type ) {
411423 case nil :
424+ // In this position we think the identifier is either a function or a variable
425+ // and it is possible that it is being defined. The decision has to be made based
426+ // on where we are in the parse tree (and all that's known is the parse stack).
427+ // The present logic is inadequate, and will be fixed in the next CL:
428+ // ExprStmt CallExpr Ident: var [x in a(x)]
429+ // ExprStmt CallExpr Ident: function [f()]
430+ // CallExpr TypeAssertExpr Ident: type [so not variable nor function]
431+ log .SetFlags (log .Lshortfile )
432+ log .Printf ("%s %s%q" , x .Name , e .strStack (), e .srcLine (x ))
433+ if len (e .stack ) >= 3 {
434+ n := len (e .stack ) - 1
435+ if _ , ok := e .stack [n - 1 ].(* ast.SelectorExpr ); ok {
436+ if _ , ok = e .stack [n - 2 ].(* ast.CallExpr ); ok {
437+ log .Print ("function" )
438+ e .token (x .NamePos , len (x .Name ), tokFunction , nil )
439+ break
440+ }
441+ }
442+ }
443+ log .Print ("var def" )
412444 e .token (x .NamePos , len (x .Name ), tokVariable , []string {"definition" })
413445 case * types.Builtin :
414446 e .token (x .NamePos , len (x .Name ), tokFunction , []string {"defaultLibrary" })
@@ -642,16 +674,21 @@ func (e *encoded) importSpec(d *ast.ImportSpec) {
642674 }
643675 // and fall through for _
644676 }
645- if d .Path .Value == "" {
677+ val := d .Path .Value
678+ if len (val ) < 2 || val [0 ] != '"' || val [len (val )- 1 ] != '"' {
679+ // avoid panics on imports without a properly quoted string
646680 return
647681 }
648- nm := d . Path . Value [1 : len (d . Path . Value )- 1 ] // trailing "
682+ nm := val [1 : len (val )- 1 ] // remove surrounding "s
649683 v := strings .LastIndex (nm , "/" )
650684 if v != - 1 {
685+ // in import "lib/math", 'math' is the package name
651686 nm = nm [v + 1 :]
652687 }
653688 start := d .Path .End () - token .Pos (1 + len (nm ))
654689 e .token (start , len (nm ), tokNamespace , nil )
690+ // There may be more cases, as import strings are implementation defined.
691+ // (E.g., module a.b.c (without a /), the 'a' should be tokNamespace, if we cared.)
655692}
656693
657694// log unexpected state
0 commit comments