Пример #1
0
//ParseDocs parses the Package's documentation with go/doc.
//
//If you do not need a particular doc.Mode call this with 0.
//
//If the package directory contains a file of package documentation
//(and the package is not itself named documentation), it is parsed
//and its doc.Package.Doc string replaces the string generated
//by the package itself.
//
//Note that the go/doc package munges the AST so this method parses the AST
//again, regardless of the value in p.AST. As a consequence, it is valid
//to call this even if you have not called the Parse method or if you have
//called the Parse method and told it not to parse comments.
func (p *Package) ParseDocs(mode doc.Mode) error {
	if p.Doc != nil {
		return nil
	}
	pkg, _, err := p.parse(true)
	if err != nil {
		return err
	}

	p.Doc = doc.New(pkg, p.Build.ImportPath, mode)

	//we don't want the below running if we happen to be importing a package
	//whose name happens to be documentation.
	if p.Build.Name == "documentation" {
		return nil
	}

	//check ignored files for any package named documentation.
	//assume there is only one such file.
	//We ignore errors here as the ignored files may not be meant to parse.
	var docfile string
	for _, u := range p.Build.IgnoredGoFiles {
		path := filepath.Join(p.Build.Dir)
		fs := token.NewFileSet()
		f, err := parser.ParseFile(fs, path, nil, parser.PackageClauseOnly)
		if err != nil {
			continue
		}
		if f.Name.Name == "documentation" {
			docfile = u
			break
		}
	}

	//there's an ignored file of package documentation,
	//parse it and replace the package doc string with this doc string.
	if docfile != "" {
		fs := token.NewFileSet()
		f := func(fi os.FileInfo) bool {
			return !fi.IsDir() && fi.Name() == docfile
		}
		pkgs, err := parser.ParseDir(fs, p.Build.Dir, f, parser.ParseComments)
		if err != nil {
			return err
		}
		d := doc.New(pkgs["documentation"], p.Build.ImportPath, 0)
		p.Doc.Doc = d.Doc
	}

	return nil
}
Пример #2
0
func getPageInfo(pkgName, diskPath string) (pi PageInfo, err error) {
	bpkg, err := build.ImportDir(diskPath, 0)
	if err != nil {
		return
	}
	inSet := make(map[string]bool)
	for _, name := range bpkg.GoFiles {
		inSet[filepath.Base(name)] = true
	}

	pi.FSet = token.NewFileSet()
	filter := func(fi os.FileInfo) bool {
		return inSet[fi.Name()]
	}
	aPkgMap, err := parser.ParseDir(pi.FSet, diskPath, filter, 0)
	if err != nil {
		return
	}
	aPkg := aPkgMap[pathpkg.Base(pkgName)]
	if aPkg == nil {
		for _, v := range aPkgMap {
			aPkg = v
			break
		}
		if aPkg == nil {
			err = errors.New("no apkg found?")
			return
		}
	}

	pi.Dirname = diskPath
	pi.PDoc = doc.New(aPkg, pkgName, 0)
	pi.IsMain = strings.Contains(pkgName, "camlistore.org/cmd/")
	return
}
Пример #3
0
func packageComment(pkg, pkgpath string) (info string, err error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, pkgpath, isGoFile, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return
	}
	for name := range pkgs {
		if name == "main" {
			continue
		}
		pdoc := doc.New(pkgs[name], pkg, doc.AllDecls)
		if pdoc.Doc == "" {
			continue
		}
		if info != "" {
			return "", errors.New("multiple packages with docs")
		}
		info = pdoc.Doc
	}
	// grab only first paragraph
	if parts := strings.SplitN(info, "\n\n", 2); len(parts) > 1 {
		info = parts[0]
	}
	// replace newlines with spaces
	info = strings.Replace(info, "\n", " ", -1)
	// truncate
	if len(info) > MaxCommentLength {
		info = info[:MaxCommentLength]
	}
	return
}
Пример #4
0
func ReflectDefs() (names map[string][]byte, err error) {
	b, err := build.Import("reflect", "", 0)
	if err != nil {
		return nil, err
	}

	ts := token.NewFileSet()

	p, err := parser.ParseDir(ts, b.Dir, gofiles, 0)
	if err != nil {
		return nil, err
	}

	pkg := doc.New(p["reflect"], "reflect", doc.AllMethods)

	acc := []string{}
	acc = values(pkg.Consts, acc)
	acc = values(pkg.Vars, acc)
	acc = funcs(pkg.Funcs, "reflect.", acc)
	acc = types(pkg.Types, acc)

	names = map[string][]byte{}
	for _, name := range acc {
		names[name] = []byte(name)
	}
	return names, nil
}
Пример #5
0
func main() {
	pkg, err := build.Import("robpike.io/ivy", "", build.ImportComment)
	if err != nil {
		log.Fatal(err)
	}
	fs := token.NewFileSet()
	pkgs, err := parser.ParseDir(fs, pkg.Dir, nil, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	astPkg := pkgs[pkg.Name]
	if astPkg == nil {
		log.Fatalf("failed to locate %s package", pkg.Name)
	}

	docPkg := doc.New(astPkg, pkg.ImportPath, doc.AllDecls)

	htmlBuf := new(bytes.Buffer)
	fmt.Fprintln(htmlBuf, `<!-- auto-generated from robpike.io/ivy package doc -->`)
	fmt.Fprintln(htmlBuf, head)
	fmt.Fprintln(htmlBuf, `<body>`)
	doc.ToHTML(htmlBuf, docPkg.Doc, nil)
	fmt.Fprintln(htmlBuf, `</body></html>`)

	goBuf := new(bytes.Buffer)
	fmt.Fprintf(goBuf, "package mobile\n\n")
	fmt.Fprintf(goBuf, "// GENERATED; DO NOT EDIT\n")
	fmt.Fprintf(goBuf, "const help = `%s`\n", sanitize(htmlBuf.Bytes()))

	buf, err := format.Source(goBuf.Bytes())
	if err != nil {
		log.Fatalf("failed to gofmt: %v", err)
	}
	os.Stdout.Write(buf)
}
Пример #6
0
// PackageDoc gets the documentation for the package with the specified import
// path and writes it to out.
func PackageDoc(ctxt *build.Context, fset *token.FileSet, srcDir string, importPath string) (*Doc, error) {
	buildPkg, err := ctxt.Import(importPath, srcDir, build.ImportComment)
	if err != nil {
		return nil, err
	}
	// only parse .go files in the specified package
	filter := func(info os.FileInfo) bool {
		for _, fname := range buildPkg.GoFiles {
			if fname == info.Name() {
				return true
			}
		}
		return false
	}
	// TODO we've already parsed the files via go/loader...can we avoid doing it again?
	pkgs, err := parser.ParseDir(fset, buildPkg.Dir, filter, parser.PackageClauseOnly|parser.ParseComments)
	if err != nil {
		return nil, err
	}
	if astPkg, ok := pkgs[buildPkg.Name]; ok {
		docPkg := doc.New(astPkg, importPath, 0)
		// TODO: we could also include package-level constants, vars, and functions (like the go doc command)
		return &Doc{
			Name: buildPkg.Name,
			Decl: "package " + buildPkg.Name, // TODO: add '// import "pkg"' (like godoc)
			Doc:  docPkg.Doc,
		}, nil
	}
	return nil, errors.New("No documentation found for " + buildPkg.Name)
}
Пример #7
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)
}
Пример #8
0
func NewPackageView(pkg *ast.Package, fset *token.FileSet, expr bool) (*PackageView, error) {
	p := new(PackageView)
	p.fset = fset
	p.pkg = pkg
	p.pdoc = doc.New(pkg, pkg.Name, doc.AllDecls)
	p.expr = expr
	return p, nil
}
Пример #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
}
Пример #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
}
Пример #11
0
func getDoc(dir string) (Doc, error) {
	bi, err := build.ImportDir(dir, 0)
	if err != nil {
		return Doc{}, nil
	}

	ip, err := importPath(dir)
	if err != nil {
		return Doc{}, err
	}

	filter := func(fi os.FileInfo) bool {
		if fi.IsDir() {
			return false
		}
		nm := fi.Name()
		for _, f := range append(bi.GoFiles, bi.CgoFiles...) {
			if nm == f {
				return true
			}
		}
		return false
	}

	pkgs, err := parser.ParseDir(token.NewFileSet(), bi.Dir, filter, parser.ParseComments)
	if err != nil {
		return Doc{}, err
	}

	pkg := pkgs[bi.Name]
	docs := doc.New(pkg, bi.ImportPath, 0)

	bugs := []string{}
	for _, bug := range docs.Notes["BUG"] {
		bugs = append(bugs, bug.Body)
	}

	name := bi.Name
	if name == "main" {
		name = filepath.Base(bi.Dir)
	}

	//get import path without the github.com/
	pathelms := strings.Split(ip, "/")[1:]
	repo := path.Join(pathelms...)

	return Doc{
		Name:     name,
		Import:   ip,
		Synopsis: bi.Doc,
		Doc:      fmtDoc(docs.Doc),
		Today:    today(),
		RepoPath: repo,
		Bugs:     bugs,
		Library:  bi.Name != "main",
		Command:  bi.Name == "main",
	}, nil
}
Пример #12
0
Файл: gen.go Проект: logan/heim
func run() error {
	pkg, err := build.Import("euphoria.io/heim/proto", "", build.FindOnly)
	if err != nil {
		return fmt.Errorf("import error: %s", err)
	}

	if pkg.SrcRoot == "" {
		return fmt.Errorf("error: can't find source for package euphoria.io/heim/proto")
	}

	pkgs, err := parser.ParseDir(
		token.NewFileSet(), filepath.Join(pkg.SrcRoot, "euphoria.io/heim/proto"), nil,
		parser.ParseComments)
	if err != nil {
		return fmt.Errorf("parse error: %s", err)
	}

	obs := (*objects)(doc.New(pkgs["proto"], "euphoria.io/heim/proto", 0))
	ps := sortObjects(obs)
	ts := types{}
	t := template.New("api.md").Funcs(template.FuncMap{
		"object": obs.tmplObject,
		"others": ps.tmplOthers,
		"packet": ps.tmplPacket,

		"linkType":     ts.linkType,
		"registerType": ts.registerType,
	})

	ts.registerType("bool")
	ts.registerType("int")
	ts.registerType("object")
	ts.registerType("string")
	ts.registerType("AccountView")
	ts.registerType("AuthOption")
	ts.registerType("Message")
	ts.registerType("PacketType")
	ts.registerType("PersonalAccountView")
	ts.registerType("SessionView")
	ts.registerType("Snowflake")
	ts.registerType("Time")
	ts.registerType("UserID")

	gendir := filepath.Join(pkg.SrcRoot, "euphoria.io/heim/doc/gen")
	if err := os.Chdir(gendir); err != nil {
		return fmt.Errorf("chdir error: %s: %s", gendir, err)
	}

	if _, err := t.ParseGlob("*.md"); err != nil {
		return fmt.Errorf("template parse error: %s", err)
	}
	if err := t.Execute(os.Stdout, nil); err != nil {
		return fmt.Errorf("template render error: %s", err)
	}

	return nil
}
Пример #13
0
func NewPackageDeclFromAstPackage(astPkg *ast.Package, fullImportPath string) *PackageDecl {
	output := &PackageDecl{TypeMap: make(map[string]*TypeDecl)}

	docPkg := doc.New(astPkg, fullImportPath, doc.AllMethods)
	for _, t := range docPkg.Types {
		output.TypeMap[t.Name] = NewTypeDeclFromDocType(t)
	}
	return output
}
Пример #14
0
func tryImport(root, relpath string) error {
	path := filepath.Join(root, relpath)
	ctx := build.Default
	dir, err := ctx.ImportDir(path, 0)
	if _, nogo := err.(*build.NoGoError); nogo {
		return nil
	}
	if err != nil {
		return fmt.Errorf("ImportDir failed: %v", err)
	}

	pkgFiles := append(dir.GoFiles, dir.CgoFiles...)
	fullPkgsFiles := make([]string, 0, len(pkgFiles))

	for _, p := range pkgFiles {
		fullPkgsFiles = append(fullPkgsFiles, filepath.Join(path, p))
	}

	pkg, err := parseFiles(fullPkgsFiles)
	if err != nil {
		if err == errNoPackagesFound {
			// that error is eaten silently
			return nil
		}
		return fmt.Errorf("Failed to parse pkg %s/%s: %v", root, relpath, err)
	}

	pdoc := doc.New(pkg, relpath, 0)

	outputValues(relpath, pdoc.Consts, "#pkg-constants", "const")
	outputValues(relpath, pdoc.Vars, "#pkg-variables", "var")

	for _, tp := range pdoc.Types {
		outputCDB(relpath+"/"+tp.Name+" "+ppType(tp)+maybeDoc(tp.Doc, tp.Name),
			"godoc:"+relpath+"#"+tp.Name)
		for _, fun := range tp.Methods {
			typename := fun.Recv
			if typename[0] == '*' {
				typename = typename[1:]
			}
			outputCDB(buildFuncKey(relpath, fun),
				"godoc:"+relpath+"#"+typename+"."+fun.Name)
		}
		for _, fun := range tp.Funcs {
			outputCDB(buildFuncKey(relpath, fun),
				"godoc:"+relpath+"#"+fun.Name)
		}
	}

	for _, fun := range pdoc.Funcs {
		outputCDB(buildFuncKey(relpath, fun),
			"godoc:"+relpath+"#"+fun.Name)
	}

	return nil
}
Пример #15
0
func getDocPackageMode(bpkg *build.Package, err error, mode doc.Mode) (dpkg *doc.Package, err2 error) {
	if err != nil {
		return nil, err
	}
	apkg, err := AstPackageFromBuildPackage(bpkg)
	if err != nil {
		return nil, err
	}
	return doc.New(apkg, bpkg.ImportPath, mode), nil
}
Пример #16
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
}
Пример #17
0
Файл: pkg.go Проект: sreis/go
// parsePackage turns the build package we found into a parsed package
// we can then use to generate documentation.
func parsePackage(writer io.Writer, pkg *build.Package, userPath string) *Package {
	fs := token.NewFileSet()
	// include tells parser.ParseDir which files to include.
	// That means the file must be in the build package's GoFiles or CgoFiles
	// list only (no tag-ignored files, tests, swig or other non-Go files).
	include := func(info os.FileInfo) bool {
		for _, name := range pkg.GoFiles {
			if name == info.Name() {
				return true
			}
		}
		for _, name := range pkg.CgoFiles {
			if name == info.Name() {
				return true
			}
		}
		return false
	}
	pkgs, err := parser.ParseDir(fs, pkg.Dir, include, parser.ParseComments)
	if err != nil {
		log.Fatal(err)
	}
	// Make sure they are all in one package.
	if len(pkgs) != 1 {
		log.Fatalf("multiple packages in directory %s", pkg.Dir)
	}
	astPkg := pkgs[pkg.Name]

	// TODO: go/doc does not include typed constants in the constants
	// list, which is what we want. For instance, time.Sunday is of type
	// time.Weekday, so it is defined in the type but not in the
	// Consts list for the package. This prevents
	//	go doc time.Sunday
	// from finding the symbol. Work around this for now, but we
	// should fix it in go/doc.
	// A similar story applies to factory functions.
	docPkg := doc.New(astPkg, pkg.ImportPath, doc.AllDecls)
	for _, typ := range docPkg.Types {
		docPkg.Consts = append(docPkg.Consts, typ.Consts...)
		docPkg.Vars = append(docPkg.Vars, typ.Vars...)
		docPkg.Funcs = append(docPkg.Funcs, typ.Funcs...)
	}

	return &Package{
		writer:   writer,
		name:     pkg.Name,
		userPath: userPath,
		pkg:      astPkg,
		file:     ast.MergePackageFiles(astPkg, 0),
		doc:      docPkg,
		build:    pkg,
		fs:       fs,
	}
}
Пример #18
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
}
Пример #19
0
func ParsePackageInfo(name, lang string) (pkg *PackageInfo, err error) {
	type PkgInfo struct {
		Dir        string // directory containing package sources
		Name       string // package name
		ImportPath string // import path of package in dir
	}

	var pkgInfo PkgInfo
	listOut, err := exec.Command(`go`, `list`, `-json`, name).Output()
	if err != nil {
		return
	}
	err = json.Unmarshal(listOut, &pkgInfo)
	if err != nil {
		return
	}

	fset := token.NewFileSet()
	past, err := parser.ParseDir(fset, pkgInfo.Dir,
		func(fi os.FileInfo) bool {
			if strings.HasSuffix(fi.Name(), "_test.go") {
				return false
			}
			return true
		},
		parser.ParseComments,
	)
	if err != nil {
		return
	}

	var mode doc.Mode
	if pkgInfo.ImportPath == "builtin" {
		mode = doc.AllDecls
	}
	pdoc := doc.New(past[pkgInfo.Name], pkgInfo.ImportPath, mode)
	pdocLocal := local.Package(lang, pkgInfo.ImportPath)

	pkg = &PackageInfo{
		Lang:      lang,
		FSet:      fset,
		PAst:      past[pkgInfo.Name],
		PDoc:      pdoc,
		PDocLocal: pdocLocal,
		PDocMap:   make(map[string]string),
	}
	pkg.initDocTable("", pkg.PDoc)
	if pkg.PDocLocal != nil {
		pkg.initDocTable(lang, pkg.PDocLocal)
	}
	return
}
Пример #20
0
func getPageInfo(pkgName, diskPath string) (pi PageInfo, err error) {
	if pkgName == pathpkg.Join(domainName, pkgPattern) ||
		pkgName == pathpkg.Join(domainName, cmdPattern) ||
		pkgName == pathpkg.Join(domainName, appPattern) {
		pi.Dirname = diskPath
		pi.populateDirs(diskPath, -1)
		return
	}
	bpkg, err := build.ImportDir(diskPath, 0)
	if err != nil {
		if _, ok := err.(*build.NoGoError); ok {
			pi.populateDirs(diskPath, -1)
			return pi, nil
		}
		return
	}
	inSet := make(map[string]bool)
	for _, name := range bpkg.GoFiles {
		if name == fileembedPattern {
			continue
		}
		inSet[filepath.Base(name)] = true
	}

	pi.FSet = token.NewFileSet()
	filter := func(fi os.FileInfo) bool {
		return inSet[fi.Name()]
	}
	aPkgMap, err := parser.ParseDir(pi.FSet, diskPath, filter, parser.ParseComments)
	if err != nil {
		return
	}
	aPkg := aPkgMap[pathpkg.Base(pkgName)]
	if aPkg == nil {
		for _, v := range aPkgMap {
			aPkg = v
			break
		}
		if aPkg == nil {
			err = errors.New("no apkg found?")
			return
		}
	}

	pi.Dirname = diskPath
	pi.PDoc = doc.New(aPkg, pkgName, 0)
	pi.IsPkg = strings.Contains(pkgName, domainName+pkgPattern)

	// get directory information
	pi.populateDirs(diskPath, -1)
	return
}
Пример #21
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
}
Пример #22
0
func main() {
	flag.Parse()
	path := flag.Arg(0)
	if path == "" {
		path = "."
	}
	fset = token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, path, func(file os.FileInfo) bool {
		name := file.Name()
		if name[0] != '.' && strings.HasSuffix(name, ".go") && !strings.HasSuffix(name, "_test.go") {
			return true
		}
		return false
	}, parser.ParseComments)
	if err != nil {
		fmt.Fprintf(os.Stderr, "Could not parse \"%s\": %v\n", path, err)
	}

	importLine := ""
	if read, err := ioutil.ReadFile(filepath.Join(path, ".import")); err == nil {
		importLine = strings.Split(string(read), "\n")[0]
	}

	var buffer bytes.Buffer

	// There should be only 1 package, but...
	for _, pkg := range pkgs {
		document := doc.New(pkg, ".", 0)

		fmt.Fprintf(&buffer, "# %s\n--\n", document.Name)
		if importLine != "" {
			fmt.Fprintf(&buffer, "    import \"%s\"\n\n", importLine)
		}
		fmt.Fprintf(&buffer, "%s\n", headifySynopsis(document.Doc))
		fmt.Fprintf(&buffer, "## Usage\n\n")
		writeConstantSection(&buffer, document.Consts)
		writeVariableSection(&buffer, document.Vars)
		writeFunctionSection(&buffer, "####", document.Funcs)
		writeTypeSection(&buffer, document.Types)
	}

	if debug {
		return
	}

	fmt.Println(strings.TrimSpace(buffer.String()))

	if *signature {
		fmt.Printf("\n--\n**godocdown** http://github.com/robertkrimen/godocdown\n")
	}
}
Пример #23
0
func (w *Walker) WalkPackage(name, dir string) {
	log.Printf("package %s", name)
	pop := w.pushScope("pkg " + name)
	defer pop()

	info, err := build.ScanDir(dir)
	if err != nil {
		log.Fatalf("pkg %q, dir %q: ScanDir: %v", name, dir, err)
	}

	apkg := &ast.Package{
		Files: make(map[string]*ast.File),
	}

	files := append(append([]string{}, info.GoFiles...), info.CgoFiles...)
	for _, file := range files {
		f, err := parser.ParseFile(w.fset, filepath.Join(dir, file), nil, 0)
		if err != nil {
			log.Fatalf("error parsing package %s, file %s: %v", name, file, err)
		}
		apkg.Files[file] = f
	}

	w.curPackageName = name
	w.curPackage = apkg
	w.prevConstType = map[string]string{}
	for name, afile := range apkg.Files {
		w.walkFile(filepath.Join(dir, name), afile)
	}

	// Now that we're done walking types, vars and consts
	// in the *ast.Package, use go/doc to do the rest
	// (functions and methods). This is done here because
	// go/doc is destructive.  We can't use the
	// *ast.Package after this.
	dpkg := doc.New(apkg, name, 0)

	for _, t := range dpkg.Types {
		// Move funcs up to the top-level, not hiding in the Types.
		dpkg.Funcs = append(dpkg.Funcs, t.Funcs...)

		for _, m := range t.Methods {
			w.walkFuncDecl(m.Decl)
		}
	}

	for _, f := range dpkg.Funcs {
		w.walkFuncDecl(f.Decl)
	}
}
Пример #24
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)
}
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)
}
Пример #26
0
func getPackageDoc(dir string) (*doc.Package, error) {
	fset := token.NewFileSet()
	pkgs, err := parser.ParseDir(fset, dir, isNotGoTestFile, parser.ParseComments)
	if err != nil {
		return nil, err
	}

	// return the first pkg
	for pkgName, pkgAST := range pkgs {
		importPath := dir + "/" + pkgName
		return doc.New(pkgAST, importPath, doc.AllDecls), nil
	}

	return nil, nil
}
Пример #27
0
func main() {
	flag.Parse()
	fset := token.NewFileSet()
	nheadings := 0
	err := filepath.Walk(*root, func(path string, fi os.FileInfo, err error) error {
		if !fi.IsDir() {
			return nil
		}
		pkgs, err := parser.ParseDir(fset, path, isGoFile, parser.ParseComments)
		if err != nil {
			if *verbose {
				fmt.Fprintln(os.Stderr, err)
			}
			return nil
		}
		for _, pkg := range pkgs {
			d := doc.New(pkg, path, doc.Mode(0))
			list := appendHeadings(nil, d.Doc)
			for _, d := range d.Consts {
				list = appendHeadings(list, d.Doc)
			}
			for _, d := range d.Types {
				list = appendHeadings(list, d.Doc)
			}
			for _, d := range d.Vars {
				list = appendHeadings(list, d.Doc)
			}
			for _, d := range d.Funcs {
				list = appendHeadings(list, d.Doc)
			}
			if len(list) > 0 {
				// directories may contain multiple packages;
				// print path and package name
				fmt.Printf("%s (package %s)\n", path, pkg.Name)
				for _, h := range list {
					fmt.Printf("\t%s\n", h)
				}
				nheadings += len(list)
			}
		}
		return nil
	})
	if err != nil {
		fmt.Fprintln(os.Stderr, err)
		os.Exit(1)
	}
	fmt.Println(nheadings, "headings found")
}
Пример #28
0
func newPackageFrom(bpkg *build.Package, p *types.Package) (*bind.Package, error) {

	var pkgast *ast.Package
	pkgs, err := parser.ParseDir(fset, bpkg.Dir, nil, parser.ParseComments)
	if err != nil {
		return nil, err
	}
	pkgast = pkgs[p.Name()]
	if pkgast == nil {
		return nil, fmt.Errorf("gopy: could not find AST for package %q", p.Name())
	}

	pkgdoc := doc.New(pkgast, bpkg.ImportPath, 0)

	return bind.NewPackage(p, pkgdoc)
}
Пример #29
0
func builtinPackage() *doc.Package {
	buildPkg, err := build.Import("builtin", "", build.ImportComment)
	// should never fail
	if err != nil {
		panic(err)
	}
	include := func(info os.FileInfo) bool {
		return info.Name() == "builtin.go"
	}
	fs := token.NewFileSet()
	astPkgs, err := parser.ParseDir(fs, buildPkg.Dir, include, parser.ParseComments)
	if err != nil {
		panic(err)
	}
	astPkg := astPkgs["builtin"]
	return doc.New(astPkg, buildPkg.ImportPath, doc.AllDecls)
}
Пример #30
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
}