Beispiel #1
0
func TestOneFile(t *testing.T) {
	code, offsetMap := translateSymbols(testCode)
	//fmt.Printf("------------------- {%s}\n", code)
	f, err := parser.ParseFile(FileSet, "xx.go", code, 0, ast.NewScope(parser.Universe))
	if err != nil {
		t.Fatalf("parse failed: %v", err)
	}
	v := make(identVisitor)
	go func() {
		ast.Walk(v, f)
		close(v)
	}()
	for e := range v {
		testExpr(t, FileSet, e, offsetMap)
	}
}
Beispiel #2
0
func parseFileInPkg(fset *token.FileSet, pkgs map[string]*ast.Package, filename string, mode uint) (err error) {
	data, err := readSource(filename, nil)
	if err != nil {
		return err
	}
	// first find package name, so we can use the correct package
	// scope when parsing the file.
	src, err := ParseFile(fset, filename, data, PackageClauseOnly, nil)
	if err != nil {
		return
	}
	name := src.Name.Name
	pkg := pkgs[name]
	if pkg == nil {
		pkg = &ast.Package{name, ast.NewScope(Universe), nil, make(map[string]*ast.File)}
		pkgs[name] = pkg
	}
	src, err = ParseFile(fset, filename, data, mode, pkg.Scope)
	if err != nil {
		return
	}
	pkg.Files[filename] = src
	return
}
Beispiel #3
0
package parser

import "github.com/grncdr/godef/go/ast"

var Universe = ast.NewScope(nil)

func declObj(kind ast.ObjKind, name string) {
	// don't use Insert because it forbids adding to Universe
	Universe.Objects[name] = ast.NewObj(kind, name)
}

func init() {
	declObj(ast.Typ, "bool")

	declObj(ast.Typ, "complex64")
	declObj(ast.Typ, "complex128")

	declObj(ast.Typ, "int")
	declObj(ast.Typ, "int8")
	declObj(ast.Typ, "int16")
	declObj(ast.Typ, "int32")
	declObj(ast.Typ, "int64")

	declObj(ast.Typ, "uint")
	declObj(ast.Typ, "uintptr")
	declObj(ast.Typ, "uint8")
	declObj(ast.Typ, "uint16")
	declObj(ast.Typ, "uint32")
	declObj(ast.Typ, "uint64")

	declObj(ast.Typ, "float")
Beispiel #4
0
func main() {
	flag.Usage = func() {
		fmt.Fprintf(os.Stderr, "usage: godef [flags] [expr]\n")
		flag.PrintDefaults()
	}
	flag.Parse()
	if flag.NArg() > 1 {
		flag.Usage()
		os.Exit(2)
	}
	types.Debug = *debug
	*tflag = *tflag || *aflag || *Aflag
	searchpos := *offset
	filename, err := realAbsolutePath(*fflag)

	if err != nil {
		fail("cannot resolve symlinks in %s: %v", filename, err)
	}

	var src []byte
	if *readStdin {
		src, _ = ioutil.ReadAll(os.Stdin)
	} else {
		// TODO if there's no filename, look in the current
		// directory and do something plausible.
		b, err := ioutil.ReadFile(filename)
		if err != nil {
			fail("cannot read %s: %v", filename, err)
		}
		src = b
	}
	pkgScope := ast.NewScope(parser.Universe)
	f, err := parser.ParseFile(types.FileSet, filename, src, 0, pkgScope)
	if f == nil {
		fail("cannot parse %s: %v", filename, err)
	}

	var o ast.Node
	switch {
	case flag.NArg() > 0:
		o = parseExpr(f.Scope, flag.Arg(0))

	case searchpos >= 0:
		o = findIdentifier(f, searchpos)

	default:
		fmt.Fprintf(os.Stderr, "no expression or offset specified\n")
		flag.Usage()
		os.Exit(2)
	}
	switch e := o.(type) {
	case *ast.ImportSpec:
		path := importPath(e)
		pkg, err := build.Default.Import(path, "", build.FindOnly)
		if err != nil {
			fail("error finding import path for %s: %s", path, err)
		}
		fmt.Println(pkg.Dir)
	case ast.Expr:
		importer := types.NewImporter(filename)
		if !*tflag {
			// try local declarations only
			if obj, typ := types.ExprType(e, importer); obj != nil {
				done(obj, typ, importer)
			}
		}
		// add declarations from other files in the local package and try again
		pkg, err := parseLocalPackage(filename, f, pkgScope)
		if pkg == nil && !*tflag {
			fmt.Printf("parseLocalPackage error: %v\n", err)
		}
		if flag.NArg() > 0 {
			// Reading declarations in other files might have
			// resolved the original expression.
			e = parseExpr(f.Scope, flag.Arg(0)).(ast.Expr)
		}
		if obj, typ := types.ExprType(e, importer); obj != nil {
			done(obj, typ, importer)
		}
		fail("no declaration found for %v", pretty{e})
	}
}