Skip to content

Commit

Permalink
gopls/internal/lsp: unify semanticTokens{Full,Range}
Browse files Browse the repository at this point in the history
...so that we needn't test them differently.

Before this CL, the max range check was only applied
in the full case.

Change-Id: I23fcfdda4f697ac321c12bd5c3fbafd7186fd8d4
Reviewed-on: https://go-review.googlesource.com/c/tools/+/541128
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Robert Findley <rfindley@google.com>
  • Loading branch information
adonovan committed Nov 10, 2023
1 parent 4479ae8 commit 4749c1b
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 52 deletions.
78 changes: 28 additions & 50 deletions gopls/internal/lsp/semantic.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,26 +38,10 @@ const maxFullFileSize int = 100000
// semDebug should NEVER be true in checked-in code
const semDebug = false

func (s *Server) semanticTokensFull(ctx context.Context, params *protocol.SemanticTokensParams) (*protocol.SemanticTokens, error) {
ctx, done := event.Start(ctx, "lsp.Server.semanticTokensFull", tag.URI.Of(params.TextDocument.URI))
func (s *Server) semanticTokens(ctx context.Context, td protocol.TextDocumentIdentifier, rng *protocol.Range) (*protocol.SemanticTokens, error) {
ctx, done := event.Start(ctx, "lsp.Server.semanticTokens", tag.URI.Of(td.URI))
defer done()

ret, err := s.computeSemanticTokens(ctx, params.TextDocument, nil)
return ret, err
}

func (s *Server) semanticTokensRange(ctx context.Context, params *protocol.SemanticTokensRangeParams) (*protocol.SemanticTokens, error) {
ctx, done := event.Start(ctx, "lsp.Server.semanticTokensRange", tag.URI.Of(params.TextDocument.URI))
defer done()

ret, err := s.computeSemanticTokens(ctx, params.TextDocument, &params.Range)
return ret, err
}

func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocumentIdentifier, rng *protocol.Range) (*protocol.SemanticTokens, error) {
ans := protocol.SemanticTokens{
Data: []uint32{},
}
snapshot, fh, ok, release, err := s.beginFileRequest(ctx, td.URI, source.UnknownKind)
defer release()
if !ok {
Expand All @@ -68,18 +52,19 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
// the client won't remember the wrong answer
return nil, fmt.Errorf("semantictokens are disabled")
}

kind := snapshot.FileKind(fh)
if kind == source.Tmpl {
// this is a little cumbersome to avoid both exporting 'encoded' and its methods
// and to avoid import cycles
e := &encoded{
ctx: ctx,
metadataSource: snapshot,
rng: rng,
tokTypes: snapshot.Options().SemanticTypes,
tokMods: snapshot.Options().SemanticMods,
}
add := func(line, start uint32, len uint32) {
// TODO(adonovan): don't ignore the rng restriction, if any.
e.add(line, start, len, tokMacro, nil)
}
data := func() []uint32 {
Expand All @@ -95,16 +80,30 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
return nil, err
}

if rng == nil && len(pgf.Src) > maxFullFileSize {
err := fmt.Errorf("semantic tokens: file %s too large for full (%d>%d)",
fh.URI().Filename(), len(pgf.Src), maxFullFileSize)
// Select range.
var start, end token.Pos
if rng != nil {
var err error
start, end, err = pgf.RangePos(*rng)
if err != nil {
return nil, fmt.Errorf("range span (%w) error for %s", err, pgf.File.Name)
}
} else {
tok := pgf.Tok
start, end = tok.Pos(0), tok.Pos(tok.Size()) // entire file
}
if int(end-start) > maxFullFileSize {
err := fmt.Errorf("semantic tokens: range %s too large (%d > %d)",
fh.URI().Filename(), end-start, maxFullFileSize)
return nil, err
}

e := &encoded{
ctx: ctx,
metadataSource: snapshot,
pgf: pgf,
rng: rng,
start: start,
end: end,
ti: pkg.GetTypesInfo(),
pkg: pkg,
fset: pkg.FileSet(),
Expand All @@ -113,16 +112,12 @@ func (s *Server) computeSemanticTokens(ctx context.Context, td protocol.TextDocu
noStrings: snapshot.Options().NoSemanticString,
noNumbers: snapshot.Options().NoSemanticNumber,
}
if err := e.init(); err != nil {
// e.init should never return an error, unless there's some
// seemingly impossible race condition
return nil, err
}
e.semantics()
ans.Data = e.Data()
// For delta requests, but we've never seen any.
ans.ResultID = fmt.Sprintf("%v", time.Now())
return &ans, nil
return &protocol.SemanticTokens{
Data: e.Data(),
// For delta requests, but we've never seen any.
ResultID: fmt.Sprintf("%v", time.Now()),
}, nil
}

func (e *encoded) semantics() {
Expand Down Expand Up @@ -224,13 +219,10 @@ type encoded struct {
metadataSource source.MetadataSource
tokTypes, tokMods []string
pgf *source.ParsedGoFile
rng *protocol.Range
start, end token.Pos // range of interest
ti *types.Info
pkg source.Package
fset *token.FileSet
// allowed starting and ending token.Pos, set by init
// used to avoid looking at declarations not in range
start, end token.Pos
// path from the root of the parse tree, used for debugging
stack []ast.Node
}
Expand Down Expand Up @@ -839,20 +831,6 @@ func (e *encoded) findKeyword(keyword string, start, end token.Pos) token.Pos {
return token.NoPos
}

func (e *encoded) init() error {
if e.rng != nil {
var err error
e.start, e.end, err = e.pgf.RangePos(*e.rng)
if err != nil {
return fmt.Errorf("range span (%w) error for %s", err, e.pgf.File.Name)
}
} else {
tok := e.pgf.Tok
e.start, e.end = tok.Pos(0), tok.Pos(tok.Size()) // entire file
}
return nil
}

func (e *encoded) Data() []uint32 {
// binary operators, at least, will be out of order
sort.Slice(e.items, func(i, j int) bool {
Expand Down
4 changes: 2 additions & 2 deletions gopls/internal/lsp/server_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 4749c1b

Please sign in to comment.