// Copyright 2023 The Go Authors. All rights reserved. // Use of this source code is governed by a BSD-style // license that can be found in the LICENSE file. // package tokeninternal provides access to some internal features of the token // package. package tokeninternal import ( "go/token" "sync" "unsafe" ) // GetLines returns the table of line-start offsets from a token.File. func GetLines(file *token.File) []int { // token.File has a Lines method on Go 1.21 and later. if file, ok := (interface{})(file).(interface{ Lines() []int }); ok { return file.Lines() } // This declaration must match that of token.File. // This creates a risk of dependency skew. // For now we check that the size of the two // declarations is the same, on the (fragile) assumption // that future changes would add fields. type tokenFile119 struct { _ string _ int _ int mu sync.Mutex // we're not complete monsters lines []int _ []struct{} } type tokenFile118 struct { _ *token.FileSet // deleted in go1.19 tokenFile119 } type uP = unsafe.Pointer switch unsafe.Sizeof(*file) { case unsafe.Sizeof(tokenFile118{}): var ptr *tokenFile118 *(*uP)(uP(&ptr)) = uP(file) ptr.mu.Lock() defer ptr.mu.Unlock() return ptr.lines case unsafe.Sizeof(tokenFile119{}): var ptr *tokenFile119 *(*uP)(uP(&ptr)) = uP(file) ptr.mu.Lock() defer ptr.mu.Unlock() return ptr.lines default: panic("unexpected token.File size") } }