golang.org/x/tools/gopls@v0.15.3/internal/protocol/semtok/semtok.go (about) 1 // Copyright 2024 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // The semtok package provides an encoder for LSP's semantic tokens. 6 package semtok 7 8 import "sort" 9 10 // A Token provides the extent and semantics of a token. 11 type Token struct { 12 Line, Start uint32 13 Len uint32 14 Type TokenType 15 Modifiers []string 16 } 17 18 type TokenType string 19 20 const ( 21 TokNamespace TokenType = "namespace" 22 TokType TokenType = "type" 23 TokInterface TokenType = "interface" 24 TokTypeParam TokenType = "typeParameter" 25 TokParameter TokenType = "parameter" 26 TokVariable TokenType = "variable" 27 TokMethod TokenType = "method" 28 TokFunction TokenType = "function" 29 TokKeyword TokenType = "keyword" 30 TokComment TokenType = "comment" 31 TokString TokenType = "string" 32 TokNumber TokenType = "number" 33 TokOperator TokenType = "operator" 34 TokMacro TokenType = "macro" // for templates 35 ) 36 37 // Encode returns the LSP encoding of a sequence of tokens. 38 // The noStrings, noNumbers options cause strings, numbers to be skipped. 39 // The lists of types and modifiers determines the bitfield encoding. 40 func Encode( 41 tokens []Token, 42 noStrings, noNumbers bool, 43 types, modifiers []string) []uint32 { 44 45 // binary operators, at least, will be out of order 46 sort.Slice(tokens, func(i, j int) bool { 47 if tokens[i].Line != tokens[j].Line { 48 return tokens[i].Line < tokens[j].Line 49 } 50 return tokens[i].Start < tokens[j].Start 51 }) 52 53 typeMap := make(map[TokenType]int) 54 for i, t := range types { 55 typeMap[TokenType(t)] = i 56 } 57 58 modMap := make(map[string]int) 59 for i, m := range modifiers { 60 modMap[m] = 1 << uint(i) // go 1.12 compatibility 61 } 62 63 // each semantic token needs five values 64 // (see Integer Encoding for Tokens in the LSP spec) 65 x := make([]uint32, 5*len(tokens)) 66 var j int 67 var last Token 68 for i := 0; i < len(tokens); i++ { 69 item := tokens[i] 70 typ, ok := typeMap[item.Type] 71 if !ok { 72 continue // client doesn't want typeStr 73 } 74 if item.Type == TokString && noStrings { 75 continue 76 } 77 if item.Type == TokNumber && noNumbers { 78 continue 79 } 80 if j == 0 { 81 x[0] = tokens[0].Line 82 } else { 83 x[j] = item.Line - last.Line 84 } 85 x[j+1] = item.Start 86 if j > 0 && x[j] == 0 { 87 x[j+1] = item.Start - last.Start 88 } 89 x[j+2] = item.Len 90 x[j+3] = uint32(typ) 91 mask := 0 92 for _, s := range item.Modifiers { 93 // modMap[s] is 0 if the client doesn't want this modifier 94 mask |= modMap[s] 95 } 96 x[j+4] = uint32(mask) 97 j += 5 98 last = item 99 } 100 return x[:j] 101 }