本文整理汇总了Golang中golang.org/x/tools/go/ast/astutil.PathEnclosingInterval函数的典型用法代码示例。如果您正苦于以下问题:Golang PathEnclosingInterval函数的具体用法?Golang PathEnclosingInterval怎么用?Golang PathEnclosingInterval使用的例子?那么恭喜您, 这里精选的函数代码示例或许可以为您提供帮助。
在下文中一共展示了PathEnclosingInterval函数的13个代码示例,这些例子默认根据受欢迎程度排序。您可以为喜欢或者感觉有用的代码点赞,您的评价将有助于系统推荐出更棒的Golang代码示例。
示例1: fastQueryPos
// fastQueryPos parses the position string and returns a queryPos.
// It parses only a single file and does not run the type checker.
func fastQueryPos(ctxt *build.Context, pos string) (*queryPos, error) {
filename, startOffset, endOffset, err := parsePos(pos)
if err != nil {
return nil, err
}
// Parse the file, opening it the file via the build.Context
// so that we observe the effects of the -modified flag.
fset := token.NewFileSet()
cwd, _ := os.Getwd()
f, err := buildutil.ParseFile(fset, ctxt, nil, cwd, filename, parser.Mode(0))
// ParseFile usually returns a partial file along with an error.
// Only fail if there is no file.
if f == nil {
return nil, err
}
if !f.Pos().IsValid() {
return nil, fmt.Errorf("%s is not a Go source file", filename)
}
start, end, err := fileOffsetToPos(fset.File(f.Pos()), startOffset, endOffset)
if err != nil {
return nil, err
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if path == nil {
return nil, fmt.Errorf("no syntax here")
}
return &queryPos{fset, start, end, path, exact, nil}, nil
}
示例2: fastQueryPos
// fastQueryPos parses the position string and returns a queryPos.
// It parses only a single file and does not run the type checker.
func fastQueryPos(pos string) (*queryPos, error) {
filename, startOffset, endOffset, err := parsePos(pos)
if err != nil {
return nil, err
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, filename, nil, 0)
// ParseFile usually returns a partial file along with an error.
// Only fail if there is no file.
if f == nil {
return nil, err
}
start, end, err := fileOffsetToPos(fset.File(f.Pos()), startOffset, endOffset)
if err != nil {
return nil, err
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if path == nil {
return nil, fmt.Errorf("no syntax here")
}
return &queryPos{fset, start, end, path, exact, nil}, nil
}
示例3: findNodeChain
func findNodeChain(f *ast.File, pos token.Pos) []ast.Node {
defer func() {
if r := recover(); r != nil {
lg("findnodechain recovered r=%v", r)
fail()
}
}()
chain, _ := astutil.PathEnclosingInterval(f, pos, pos+1)
return chain
}
示例4: PathEnclosingInterval
// PathEnclosingInterval returns the PackageInfo and ast.Node that
// contain source interval [start, end), and all the node's ancestors
// up to the AST root. It searches all ast.Files of all packages in prog.
// exact is defined as for astutil.PathEnclosingInterval.
//
// The zero value is returned if not found.
//
func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
for _, info := range prog.AllPackages {
for _, f := range info.Files {
if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
continue
}
if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
return info, path, exact
}
}
}
return nil, nil, false
}
示例5: TestPathEnclosingInterval_Paths
func TestPathEnclosingInterval_Paths(t *testing.T) {
// For these tests, we check only the path of the enclosing
// node, but not its complete text because it's often quite
// large when !exact.
tests := []struct {
substr string // first occurrence of this string indicates interval
path string // the pathToString(),exact of the expected path
}{
{"// add",
"[BlockStmt FuncDecl File],false"},
{"(x + y",
"[ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
{"x +",
"[BinaryExpr ParenExpr AssignStmt BlockStmt FuncDecl File],false"},
{"z := (x",
"[AssignStmt BlockStmt FuncDecl File],false"},
{"func f",
"[FuncDecl File],false"},
{"func f()",
"[FuncDecl File],false"},
{" f()",
"[FuncDecl File],false"},
{"() {}",
"[FuncDecl File],false"},
{"// Hello",
"[File],false"},
{" f",
"[Ident FuncDecl File],true"},
{"func ",
"[FuncDecl File],true"},
{"mai",
"[Ident File],true"},
{"f() // NB",
"[CallExpr ExprStmt BlockStmt FuncDecl File],true"},
}
for _, test := range tests {
f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
if f == nil {
continue
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if got := fmt.Sprintf("%s,%v", pathToString(path), exact); got != test.path {
t.Errorf("PathEnclosingInterval(%q): got %q, want %q",
test.substr, got, test.path)
continue
}
}
}
示例6: PathEnclosingInterval
// PathEnclosingInterval returns the PackageInfo and ast.Node that
// contain source interval [start, end), and all the node's ancestors
// up to the AST root. It searches all ast.Files of all packages in prog.
// exact is defined as for astutil.PathEnclosingInterval.
//
// The zero value is returned if not found.
//
func (prog *Program) PathEnclosingInterval(start, end token.Pos) (pkg *PackageInfo, path []ast.Node, exact bool) {
for _, info := range prog.AllPackages {
for _, f := range info.Files {
if f.Pos() == token.NoPos {
// This can happen if the parser saw
// too many errors and bailed out.
// (Use parser.AllErrors to prevent that.)
continue
}
if !tokenFileContainsPos(prog.Fset.File(f.Pos()), start) {
continue
}
if path, exact := astutil.PathEnclosingInterval(f, start, end); path != nil {
return info, path, exact
}
}
}
return nil, nil, false
}
示例7: fastQueryPos
// fastQueryPos parses the position string and returns a queryPos.
// It parses only a single file and does not run the type checker.
func fastQueryPos(pos string) (*queryPos, error) {
filename, startOffset, endOffset, err := parsePos(pos)
if err != nil {
return nil, err
}
fset := token.NewFileSet()
f, err := parser.ParseFile(fset, filename, nil, 0)
if err != nil {
return nil, err
}
start, end, err := fileOffsetToPos(fset.File(f.Pos()), startOffset, endOffset)
if err != nil {
return nil, err
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if path == nil {
return nil, fmt.Errorf("no syntax here")
}
return &queryPos{fset, start, end, path, exact, nil}, nil
}
示例8: TestEnclosingFunction
func TestEnclosingFunction(t *testing.T) {
tests := []struct {
input string // the input file
substr string // first occurrence of this string denotes interval
fn string // name of expected containing function
}{
// We use distinctive numbers as syntactic landmarks.
// Ordinary function:
{`package main
func f() { println(1003) }`,
"100", "main.f"},
// Methods:
{`package main
type T int
func (t T) f() { println(200) }`,
"200", "(main.T).f"},
// Function literal:
{`package main
func f() { println(func() { print(300) }) }`,
"300", "main.f$1"},
// Doubly nested
{`package main
func f() { println(func() { print(func() { print(350) })})}`,
"350", "main.f$1$1"},
// Implicit init for package-level var initializer.
{"package main; var a = 400", "400", "main.init"},
// No code for constants:
{"package main; const a = 500", "500", "(none)"},
// Explicit init()
{"package main; func init() { println(600) }", "600", "main.init#1"},
// Multiple explicit init functions:
{`package main
func init() { println("foo") }
func init() { println(800) }`,
"800", "main.init#2"},
// init() containing FuncLit.
{`package main
func init() { println(func(){print(900)}) }`,
"900", "main.init#1$1"},
}
for _, test := range tests {
conf := loader.Config{Fset: token.NewFileSet()}
f, start, end := findInterval(t, conf.Fset, test.input, test.substr)
if f == nil {
continue
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if !exact {
t.Errorf("EnclosingFunction(%q) not exact", test.substr)
continue
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
continue
}
prog := ssautil.CreateProgram(iprog, 0)
pkg := prog.Package(iprog.Created[0].Pkg)
pkg.Build()
name := "(none)"
fn := ssa.EnclosingFunction(pkg, path)
if fn != nil {
name = fn.String()
}
if name != test.fn {
t.Errorf("EnclosingFunction(%q in %q) got %s, want %s",
test.substr, test.input, name, test.fn)
continue
}
// While we're here: test HasEnclosingFunction.
if has := ssa.HasEnclosingFunction(pkg, path); has != (fn != nil) {
t.Errorf("HasEnclosingFunction(%q in %q) got %v, want %v",
test.substr, test.input, has, fn != nil)
continue
}
}
}
示例9: TestObjValueLookup
func TestObjValueLookup(t *testing.T) {
if runtime.GOOS == "android" {
t.Skipf("no testdata directory on %s", runtime.GOOS)
}
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/objlookup.go", nil)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
// Maps each var Ident (represented "name:linenum") to the
// kind of ssa.Value we expect (represented "Constant", "&Alloc").
expectations := make(map[string]string)
// Find all annotations of form x::BinOp, &y::Alloc, etc.
re := regexp.MustCompile(`(\b|&)?(\w*)::(\w*)\b`)
for _, c := range f.Comments {
text := c.Text()
pos := conf.Fset.Position(c.Pos())
for _, m := range re.FindAllStringSubmatch(text, -1) {
key := fmt.Sprintf("%s:%d", m[2], pos.Line)
value := m[1] + m[3]
expectations[key] = value
}
}
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
prog := ssautil.CreateProgram(iprog, 0 /*|ssa.PrintFunctions*/)
mainInfo := iprog.Created[0]
mainPkg := prog.Package(mainInfo.Pkg)
mainPkg.SetDebugMode(true)
mainPkg.Build()
var varIds []*ast.Ident
var varObjs []*types.Var
for id, obj := range mainInfo.Defs {
// Check invariants for func and const objects.
switch obj := obj.(type) {
case *types.Func:
checkFuncValue(t, prog, obj)
case *types.Const:
checkConstValue(t, prog, obj)
case *types.Var:
if id.Name == "_" {
continue
}
varIds = append(varIds, id)
varObjs = append(varObjs, obj)
}
}
for id, obj := range mainInfo.Uses {
if obj, ok := obj.(*types.Var); ok {
varIds = append(varIds, id)
varObjs = append(varObjs, obj)
}
}
// Check invariants for var objects.
// The result varies based on the specific Ident.
for i, id := range varIds {
obj := varObjs[i]
ref, _ := astutil.PathEnclosingInterval(f, id.Pos(), id.Pos())
pos := prog.Fset.Position(id.Pos())
exp := expectations[fmt.Sprintf("%s:%d", id.Name, pos.Line)]
if exp == "" {
t.Errorf("%s: no expectation for var ident %s ", pos, id.Name)
continue
}
wantAddr := false
if exp[0] == '&' {
wantAddr = true
exp = exp[1:]
}
checkVarValue(t, prog, mainPkg, ref, obj, exp, wantAddr)
}
}
示例10: TestValueForExpr
// Ensure that, in debug mode, we can determine the ssa.Value
// corresponding to every ast.Expr.
func TestValueForExpr(t *testing.T) {
if runtime.GOOS == "android" {
t.Skipf("no testdata dir on %s", runtime.GOOS)
}
conf := loader.Config{ParserMode: parser.ParseComments}
f, err := conf.ParseFile("testdata/valueforexpr.go", nil)
if err != nil {
t.Error(err)
return
}
conf.CreateFromFiles("main", f)
iprog, err := conf.Load()
if err != nil {
t.Error(err)
return
}
mainInfo := iprog.Created[0]
prog := ssautil.CreateProgram(iprog, 0)
mainPkg := prog.Package(mainInfo.Pkg)
mainPkg.SetDebugMode(true)
mainPkg.Build()
if false {
// debugging
for _, mem := range mainPkg.Members {
if fn, ok := mem.(*ssa.Function); ok {
fn.WriteTo(os.Stderr)
}
}
}
// Find the actual AST node for each canonical position.
parenExprByPos := make(map[token.Pos]*ast.ParenExpr)
ast.Inspect(f, func(n ast.Node) bool {
if n != nil {
if e, ok := n.(*ast.ParenExpr); ok {
parenExprByPos[e.Pos()] = e
}
}
return true
})
// Find all annotations of form /*@kind*/.
for _, c := range f.Comments {
text := strings.TrimSpace(c.Text())
if text == "" || text[0] != '@' {
continue
}
text = text[1:]
pos := c.End() + 1
position := prog.Fset.Position(pos)
var e ast.Expr
if target := parenExprByPos[pos]; target == nil {
t.Errorf("%s: annotation doesn't precede ParenExpr: %q", position, text)
continue
} else {
e = target.X
}
path, _ := astutil.PathEnclosingInterval(f, pos, pos)
if path == nil {
t.Errorf("%s: can't find AST path from root to comment: %s", position, text)
continue
}
fn := ssa.EnclosingFunction(mainPkg, path)
if fn == nil {
t.Errorf("%s: can't find enclosing function", position)
continue
}
v, gotAddr := fn.ValueForExpr(e) // (may be nil)
got := strings.TrimPrefix(fmt.Sprintf("%T", v), "*ssa.")
if want := text; got != want {
t.Errorf("%s: got value %q, want %q", position, got, want)
}
if v != nil {
T := v.Type()
if gotAddr {
T = T.Underlying().(*types.Pointer).Elem() // deref
}
if !types.Identical(T, mainInfo.TypeOf(e)) {
t.Errorf("%s: got type %s, want %s", position, mainInfo.TypeOf(e), T)
}
}
}
}
示例11: TestPathEnclosingInterval_Exact
func TestPathEnclosingInterval_Exact(t *testing.T) {
// For the exact tests, we check that a substring is mapped to
// the canonical string for the node it denotes.
tests := []struct {
substr string // first occurrence of this string indicates interval
node string // complete text of expected containing node
}{
{"package",
input[11 : len(input)-1]},
{"\npack",
input[11 : len(input)-1]},
{"main",
"main"},
{"import",
"import \"fmt\""},
{"\"fmt\"",
"\"fmt\""},
{"\nfunc f() {}\n",
"func f() {}"},
{"x ",
"x"},
{" y",
"y"},
{"z",
"z"},
{" + ",
"x + y"},
{" :=",
"z := (x + y)"},
{"x + y",
"x + y"},
{"(x + y)",
"(x + y)"},
{" (x + y) ",
"(x + y)"},
{" (x + y) // add",
"(x + y)"},
{"func",
"func f() {}"},
{"func f() {}",
"func f() {}"},
{"\nfun",
"func f() {}"},
{" f",
"f"},
}
for _, test := range tests {
f, start, end := findInterval(t, new(token.FileSet), input, test.substr)
if f == nil {
continue
}
path, exact := astutil.PathEnclosingInterval(f, start, end)
if !exact {
t.Errorf("PathEnclosingInterval(%q) not exact", test.substr)
continue
}
if len(path) == 0 {
if test.node != "" {
t.Errorf("PathEnclosingInterval(%q).path: got [], want %q",
test.substr, test.node)
}
continue
}
if got := input[path[0].Pos():path[0].End()]; got != test.node {
t.Errorf("PathEnclosingInterval(%q): got %q, want %q (path was %s)",
test.substr, got, test.node, pathToString(path))
continue
}
}
}
示例12: doQuickFix
// doQuickFix tries to fix the source AST so that it compiles well.
func (s *Session) doQuickFix() error {
const maxAttempts = 10
s.reset()
quickFixAttempt:
for i := 0; i < maxAttempts; i++ {
s.TypeInfo = types.Info{
Types: make(map[ast.Expr]types.TypeAndValue),
}
files := s.ExtraFiles
files = append(files, s.File)
config := quickfix.Config{
Fset: s.Fset,
Files: files,
TypeInfo: &s.TypeInfo,
}
_, err := config.QuickFixOnce()
if err == nil {
break
}
debugf("quickFix :: err = %#v", err)
errList, ok := err.(quickfix.ErrorList)
if !ok {
continue
}
// (try to) fix gore-specific remaining errors
for _, err := range errList {
err, ok := err.(types.Error)
if !ok {
continue
}
// "... used as value":
//
// convert
// __gore_pp(funcWithSideEffectReturningNoValue())
// to
// funcWithSideEffectReturningNoValue()
if strings.HasSuffix(err.Msg, " used as value") {
nodepath, _ := astutil.PathEnclosingInterval(s.File, err.Pos, err.Pos)
for _, node := range nodepath {
stmt, ok := node.(ast.Stmt)
if !ok {
continue
}
for i := range s.mainBody.List {
if s.mainBody.List[i] != stmt {
continue
}
exprs := printedExprs(stmt)
stmts := s.mainBody.List[0:i]
for _, expr := range exprs {
stmts = append(stmts, &ast.ExprStmt{X: expr})
}
s.mainBody.List = append(stmts, s.mainBody.List[i+1:]...)
continue quickFixAttempt
}
}
}
}
debugf("quickFix :: give up: %#v", err)
}
return nil
}
示例13: QuickFixOnce
func (c Config) QuickFixOnce() (bool, error) {
fset := c.Fset
files := c.Files
errs := []error{}
config := &types.Config{
Error: func(err error) {
errs = append(errs, err)
},
Importer: importer.Default(),
}
_, err := config.Check("_quickfix", fset, files, c.TypeInfo)
if err == nil {
return false, nil
}
// apply fixes on AST later so that we won't break funcs that inspect AST by positions
fixes := map[error]func() bool{}
unhandled := ErrorList{}
foundError := len(errs) > 0
for _, err := range errs {
err, ok := err.(types.Error)
if !ok {
unhandled = append(unhandled, err)
continue
}
f := findFile(c.Files, err.Pos)
if f == nil {
e := ErrCouldNotLocate{
Err: err,
Fset: fset,
}
unhandled = append(unhandled, e)
continue
}
nodepath, _ := astutil.PathEnclosingInterval(f, err.Pos, err.Pos)
var fix func() bool
// - "%s declared but not used"
// - "%q imported but not used" (+ " as %s")
// - "label %s declared but not used" TODO
// - "no new variables on left side of :="
if m := declaredNotUsed.FindStringSubmatch(err.Msg); m != nil {
identName := m[1]
fix = func() bool {
return fixDeclaredNotUsed(nodepath, identName)
}
} else if m := importedNotUsed.FindStringSubmatch(err.Msg); m != nil {
pkgPath := m[1] // quoted string, but it's okay because this will be compared to ast.BasicLit.Value.
fix = func() bool {
return fixImportedNotUsed(nodepath, pkgPath)
}
} else if err.Msg == noNewVariablesOnDefine {
fix = func() bool {
return fixNoNewVariables(nodepath)
}
} else {
unhandled = append(unhandled, err)
}
if fix != nil {
fixes[err] = fix
}
}
for err, fix := range fixes {
if fix() == false {
unhandled = append(unhandled, err)
}
}
return foundError, unhandled.any()
}