go/packages/packagestest: convert to the span library

Change-Id: Ib8984dd0828e3bb0b49eaa1604649300a4d54306
Reviewed-on: https://go-review.googlesource.com/c/tools/+/168900
Reviewed-by: Michael Matloob <matloob@golang.org>
This commit is contained in:
Ian Cottrell 2019-03-22 16:43:20 -04:00
parent c1a832b0ad
commit 5a8dccf5b4
4 changed files with 48 additions and 37 deletions

View File

@ -13,6 +13,7 @@ import (
"golang.org/x/tools/go/expect" "golang.org/x/tools/go/expect"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/span"
) )
const ( const (
@ -116,15 +117,14 @@ func (e *Exported) Expect(methods map[string]interface{}) error {
return nil return nil
} }
type Range struct { // Range is a type alias for span.Range for backwards compatability, prefer
Start token.Pos // using span.Range directly.
End token.Pos type Range = span.Range
}
// Mark adds a new marker to the known set. // Mark adds a new marker to the known set.
func (e *Exported) Mark(name string, r Range) { func (e *Exported) Mark(name string, r Range) {
if e.markers == nil { if e.markers == nil {
e.markers = make(map[string]Range) e.markers = make(map[string]span.Range)
} }
e.markers[name] = r e.markers[name] = r
} }
@ -166,7 +166,7 @@ func (e *Exported) getMarkers() error {
return nil return nil
} }
// set markers early so that we don't call getMarkers again from Expect // set markers early so that we don't call getMarkers again from Expect
e.markers = make(map[string]Range) e.markers = make(map[string]span.Range)
return e.Expect(map[string]interface{}{ return e.Expect(map[string]interface{}{
markMethod: e.Mark, markMethod: e.Mark,
}) })
@ -177,7 +177,8 @@ var (
identifierType = reflect.TypeOf(expect.Identifier("")) identifierType = reflect.TypeOf(expect.Identifier(""))
posType = reflect.TypeOf(token.Pos(0)) posType = reflect.TypeOf(token.Pos(0))
positionType = reflect.TypeOf(token.Position{}) positionType = reflect.TypeOf(token.Position{})
rangeType = reflect.TypeOf(Range{}) rangeType = reflect.TypeOf(span.Range{})
spanType = reflect.TypeOf(span.Span{})
fsetType = reflect.TypeOf((*token.FileSet)(nil)) fsetType = reflect.TypeOf((*token.FileSet)(nil))
regexType = reflect.TypeOf((*regexp.Regexp)(nil)) regexType = reflect.TypeOf((*regexp.Regexp)(nil))
exportedType = reflect.TypeOf((*Exported)(nil)) exportedType = reflect.TypeOf((*Exported)(nil))
@ -239,6 +240,18 @@ func (e *Exported) buildConverter(pt reflect.Type) (converter, error) {
} }
return reflect.ValueOf(r), remains, nil return reflect.ValueOf(r), remains, nil
}, nil }, nil
case pt == spanType:
return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) {
r, remains, err := e.rangeConverter(n, args)
if err != nil {
return reflect.Value{}, nil, err
}
spn, err := r.Span()
if err != nil {
return reflect.Value{}, nil, err
}
return reflect.ValueOf(spn), remains, nil
}, nil
case pt == identifierType: case pt == identifierType:
return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) { return func(n *expect.Note, args []interface{}) (reflect.Value, []interface{}, error) {
if len(args) < 1 { if len(args) < 1 {
@ -340,9 +353,9 @@ func (e *Exported) buildConverter(pt reflect.Type) (converter, error) {
} }
} }
func (e *Exported) rangeConverter(n *expect.Note, args []interface{}) (Range, []interface{}, error) { func (e *Exported) rangeConverter(n *expect.Note, args []interface{}) (span.Range, []interface{}, error) {
if len(args) < 1 { if len(args) < 1 {
return Range{}, nil, fmt.Errorf("missing argument") return span.Range{}, nil, fmt.Errorf("missing argument")
} }
arg := args[0] arg := args[0]
args = args[1:] args = args[1:]
@ -354,34 +367,34 @@ func (e *Exported) rangeConverter(n *expect.Note, args []interface{}) (Range, []
// end of file identifier, look up the current file // end of file identifier, look up the current file
f := e.fset.File(n.Pos) f := e.fset.File(n.Pos)
eof := f.Pos(f.Size()) eof := f.Pos(f.Size())
return Range{Start: eof, End: token.NoPos}, args, nil return span.Range{FileSet: e.fset, Start: eof, End: token.NoPos}, args, nil
default: default:
// look up an marker by name // look up an marker by name
mark, ok := e.markers[string(arg)] mark, ok := e.markers[string(arg)]
if !ok { if !ok {
return Range{}, nil, fmt.Errorf("cannot find marker %v", arg) return span.Range{}, nil, fmt.Errorf("cannot find marker %v", arg)
} }
return mark, args, nil return mark, args, nil
} }
case string: case string:
start, end, err := expect.MatchBefore(e.fset, e.FileContents, n.Pos, arg) start, end, err := expect.MatchBefore(e.fset, e.FileContents, n.Pos, arg)
if err != nil { if err != nil {
return Range{}, nil, err return span.Range{}, nil, err
} }
if start == token.NoPos { if start == token.NoPos {
return Range{}, nil, fmt.Errorf("%v: pattern %s did not match", e.fset.Position(n.Pos), arg) return span.Range{}, nil, fmt.Errorf("%v: pattern %s did not match", e.fset.Position(n.Pos), arg)
} }
return Range{Start: start, End: end}, args, nil return span.Range{FileSet: e.fset, Start: start, End: end}, args, nil
case *regexp.Regexp: case *regexp.Regexp:
start, end, err := expect.MatchBefore(e.fset, e.FileContents, n.Pos, arg) start, end, err := expect.MatchBefore(e.fset, e.FileContents, n.Pos, arg)
if err != nil { if err != nil {
return Range{}, nil, err return span.Range{}, nil, err
} }
if start == token.NoPos { if start == token.NoPos {
return Range{}, nil, fmt.Errorf("%v: pattern %s did not match", e.fset.Position(n.Pos), arg) return span.Range{}, nil, fmt.Errorf("%v: pattern %s did not match", e.fset.Position(n.Pos), arg)
} }
return Range{Start: start, End: end}, args, nil return span.Range{FileSet: e.fset, Start: start, End: end}, args, nil
default: default:
return Range{}, nil, fmt.Errorf("cannot convert %v to pos", arg) return span.Range{}, nil, fmt.Errorf("cannot convert %v to pos", arg)
} }
} }

View File

@ -10,6 +10,7 @@ import (
"golang.org/x/tools/go/expect" "golang.org/x/tools/go/expect"
"golang.org/x/tools/go/packages/packagestest" "golang.org/x/tools/go/packages/packagestest"
"golang.org/x/tools/internal/span"
) )
func TestExpect(t *testing.T) { func TestExpect(t *testing.T) {
@ -42,7 +43,7 @@ func TestExpect(t *testing.T) {
} }
}, },
"directNote": func(n *expect.Note) {}, "directNote": func(n *expect.Note) {},
"range": func(r packagestest.Range) { "range": func(r span.Range) {
if r.Start == token.NoPos || r.Start == 0 { if r.Start == token.NoPos || r.Start == 0 {
t.Errorf("Range had no valid starting position") t.Errorf("Range had no valid starting position")
} }

View File

@ -24,6 +24,7 @@ import (
"golang.org/x/tools/go/expect" "golang.org/x/tools/go/expect"
"golang.org/x/tools/go/packages" "golang.org/x/tools/go/packages"
"golang.org/x/tools/internal/span"
) )
var ( var (
@ -66,7 +67,7 @@ type Exported struct {
written map[string]map[string]string // the full set of exported files written map[string]map[string]string // the full set of exported files
fset *token.FileSet // The file set used when parsing expectations fset *token.FileSet // The file set used when parsing expectations
notes []*expect.Note // The list of expectations extracted from go source files notes []*expect.Note // The list of expectations extracted from go source files
markers map[string]Range // The set of markers extracted from go source files markers map[string]span.Range // The set of markers extracted from go source files
} }
// Exporter implementations are responsible for converting from the generic description of some // Exporter implementations are responsible for converting from the generic description of some

View File

@ -8,7 +8,6 @@ import (
"context" "context"
"flag" "flag"
"fmt" "fmt"
"go/token"
"io/ioutil" "io/ioutil"
"os" "os"
"os/exec" "os/exec"
@ -60,46 +59,43 @@ func TestDefinition(t *testing.T) {
defer exported.Cleanup() defer exported.Cleanup()
count := 0 count := 0
if err := exported.Expect(map[string]interface{}{ if err := exported.Expect(map[string]interface{}{
"definition": func(fset *token.FileSet, src token.Pos, flags string, def packagestest.Range, match string) { "definition": func(src span.Span, flags string, def span.Span, match string) {
count++ count++
args := []string{"query"} args := []string{"query"}
if flags != "" { if flags != "" {
args = append(args, strings.Split(flags, " ")...) args = append(args, strings.Split(flags, " ")...)
} }
args = append(args, "definition") args = append(args, "definition")
f := fset.File(src) args = append(args, fmt.Sprint(src))
spn := span.New(span.FileURI(f.Name()), span.NewPoint(0, 0, f.Offset(src)), span.Point{})
args = append(args, fmt.Sprint(spn))
app := &cmd.Application{} app := &cmd.Application{}
app.Config = *exported.Config app.Config = *exported.Config
got := captureStdOut(t, func() { got := captureStdOut(t, func() {
tool.Main(context.Background(), app, args) tool.Main(context.Background(), app, args)
}) })
start := fset.Position(def.Start)
end := fset.Position(def.End)
expect := os.Expand(match, func(name string) string { expect := os.Expand(match, func(name string) string {
switch name { switch name {
case "file": case "file":
return start.Filename fname, _ := def.URI().Filename()
return fname
case "efile": case "efile":
qfile := strconv.Quote(start.Filename) fname, _ := def.URI().Filename()
qfile := strconv.Quote(fname)
return qfile[1 : len(qfile)-1] return qfile[1 : len(qfile)-1]
case "euri": case "euri":
uri := span.FileURI(start.Filename) quri := strconv.Quote(string(def.URI()))
quri := strconv.Quote(string(uri))
return quri[1 : len(quri)-1] return quri[1 : len(quri)-1]
case "line": case "line":
return fmt.Sprint(start.Line) return fmt.Sprint(def.Start().Line())
case "col": case "col":
return fmt.Sprint(start.Column) return fmt.Sprint(def.Start().Column())
case "offset": case "offset":
return fmt.Sprint(start.Offset) return fmt.Sprint(def.Start().Offset())
case "eline": case "eline":
return fmt.Sprint(end.Line) return fmt.Sprint(def.End().Line())
case "ecol": case "ecol":
return fmt.Sprint(end.Column) return fmt.Sprint(def.End().Column())
case "eoffset": case "eoffset":
return fmt.Sprint(end.Offset) return fmt.Sprint(def.End().Offset())
default: default:
return name return name
} }