tokeninternal.go (1475B)
1 // Copyright 2023 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 // package tokeninternal provides access to some internal features of the token 6 // package. 7 package tokeninternal 8 9 import ( 10 "go/token" 11 "sync" 12 "unsafe" 13 ) 14 15 // GetLines returns the table of line-start offsets from a token.File. 16 func GetLines(file *token.File) []int { 17 // token.File has a Lines method on Go 1.21 and later. 18 if file, ok := (interface{})(file).(interface{ Lines() []int }); ok { 19 return file.Lines() 20 } 21 22 // This declaration must match that of token.File. 23 // This creates a risk of dependency skew. 24 // For now we check that the size of the two 25 // declarations is the same, on the (fragile) assumption 26 // that future changes would add fields. 27 type tokenFile119 struct { 28 _ string 29 _ int 30 _ int 31 mu sync.Mutex // we're not complete monsters 32 lines []int 33 _ []struct{} 34 } 35 type tokenFile118 struct { 36 _ *token.FileSet // deleted in go1.19 37 tokenFile119 38 } 39 40 type uP = unsafe.Pointer 41 switch unsafe.Sizeof(*file) { 42 case unsafe.Sizeof(tokenFile118{}): 43 var ptr *tokenFile118 44 *(*uP)(uP(&ptr)) = uP(file) 45 ptr.mu.Lock() 46 defer ptr.mu.Unlock() 47 return ptr.lines 48 49 case unsafe.Sizeof(tokenFile119{}): 50 var ptr *tokenFile119 51 *(*uP)(uP(&ptr)) = uP(file) 52 ptr.mu.Lock() 53 defer ptr.mu.Unlock() 54 return ptr.lines 55 56 default: 57 panic("unexpected token.File size") 58 } 59 }