summaryrefslogtreecommitdiff
path: root/src/pkg/go
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2009-07-29 17:01:09 -0700
committerRobert Griesemer <gri@golang.org>2009-07-29 17:01:09 -0700
commit53abf93013954216d6521b5a10a2202f7d7bcb36 (patch)
treefe5b6fe43fb4577157bd2c05385b8db29866ebcc /src/pkg/go
parent297317cfed550069aeb8442f968d5cdcec9908aa (diff)
downloadgolang-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.go79
-rw-r--r--src/pkg/go/parser/interface.go19
-rw-r--r--src/pkg/go/parser/parser_test.go11
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);
}
}