Example #1
0
func (m *mDoc) Call() (interface{}, string) {
	res := []*Doc{}

	fset, af, err := parseAstFile(m.Fn, m.Src, parser.ParseComments)
	if err != nil {
		return res, err.Error()
	}

	sel, id := identAt(fset, af, m.Offset)
	if id == nil {
		return res, ""
	}

	pkgs, _ := parser.ParseDir(fset, filepath.Dir(m.Fn), fiHasGoExt, parser.ParseComments)
	if pkgs == nil {
		pkgs = map[string]*ast.Package{}
	}

	pkgName := af.Name.Name
	files := map[string]*ast.File{}
	pkg, _ := pkgs[pkgName]
	if pkg != nil {
		files = pkg.Files
	}
	files[m.Fn] = af
	pkg, _ = ast.NewPackage(fset, files, nil, nil)
	if pkg == nil {
		return res, ""
	}
	pkgs[pkg.Name] = pkg

	obj, pkg, objPkgs := findUnderlyingObj(fset, af, pkg, pkgs, rootDirs(m.Env), sel, id)
	if obj != nil {
		res = append(res, objDoc(fset, pkg, m.TabIndent, m.TabWidth, obj))
		if objPkgs != nil {
			xName := "Example" + obj.Name
			xPrefix := xName + "_"
			for _, objPkg := range objPkgs {
				xPkg, _ := ast.NewPackage(fset, objPkg.Files, nil, nil)
				if xPkg == nil || xPkg.Scope == nil {
					continue
				}

				for _, xObj := range xPkg.Scope.Objects {
					if xObj.Name == xName || strings.HasPrefix(xObj.Name, xPrefix) {
						res = append(res, objDoc(fset, xPkg, m.TabIndent, m.TabWidth, xObj))
					}
				}
			}
		}
	}
	return res, ""
}
Example #2
0
func check(t *testing.T, testname string, testfiles []string) {
	// TODO(gri) Eventually all these different phases should be
	//           subsumed into a single function call that takes
	//           a set of files and creates a fully resolved and
	//           type-checked AST.

	files, err := parseFiles(t, testname, testfiles)

	// we are expecting the following errors
	// (collect these after parsing the files so that
	// they are found in the file set)
	errors := expectedErrors(t, testname, files)

	// verify errors returned by the parser
	eliminate(t, errors, err)

	// verify errors returned after resolving identifiers
	pkg, err := ast.NewPackage(fset, files, GcImporter, Universe)
	eliminate(t, errors, err)

	// verify errors returned by the typechecker
	_, err = Check(fset, pkg)
	eliminate(t, errors, err)

	// there should be no expected errors left
	if len(errors) > 0 {
		t.Errorf("%s: %d errors not reported:", testname, len(errors))
		for pos, msg := range errors {
			t.Errorf("%s: %s\n", fset.Position(pos), msg)
		}
	}
}
Example #3
0
// parseReflect parses the reflect package and type-checks its AST.
// This is used to generate runtime type structures.
func (c *compiler) parseReflect() (*ast.Package, error) {
	buildpkg, err := build.Import("reflect", "", 0)
	if err != nil {
		return nil, err
	}

	filenames := make([]string, len(buildpkg.GoFiles))
	for i, f := range buildpkg.GoFiles {
		filenames[i] = path.Join(buildpkg.Dir, f)
	}
	fset := token.NewFileSet()
	files, err := parseFiles(fset, filenames)
	if err != nil {
		return nil, err
	}

	pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
	if err != nil {
		return nil, err
	}

	_, err = types.Check(buildpkg.Name, c, fset, pkg)
	if err != nil {
		return nil, err
	}
	return pkg, nil
}
Example #4
0
func compilePackage(fset *token.FileSet, files map[string]*ast.File) (*llgo.Module, error) {
	// make a package (resolve all identifiers)
	pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
	if err != nil {
		report(err)
		return nil, err
	}

	exprTypes, err := types.Check(fset, pkg)
	if err != nil {
		report(err)
		return nil, err
	}

	if *dumpast {
		ast.Fprint(os.Stderr, fset, pkg, nil)
		os.Exit(0)
	}

	compiler := llgo.NewCompiler()
	compiler.SetTraceEnabled(*trace)
	compiler.SetTargetArch(*arch)
	compiler.SetTargetOs(*os_)
	return compiler.Compile(fset, pkg, exprTypes)
}
Example #5
0
func TestFilterDuplicates(t *testing.T) {
	// parse input
	fset := token.NewFileSet()
	file, err := parser.ParseFile(fset, "", input, 0)
	if err != nil {
		t.Fatal(err)
	}

	// create package
	files := map[string]*ast.File{"": file}
	pkg, err := ast.NewPackage(fset, files, nil, nil)
	if err != nil {
		t.Fatal(err)
	}

	// filter
	merged := ast.MergePackageFiles(pkg, ast.FilterFuncDuplicates)

	// pretty-print
	var buf bytes.Buffer
	if err := format.Node(&buf, fset, merged); err != nil {
		t.Fatal(err)
	}
	output := buf.String()

	if output != golden {
		t.Errorf("incorrect output:\n%s", output)
	}
}
Example #6
0
func doParseReflect() {
	buildpkg, err := build.Import("reflect", "", 0)
	if err != nil {
		parseReflectResult, parseReflectError = nil, err
		return
	}

	filenames := make([]string, len(buildpkg.GoFiles))
	for i, f := range buildpkg.GoFiles {
		filenames[i] = path.Join(buildpkg.Dir, f)
	}
	fset := token.NewFileSet()
	files, err := parseFiles(fset, filenames)
	if err != nil {
		parseReflectResult, parseReflectError = nil, err
		return
	}

	pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
	if err != nil {
		parseReflectResult, parseReflectError = nil, err
		return
	}

	_, err = types.Check(fset, pkg)
	if err != nil {
		parseReflectResult, parseReflectError = nil, err
		return
	}

	parseReflectResult, parseReflectError = pkg, nil
	return
}
Example #7
0
func compilePackage(compiler llgo.Compiler, fset *token.FileSet, files map[string]*ast.File, importpath string) (*llgo.Module, error) {
	// make a package (resolve all identifiers)
	pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
	if err != nil {
		report(err)
		return nil, err
	}

	// an empty importpath means the same as the package name
	if importpath == "" {
		importpath = pkg.Name
	}

	exprTypes, err := types.Check(importpath, compiler, fset, pkg)
	if err != nil {
		report(err)
		return nil, err
	}

	if *dumpast {
		ast.Fprint(os.Stderr, fset, pkg, nil)
		os.Exit(0)
	}

	return compiler.Compile(fset, pkg, importpath, exprTypes)
}
Example #8
0
func main() {
	flag.Parse()
	if len(flag.Args()) != 1 {
		log.Fatal("Usage: go run goprint.go path")
	}
	bpkg, err := build.Default.Import(flag.Args()[0], ".", 0)
	if err != nil {
		log.Fatal(err)
	}
	fset := token.NewFileSet()
	files := make(map[string]*ast.File)
	for _, fname := range bpkg.GoFiles {
		p, err := ioutil.ReadFile(filepath.Join(bpkg.SrcRoot, bpkg.ImportPath, fname))
		if err != nil {
			log.Fatal(err)
		}
		file, err := parser.ParseFile(fset, fname, p, parser.ParseComments)
		if err != nil {
			log.Fatal(err)
		}
		files[fname] = file
	}
	c := spew.NewDefaultConfig()
	c.DisableMethods = true
	apkg, _ := ast.NewPackage(fset, files, importer, nil)
	c.Dump(apkg)
	ast.Print(fset, apkg)
	dpkg := doc.New(apkg, bpkg.ImportPath, 0)
	c.Dump(dpkg)
}
Example #9
0
func ExtractStructs(inputPath string) (string, []*StructInfo, error) {
	fset := token.NewFileSet()

	f, err := parser.ParseFile(fset, inputPath, nil, parser.ParseComments)

	if err != nil {
		return "", nil, err
	}

	packageName := f.Name.String()
	structs := make(map[string]*StructInfo)

	for k, d := range f.Scope.Objects {
		if d.Kind == ast.Typ {
			incl, err := shouldInclude(d)
			if err != nil {
				return "", nil, err
			}
			if incl {
				stobj := NewStructInfo(k)

				structs[k] = stobj
			}
		}
	}

	files := map[string]*ast.File{
		inputPath: f,
	}

	pkg, _ := ast.NewPackage(fset, files, nil, nil)

	d := doc.New(pkg, f.Name.String(), doc.AllDecls)
	for _, t := range d.Types {
		if skipre.MatchString(t.Doc) {
			delete(structs, t.Name)
		} else {
			if skipdec.MatchString(t.Doc) {
				s, ok := structs[t.Name]
				if ok {
					s.Options.SkipDecoder = true
				}
			}
			if skipenc.MatchString(t.Doc) {
				s, ok := structs[t.Name]
				if ok {
					s.Options.SkipEncoder = true
				}
			}
		}
	}

	rv := make([]*StructInfo, 0)
	for _, v := range structs {
		rv = append(rv, v)
	}
	return packageName, rv, nil
}
Example #10
0
// build generates data from source files.
func (w *routerWalker) build(srcs []*source) (*Package, error) {
	// Add source files to walker, I skipped references here.
	w.srcs = make(map[string]*source)
	for _, src := range srcs {
		w.srcs[src.name] = src
	}

	w.fset = token.NewFileSet()

	// Find the package and associated files.
	ctxt := gobuild.Context{
		GOOS:          runtime.GOOS,
		GOARCH:        runtime.GOARCH,
		CgoEnabled:    true,
		JoinPath:      path.Join,
		IsAbsPath:     path.IsAbs,
		SplitPathList: func(list string) []string { return strings.Split(list, ":") },
		IsDir:         func(path string) bool { panic("unexpected") },
		HasSubdir:     func(root, dir string) (rel string, ok bool) { panic("unexpected") },
		ReadDir:       func(dir string) (fi []os.FileInfo, err error) { return w.readDir(dir) },
		OpenFile:      func(path string) (r io.ReadCloser, err error) { return w.openFile(path) },
		Compiler:      "gc",
	}

	bpkg, err := ctxt.ImportDir(w.pdoc.ImportPath, 0)
	// Continue if there are no Go source files; we still want the directory info.
	_, nogo := err.(*gobuild.NoGoError)
	if err != nil {
		if nogo {
			err = nil
		} else {
			return nil, errors.New("routerWalker.build -> " + err.Error())
		}
	}

	// Parse the Go files
	files := make(map[string]*ast.File)
	for _, name := range append(bpkg.GoFiles, bpkg.CgoFiles...) {
		file, err := parser.ParseFile(w.fset, name, w.srcs[name].data, parser.ParseComments)
		if err != nil {
			return nil, errors.New("routerWalker.build -> parse go files: " + err.Error())
		}
		files[name] = file
	}

	apkg, _ := ast.NewPackage(w.fset, files, simpleImporter, nil)

	mode := doc.Mode(0)
	if w.pdoc.ImportPath == "builtin" {
		mode |= doc.AllDecls
	}

	pdoc := doc.New(apkg, w.pdoc.ImportPath, mode)

	w.pdoc.Types = w.types(pdoc.Types)

	return w.pdoc, err
}
Example #11
0
func TestResolveQualifiedIdents(t *testing.T) {
	// parse package files
	fset := token.NewFileSet()
	files := make(map[string]*ast.File)
	for i, src := range sources {
		filename := fmt.Sprintf("file%d", i)
		f, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
		if err != nil {
			t.Fatal(err)
		}
		files[filename] = f
	}

	// resolve package AST
	pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
	if err != nil {
		t.Fatal(err)
	}

	// check that all packages were imported
	for _, name := range pkgnames {
		if pkg.Imports[name] == nil {
			t.Errorf("package %s not imported", name)
		}
	}

	// check that there are no top-level unresolved identifiers
	for _, f := range pkg.Files {
		for _, x := range f.Unresolved {
			t.Errorf("%s: unresolved global identifier %s", fset.Position(x.Pos()), x.Name)
		}
	}

	// resolve qualified identifiers
	if err := ResolveQualifiedIdents(fset, pkg); err != nil {
		t.Error(err)
	}

	// check that qualified identifiers are resolved
	ast.Inspect(pkg, func(n ast.Node) bool {
		if s, ok := n.(*ast.SelectorExpr); ok {
			if x, ok := s.X.(*ast.Ident); ok {
				if x.Obj == nil {
					t.Errorf("%s: unresolved qualified identifier %s", fset.Position(x.Pos()), x.Name)
					return false
				}
				if x.Obj.Kind == ast.Pkg && s.Sel != nil && s.Sel.Obj == nil {
					t.Errorf("%s: unresolved selector %s", fset.Position(s.Sel.Pos()), s.Sel.Name)
					return false
				}
				return false
			}
			return false
		}
		return true
	})
}
Example #12
0
// AnalyzeFile scans the provided file for references to packages with the given
// package prefix. The list of unique (package, identifier) pairs is returned
func AnalyzeFile(file *ast.File, pkgPrefix string) (*References, error) {
	visitor := newRefsSaver(pkgPrefix)
	fset := token.NewFileSet()
	files := map[string]*ast.File{file.Name.Name: file}
	// Ignore errors (from unknown packages)
	pkg, _ := ast.NewPackage(fset, files, visitor.importer(), nil)
	ast.Walk(visitor, pkg)
	return &visitor.References, nil
}
Example #13
0
func (c *FunctionCache) NamedFunction(name string, signature string) llvm.Value {
	f, _ := c.functions[name+":"+signature]
	if !f.IsNil() {
		return f
	}

	if strings.HasPrefix(name, c.module.Name+".") {
		obj := c.pkg.Scope.Lookup(name[len(c.module.Name)+1:])
		value := c.Resolve(obj)
		f = value.LLVMValue()
	} else {
		fset := token.NewFileSet()
		code := `package runtime;import("unsafe");` + signature + `{panic()}`
		file, err := parser.ParseFile(fset, "", code, 0)
		if err != nil {
			panic(err)
		}

		// Parse the runtime package, since we may need to refer to
		// its types. TODO cache the package.
		buildpkg, err := build.Import("github.com/axw/llgo/pkg/runtime", "", 0)
		if err != nil {
			panic(err)
		}
		runtimefiles := make([]string, len(buildpkg.GoFiles))
		for i, f := range buildpkg.GoFiles {
			runtimefiles[i] = path.Join(buildpkg.Dir, f)
		}

		files, err := parseFiles(fset, runtimefiles)
		if err != nil {
			panic(err)
		}
		files["<src>"] = file
		pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
		if err != nil {
			panic(err)
		}

		_, err = types.Check(fset, pkg)
		if err != nil {
			panic(err)
		}

		fdecl := file.Decls[len(file.Decls)-1].(*ast.FuncDecl)
		ftype := fdecl.Name.Obj.Type.(*types.Func)
		llvmfptrtype := c.types.ToLLVM(ftype)
		f = llvm.AddFunction(c.module.Module, name, llvmfptrtype.ElementType())
		if !strings.HasPrefix(name, "llvm.") {
			f.SetLinkage(llvm.AvailableExternallyLinkage)
		}
	}
	c.functions[name+":"+signature] = f
	return f
}
Example #14
0
//ExtractStructs extract struct infos from file
func ExtractStructs(inputPath string) (string, []*ActStructInfo, error) {
	fset := token.NewFileSet()

	f, err := parser.ParseFile(fset, inputPath, nil, parser.ParseComments)

	if err != nil {
		return "", nil, err
	}

	packageName := f.Name.String()
	structs := make(map[string]*ActStructInfo)

	for k, d := range f.Scope.Objects {
		if d.Kind == ast.Typ {
			ts, ok := d.Decl.(*ast.TypeSpec)
			if !ok {
				return "", nil, fmt.Errorf("Unknown type without TypeSec: %v", d)
			}

			_, ok = ts.Type.(*ast.StructType)
			if !ok {
				_, ok = ts.Type.(*ast.ArrayType)
				if !ok {
					_, ok = ts.Type.(*ast.MapType)
					if !ok {
						continue
					}
				}
			}

			stobj := NewStructInfo(k)

			structs[k] = stobj
		}
	}

	files := map[string]*ast.File{
		inputPath: f,
	}

	pkg, _ := ast.NewPackage(fset, files, nil, nil)

	d := doc.New(pkg, f.Name.String(), doc.AllDecls)
	for _, t := range d.Types {
		if skipre.MatchString(t.Doc) {
			delete(structs, t.Name)
		}
	}

	var rv []*ActStructInfo
	for _, v := range structs {
		rv = append(rv, v)
	}
	return packageName, rv, nil
}
Example #15
0
func (ctx *Context) loadPackage(importPath string, flags int) (*Package, error) {
	bpkg, err := build.Import(importPath, ctx.cwd, 0)
	if _, ok := err.(*build.NoGoError); ok {
		return &Package{bpkg: bpkg}, nil
	}
	if err != nil {
		return nil, err
	}

	pkg := &Package{
		fset: token.NewFileSet(),
		bpkg: bpkg,
	}

	files := make(map[string]*ast.File)
	for _, name := range append(pkg.bpkg.GoFiles, pkg.bpkg.CgoFiles...) {
		file, err := pkg.parseFile(name)
		if err != nil {
			pkg.errors = append(pkg.errors, err)
			continue
		}
		files[name] = file
	}

	pkg.apkg, _ = ast.NewPackage(pkg.fset, files, simpleImporter, nil)

	if flags&loadDoc != 0 {
		mode := doc.Mode(0)
		if pkg.bpkg.ImportPath == "builtin" || flags&loadUnexported != 0 {
			mode |= doc.AllDecls
		}
		pkg.dpkg = doc.New(pkg.apkg, pkg.bpkg.ImportPath, mode)
		if pkg.bpkg.ImportPath == "builtin" {
			for _, t := range pkg.dpkg.Types {
				pkg.dpkg.Funcs = append(pkg.dpkg.Funcs, t.Funcs...)
				t.Funcs = nil
			}
			sort.Sort(byFuncName(pkg.dpkg.Funcs))
		}
	}

	if flags&loadExamples != 0 {
		for _, name := range append(pkg.bpkg.TestGoFiles, pkg.bpkg.XTestGoFiles...) {
			file, err := pkg.parseFile(name)
			if err != nil {
				pkg.errors = append(pkg.errors, err)
				continue
			}
			pkg.examples = append(pkg.examples, doc.Examples(file)...)
		}
	}

	return pkg, nil
}
Example #16
0
func processPackage(fset *token.FileSet, files map[string]*ast.File) {
	// make a package (resolve all identifiers)
	pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
	if err != nil {
		report(err)
		return
	}
	if err = types.Check(fset, pkg, nil, nil); err != nil {
		report(err)
	}
}
Example #17
0
func LookupType(pkgs map[string]*ast.Package, name string) *ast.Object {
	for k := range pkgs {
		fset := token.NewFileSet()
		pkg, err := ast.NewPackage(fset, pkgs[k].Files, nil, nil)
		if err != nil {
			// panic(err) // too much errors due to the abscence of an importer (incomplete types)
		}
		return pkg.Scope.Lookup(name)
	}
	return nil
}
Example #18
0
func (c *FunctionCache) NamedFunction(name string, signature string) llvm.Value {
	f, _ := c.functions[name+":"+signature]
	if !f.IsNil() {
		return f
	}

	if strings.HasPrefix(name, c.module.Name+".") {
		obj := c.pkg.Scope.Lookup(name[len(c.module.Name)+1:])
		value := c.Resolve(obj)
		f = value.LLVMValue()
	} else {
		fset := token.NewFileSet()
		code := `package runtime;import("unsafe");` + signature + `{panic()}`
		file, err := parser.ParseFile(fset, "", code, 0)
		if err != nil {
			panic(err)
		}

		// Parse the runtime package, since we may need to refer to
		// its types. Can't be cached, because type-checking can't
		// be done twice on the AST.
		buildpkg, err := build.Import("github.com/axw/llgo/pkg/runtime", "", 0)
		if err != nil {
			panic(err)
		}

		// All types visible to the compiler are in "types.go".
		runtimefiles := []string{path.Join(buildpkg.Dir, "types.go")}

		files, err := parseFiles(fset, runtimefiles)
		if err != nil {
			panic(err)
		}
		files["<src>"] = file

		pkg, err := ast.NewPackage(fset, files, types.GcImport, types.Universe)
		if err != nil {
			panic(err)
		}

		_, err = types.Check("", c.compiler, fset, pkg)
		if err != nil {
			panic(err)
		}

		fdecl := file.Decls[len(file.Decls)-1].(*ast.FuncDecl)
		ftype := fdecl.Name.Obj.Type.(*types.Func)
		llvmfptrtype := c.types.ToLLVM(ftype)
		f = llvm.AddFunction(c.module.Module, name, llvmfptrtype.ElementType())
	}
	c.functions[name+":"+signature] = f
	return f
}
Example #19
0
func New(p *build.Package, mode parser.Mode) (*token.FileSet, *ast.Package, error) {
	fset := token.NewFileSet()
	var names []string
	names = append(names, p.GoFiles...)
	names = append(names, p.CgoFiles...)
	files, err := ParseFiles(fset, p.Dir, names, mode)
	if err != nil {
		return nil, nil, err
	}
	a, _ := ast.NewPackage(fset, files, Importer, nil)
	return fset, a, nil
}
Example #20
0
func (e Environment) _importPackage(p string, shallow bool) (*Package, error) {
	b, err := e.importBuildPackage(p)
	if err != nil {
		if noBuildable(err) && !shallow {
			dir, sub, err := e.importSubpackages(p)
			if err != nil {
				return nil, err
			}
			return &Package{name: path.Base(p), dir: dir, Packages: sub, env: e}, nil

		}
	}
	fset := token.NewFileSet()
	var names []string
	names = append(names, b.GoFiles...)
	names = append(names, b.CgoFiles...)
	files, err := e.parseFiles(fset, b.Dir, names, parser.ParseComments)
	if err != nil {
		return nil, err
	}
	bodies := make(map[*ast.FuncDecl]*ast.BlockStmt)
	for _, f := range files {
		for _, d := range f.Decls {
			if fn, ok := d.(*ast.FuncDecl); ok {
				bodies[fn] = fn.Body
			}
		}
	}
	// NewPackage will always return errors because it won't
	// resolve builtin types.
	a, _ := ast.NewPackage(fset, files, astutil.Importer, nil)
	flags := doc.AllMethods
	if p == "builtin" {
		flags |= doc.AllDecls
	}
	pkg := &Package{
		fset:   fset,
		bpkg:   b,
		apkg:   a,
		dpkg:   doc.New(a, b.ImportPath, flags),
		bodies: bodies,
		env:    e,
	}
	if !shallow {
		sub, err := e.ImportPackages(b.Dir)
		if err != nil {
			return nil, err
		}
		pkg.Packages = sub
	}
	return pkg, nil
}
Example #21
0
func populateASTWithTokenSet(pkg *Package, fset *token.FileSet) error {
	gtor := &astPopulator{fset: fset, populated: map[canPopulateAST]struct{}{}}

	files := map[string]*ast.File{}
	for _, f := range pkg.Files() {
		f.populateAST(gtor)
		files[f.Name()] = f.AST()
	}

	apkg, err := ast.NewPackage(gtor.fset, files, nil, nil)
	pkg.ast = apkg
	return err
}
Example #22
0
func parsePkg(fset *token.FileSet, srcDir string, mode parser.Mode) (pkg *ast.Package, pkgs map[string]*ast.Package, err error) {
	if pkgs, err = parser.ParseDir(fset, srcDir, fiHasGoExt, mode); pkgs != nil {
		_, pkgName := filepath.Split(srcDir)
		// we aren't going to support package whose name don't match the directory unless it's main
		p, ok := pkgs[pkgName]
		if !ok {
			p, ok = pkgs["main"]
		}
		if ok {
			pkg, err = ast.NewPackage(fset, p.Files, nil, nil)
		}
	}
	return
}
Example #23
0
func packageFromInfo(prog *loader.Program, pkgInfo *loader.PackageInfo) *Package {
	files := map[string]*ast.File{}
	for _, f := range pkgInfo.Files {
		files[prog.Fset.File(f.Pos()).Name()] = f
	}

	// Ignore (perhaps) "unresolved identifier" errors
	astPkg, _ := ast.NewPackage(prog.Fset, files, nil, nil)

	var mode doc.Mode
	docPkg := doc.New(astPkg, pkgInfo.String(), mode)

	return NewPackage(prog.Fset, docPkg, pkgInfo.Pkg)
}
Example #24
0
func (b *builder) merge() ([]byte, error) {
	var buf bytes.Buffer
	if err := b.tpl.Execute(&buf, b); err != nil {
		return nil, err
	}

	f, err := parser.ParseFile(b.fset, "", &buf, 0)
	if err != nil {
		return nil, err
	}
	// b.imports(f)
	b.deleteImports(f)
	b.files["main.go"] = f

	pkg, _ := ast.NewPackage(b.fset, b.files, nil, nil)
	pkg.Name = "main"

	ret, err := ast.MergePackageFiles(pkg, 0), nil
	if err != nil {
		return nil, err
	}

	// @TODO: we reread the file, probably something goes wrong with position
	buf.Reset()
	if err = format.Node(&buf, b.fset, ret); err != nil {
		return nil, err
	}

	ret, err = parser.ParseFile(b.fset, "", buf.Bytes(), 0)
	if err != nil {
		return nil, err
	}

	for _, spec := range b.imports {
		var name string
		if spec.Name != nil {
			name = spec.Name.Name
		}
		ipath, _ := strconv.Unquote(spec.Path.Value)
		addImport(b.fset, ret, name, ipath)
	}

	buf.Reset()
	if err := format.Node(&buf, b.fset, ret); err != nil {
		return nil, err
	}

	return buf.Bytes(), nil
}
func astFrom(filePath string) *doc.Package {
	fset := token.NewFileSet()
	m := make(map[string]*ast.File)

	f, err := parser.ParseFile(fset, filePath, nil, parser.ParseComments)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	m[filePath] = f
	apkg, _ := ast.NewPackage(fset, m, nil, nil)

	return doc.New(apkg, "", 0)
}
Example #26
0
func NewPackageAST(files []string) (*ast.Package, error) {
	asts := make(map[string]*ast.File)

	fset := token.NewFileSet()
	for _, file := range files {
		ast, err := parser.ParseFile(fset, file, nil, parser.ParseComments)
		if err != nil {
			return nil, err
		}
		asts[file] = ast
	}

	pkg, _ := ast.NewPackage(fset, asts, nil, nil)
	return pkg, nil
}
Example #27
0
func makePkg(t *testing.T, src string) (*ast.Package, error) {
	file, err := parser.ParseFile(fset, filename, src, parser.DeclarationErrors)
	if err != nil {
		return nil, err
	}
	files := map[string]*ast.File{filename: file}
	pkg, err := ast.NewPackage(fset, files, GcImport, Universe)
	if err != nil {
		return nil, err
	}
	if err := Check(fset, pkg, nil, nil); err != nil {
		return nil, err
	}
	return pkg, nil
}
Example #28
0
func main() {
	fset := token.NewFileSet()
	files := map[string]*ast.File{}

	for _, f := range os.Args[1:] {
		file, err := parser.ParseFile(fset, f, nil, 0)
		if err != nil {
			panic("parse file:" + err.Error())
		}
		files[f] = file

	}
	pack, err := ast.NewPackage(fset, files, types.GcImporter, types.Universe)
	if err != nil {
		panic("new package" + err.Error())
	}
	/*for name, object := range pack.Scope.Objects {
		if f, ok := object.Decl.(*ast.FuncDecl); ok {
			if f.Type.Results == nil {
				continue
			}
			for _, returnValue := range f.Type.Results.List {
				if returnValue.Type.(*ast.Ident).Name == "error" {
					fmt.Println(name, ": function returns error")
				}
			}
		}
	}*/

	//check that the file is valid
	/*valid := true
	ast.Walk(visitor(func(node ast.Node) bool {
		switch node.(type) {
		case *ast.BadDecl,
			*ast.BadExpr,
			*ast.BadStmt:
			valid = false
			return false
		}
		return true
	}), pack)
	if !valid {
		panic("invalid file")
	}*/

	ast.Walk(SimpleVisitor{pack, fset}, pack)
}
Example #29
0
func NewFilePackage(filename string) (*PackageView, error) {
	p := new(PackageView)
	p.fset = token.NewFileSet()
	file, err := parser.ParseFile(p.fset, filename, nil, parser.AllErrors)
	if file == nil {
		return nil, err
	}
	m := make(map[string]*ast.File)
	m[filename] = file
	pkg, err := ast.NewPackage(p.fset, m, nil, nil)
	if err != nil {
		return nil, err
	}
	p.pkg = pkg
	p.pdoc = doc.New(pkg, pkg.Name, doc.AllDecls)
	return p, nil
}
Example #30
0
// AnalyzePackages scans the provided packages for references to packages with the given
// package prefix. The list of unique (package, identifier) pairs is returned
func AnalyzePackages(pkgs []*build.Package, pkgPrefix string) (*References, error) {
	visitor := newRefsSaver(pkgPrefix)
	imp := visitor.importer()
	fset := token.NewFileSet()
	for _, pkg := range pkgs {
		fileNames := append(append([]string{}, pkg.GoFiles...), pkg.CgoFiles...)
		files := make(map[string]*ast.File)
		for _, name := range fileNames {
			f, err := parser.ParseFile(fset, filepath.Join(pkg.Dir, name), nil, 0)
			if err != nil {
				return nil, err
			}
			files[name] = f
		}
		// Ignore errors (from unknown packages)
		astpkg, _ := ast.NewPackage(fset, files, imp, nil)
		ast.Walk(visitor, astpkg)
	}
	return &visitor.References, nil
}