diff options
author | Robert Griesemer <gri@golang.org> | 2009-07-29 17:01:09 -0700 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2009-07-29 17:01:09 -0700 |
commit | 53abf93013954216d6521b5a10a2202f7d7bcb36 (patch) | |
tree | fe5b6fe43fb4577157bd2c05385b8db29866ebcc /src/pkg/go | |
parent | 297317cfed550069aeb8442f968d5cdcec9908aa (diff) | |
download | golang-53abf93013954216d6521b5a10a2202f7d7bcb36.tar.gz |
parser:
- Changed filter function for parser.ParsePackage to
take an *os.Dir instead of a filename for more
powerful filters
- Removed TODO in ast.PackageInterface: Now collect
package comments from all package files
- Cleanups in godoc: Use the new ParsePackage and
PackageInterface functions; as a result computing
package information is much simpler now.
R=rsc
DELTA=285 (80 added, 110 deleted, 95 changed)
OCL=32473
CL=32486
Diffstat (limited to 'src/pkg/go')
-rw-r--r-- | src/pkg/go/ast/filter.go | 79 | ||||
-rw-r--r-- | src/pkg/go/parser/interface.go | 19 | ||||
-rw-r--r-- | src/pkg/go/parser/parser_test.go | 11 |
3 files changed, 73 insertions, 36 deletions
diff --git a/src/pkg/go/ast/filter.go b/src/pkg/go/ast/filter.go index b85eddb40..28277af76 100644 --- a/src/pkg/go/ast/filter.go +++ b/src/pkg/go/ast/filter.go @@ -190,40 +190,71 @@ func FilterExports(src *File) bool { } -// PackageInterface returns an AST containing only the exported declarations -// of the package pkg. The pkg AST is modified by PackageInterface. +// separator is an empty //-style comment that is interspersed between +// different comment groups when they are concatenated into a single group // -func PackageInterface(pkg *Package) *File { - // filter each package file - for filename, s := range pkg.Files { - if !FilterExports(s) { - pkg.Files[filename] = nil, false; +var separator = &Comment{noPos, []byte{'/', '/'}}; + + +// PackageExports returns an AST containing only the exported declarations +// of the package pkg. PackageExports modifies the pkg AST. +// +func PackageExports(pkg *Package) *File { + // Collect all source files with exported declarations and count + // the number of package comments and declarations in all files. + files := make([]*File, len(pkg.Files)); + ncomments := 0; + ndecls := 0; + i := 0; + for _, f := range pkg.Files { + if f.Doc != nil { + ncomments += len(f.Doc.List) + 1; // +1 for separator + } + if FilterExports(f) { + ndecls += len(f.Decls); + files[i] = f; + i++; } } + files = files[0 : i]; - // compute total number of top-level declarations in all source files + // Collect package comments from all package files into a single + // CommentGroup - the collected package documentation. The order + // is unspecified. In general there should be only one file with + // a package comment; but it's better to collect extra comments + // than drop them on the floor. var doc *CommentGroup; - n := 0; - for _, src := range pkg.Files { - if doc == nil && src.Doc != nil { - // TODO(gri) what to do with multiple package comments? - doc = src.Doc; + if ncomments > 0 { + list := make([]*Comment, ncomments - 1); // -1: no separator before first group + i := 0; + for _, f := range pkg.Files { + if f.Doc != nil { + if i > 0 { + // not the first group - add separator + list[i] = separator; + i++; + } + for _, c := range f.Doc.List { + list[i] = c; + i++ + } + } } - n += len(src.Decls); + doc = &CommentGroup{list, nil}; } - // collect top-level declarations of all source files - decls := make([]Decl, n); - i := 0; - for _, src := range pkg.Files { - for _, d := range src.Decls { - decls[i] = d; - i++; + // Collect exported declarations from all package files. + var decls []Decl; + if ndecls > 0 { + decls = make([]Decl, ndecls); + i := 0; + for _, f := range files { + for _, d := range f.Decls { + decls[i] = d; + i++; + } } } - // TODO(gri) should also collect comments so that this function - // can be used by godoc. - var noPos token.Position; return &File{doc, noPos, &Ident{noPos, pkg.Name}, decls, nil}; } diff --git a/src/pkg/go/parser/interface.go b/src/pkg/go/parser/interface.go index f3a46da40..5fa60c1cd 100644 --- a/src/pkg/go/parser/interface.go +++ b/src/pkg/go/parser/interface.go @@ -148,30 +148,31 @@ func ParsePkgFile(pkgname, filename string, mode uint) (*ast.File, os.Error) { // ParsePackage parses all files in the directory specified by path and // returns an AST representing the package found. The set of files may be // restricted by providing a non-nil filter function; only the files with -// (path-local) filenames passing through the filter are considered. If -// zero or more then one package is found, an error is returned. Mode -// flags that control the amount of source text parsed are ignored. +// os.Dir entries passing through the filter are considered. +// If ParsePackage does not find exactly one package, it returns an error. +// Mode flags that control the amount of source text parsed are ignored. // -func ParsePackage(path string, filter func(string) bool, mode uint) (*ast.Package, os.Error) { +func ParsePackage(path string, filter func(*os.Dir) bool, mode uint) (*ast.Package, os.Error) { fd, err := os.Open(path, os.O_RDONLY, 0); if err != nil { return nil, err; } - list, err := fd.Readdirnames(-1); + list, err := fd.Readdir(-1); if err != nil { return nil, err; } name := ""; files := make(map[string]*ast.File); - for _, filename := range list { - if filter == nil || filter(filename) { - src, err := ParsePkgFile(name, pathutil.Join(path, filename), mode); + for i := 0; i < len(list); i++ { + entry := &list[i]; + if filter == nil || filter(entry) { + src, err := ParsePkgFile(name, pathutil.Join(path, entry.Name), mode); if err != nil { return nil, err; } - files[filename] = src; + files[entry.Name] = src; if name == "" { name = src.Name.Value; } diff --git a/src/pkg/go/parser/parser_test.go b/src/pkg/go/parser/parser_test.go index b6618d06e..29719b6de 100644 --- a/src/pkg/go/parser/parser_test.go +++ b/src/pkg/go/parser/parser_test.go @@ -62,7 +62,7 @@ func TestParse3(t *testing.T) { } -func filter(filename string) bool { +func nameFilter(filename string) bool { switch filename { case "parser.go": case "interface.go": @@ -74,9 +74,14 @@ func filter(filename string) bool { } +func dirFilter(d *os.Dir) bool { + return nameFilter(d.Name); +} + + func TestParse4(t *testing.T) { path := "."; - pkg, err := ParsePackage(path, filter, 0); + pkg, err := ParsePackage(path, dirFilter, 0); if err != nil { t.Fatalf("ParsePackage(%s): %v", path, err); } @@ -84,7 +89,7 @@ func TestParse4(t *testing.T) { t.Errorf("incorrect package name: %s", pkg.Name); } for filename, _ := range pkg.Files { - if !filter(filename) { + if !nameFilter(filename) { t.Errorf("unexpected package file: %s", filename); } } |