github.com/jhump/golang-x-tools@v0.0.0-20220218190644-4958d6d39439/internal/lsp/source/offset_test.go (about)

     1  // Copyright 2021 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 source_test
     6  
     7  import (
     8  	"go/token"
     9  	"go/types"
    10  	"testing"
    11  
    12  	"github.com/jhump/golang-x-tools/go/packages"
    13  )
    14  
    15  // This test reports any unexpected uses of (*go/token.File).Offset within
    16  // the gopls codebase to ensure that we don't check in more code that is prone
    17  // to panicking. All calls to (*go/token.File).Offset should be replaced with
    18  // calls to source.Offset.
    19  func TestTokenOffset(t *testing.T) {
    20  	fset := token.NewFileSet()
    21  	pkgs, err := packages.Load(&packages.Config{
    22  		Fset: fset,
    23  		Mode: packages.NeedName | packages.NeedModule | packages.NeedCompiledGoFiles | packages.NeedTypes | packages.NeedTypesInfo | packages.NeedSyntax | packages.NeedImports | packages.NeedDeps,
    24  	}, "go/token", "github.com/jhump/golang-x-tools/internal/lsp/...", "github.com/jhump/golang-x-tools/gopls/...")
    25  	if err != nil {
    26  		t.Fatal(err)
    27  	}
    28  	var tokPkg *packages.Package
    29  	for _, pkg := range pkgs {
    30  		if pkg.PkgPath == "go/token" {
    31  			tokPkg = pkg
    32  			break
    33  		}
    34  	}
    35  	typname, ok := tokPkg.Types.Scope().Lookup("File").(*types.TypeName)
    36  	if !ok {
    37  		t.Fatal("expected go/token.File typename, got none")
    38  	}
    39  	named, ok := typname.Type().(*types.Named)
    40  	if !ok {
    41  		t.Fatalf("expected named type, got %T", typname.Type)
    42  	}
    43  	var offset *types.Func
    44  	for i := 0; i < named.NumMethods(); i++ {
    45  		meth := named.Method(i)
    46  		if meth.Name() == "Offset" {
    47  			offset = meth
    48  			break
    49  		}
    50  	}
    51  	for _, pkg := range pkgs {
    52  		for ident, obj := range pkg.TypesInfo.Uses {
    53  			if ident.Name != "Offset" {
    54  				continue
    55  			}
    56  			if pkg.PkgPath == "go/token" {
    57  				continue
    58  			}
    59  			if !types.Identical(offset.Type(), obj.Type()) {
    60  				continue
    61  			}
    62  			// The only permitted use is in golang.org/x/tools/internal/lsp/source.Offset,
    63  			// so check the enclosing function.
    64  			sourceOffset := pkg.Types.Scope().Lookup("Offset").(*types.Func)
    65  			if sourceOffset.Pos() <= ident.Pos() && ident.Pos() <= sourceOffset.Scope().End() {
    66  				continue // accepted usage
    67  			}
    68  			t.Errorf(`%s: Unexpected use of (*go/token.File).Offset. Please use golang.org/x/tools/internal/lsp/source.Offset instead.`, fset.Position(ident.Pos()))
    69  		}
    70  	}
    71  }