1
0
mirror of https://github.com/golang/go synced 2024-11-22 03:44:39 -07:00

go/ast: adjustments to filter function

CL 4938041 made some incorrect changes to the filter
function which caused a different doc/codelab/wiki/index.html
file to be generated.

Added FilterFileExports and FilterPackageExports function.
Same as the existing FileExpors/PackageExports functions
but using shared code. The old functions will be removed
in the next CL.

R=r, rsc
CC=golang-dev
https://golang.org/cl/4932048
This commit is contained in:
Robert Griesemer 2011-08-23 14:17:18 -07:00
parent b99d722963
commit cde06f541f
2 changed files with 57 additions and 23 deletions

View File

@ -135,7 +135,7 @@ func declExports(decl Decl) bool {
// and their associated information (such as type, initial value, or function // and their associated information (such as type, initial value, or function
// body) are removed. Non-exported fields and methods of exported types are // body) are removed. Non-exported fields and methods of exported types are
// stripped, and the function bodies of exported functions are set to nil. // stripped, and the function bodies of exported functions are set to nil.
// The File.comments list is not changed. // The File.Comments list is not changed.
// //
// FileExports returns true if there is an exported declaration; it returns // FileExports returns true if there is an exported declaration; it returns
// false otherwise. // false otherwise.
@ -224,7 +224,9 @@ func filterFieldList(fields *FieldList, filter Filter) (removedFields bool) {
keepField = len(f.Names) > 0 keepField = len(f.Names) > 0
} }
if keepField { if keepField {
filterType(f.Type, filter) if filter == exportFilter {
filterType(f.Type, filter)
}
list[j] = f list[j] = f
j++ j++
} }
@ -286,15 +288,19 @@ func filterSpec(spec Spec, f Filter) bool {
case *ValueSpec: case *ValueSpec:
s.Names = filterIdentList(s.Names, f) s.Names = filterIdentList(s.Names, f)
if len(s.Names) > 0 { if len(s.Names) > 0 {
filterType(s.Type, f) if f == exportFilter {
filterType(s.Type, f)
}
return true return true
} }
case *TypeSpec: case *TypeSpec:
if f(s.Name.Name) { if f(s.Name.Name) {
filterType(s.Type, f) if f == exportFilter {
filterType(s.Type, f)
}
return true return true
} }
if f != IsExported { if f != exportFilter {
// For general filtering (not just exports), // For general filtering (not just exports),
// filter type even if name is not filtered // filter type even if name is not filtered
// out. // out.
@ -330,7 +336,9 @@ func FilterDecl(decl Decl, f Filter) bool {
d.Specs = filterSpecList(d.Specs, f) d.Specs = filterSpecList(d.Specs, f)
return len(d.Specs) > 0 return len(d.Specs) > 0
case *FuncDecl: case *FuncDecl:
d.Body = nil // strip body if f == exportFilter {
d.Body = nil // strip body
}
return f(d.Name.Name) return f(d.Name.Name)
} }
return false return false
@ -339,16 +347,13 @@ func FilterDecl(decl Decl, f Filter) bool {
// FilterFile trims the AST for a Go file in place by removing all // FilterFile trims the AST for a Go file in place by removing all
// names from top-level declarations (including struct field and // names from top-level declarations (including struct field and
// interface method names, but not from parameter lists) that don't // interface method names, but not from parameter lists) that don't
// pass through the filter f. Function bodies are set to nil. // pass through the filter f. If the declaration is empty afterwards,
// If the declaration is empty afterwards, the declaration is // the declaration is removed from the AST. The File.Comments list
// removed from the AST. The File.comments list is not changed. // is not changed.
// //
// FilterFile returns true if there are any top-level declarations // FilterFile returns true if there are any top-level declarations
// left after filtering; it returns false otherwise. // left after filtering; it returns false otherwise.
// //
// To trim an AST such that only exported nodes remain, call
// FilterFile with IsExported as filter function.
//
func FilterFile(src *File, f Filter) bool { func FilterFile(src *File, f Filter) bool {
j := 0 j := 0
for _, d := range src.Decls { for _, d := range src.Decls {
@ -361,20 +366,17 @@ func FilterFile(src *File, f Filter) bool {
return j > 0 return j > 0
} }
// FilterPackage trims the AST for a Go package in place by removing all // FilterPackage trims the AST for a Go package in place by removing
// names from top-level declarations (including struct field and // all names from top-level declarations (including struct field and
// interface method names, but not from parameter lists) that don't // interface method names, but not from parameter lists) that don't
// pass through the filter f. Function bodies are set to nil. // pass through the filter f. If the declaration is empty afterwards,
// If the declaration is empty afterwards, the declaration is // the declaration is removed from the AST. The pkg.Files list is not
// removed from the AST. The pkg.Files list is not changed, so // changed, so that file names and top-level package comments don't get
// that file names and top-level package comments don't get lost. // lost.
// //
// FilterPackage returns true if there are any top-level declarations // FilterPackage returns true if there are any top-level declarations
// left after filtering; it returns false otherwise. // left after filtering; it returns false otherwise.
// //
// To trim an AST such that only exported nodes remain, call
// FilterPackage with IsExported as filter function.
//
func FilterPackage(pkg *Package, f Filter) bool { func FilterPackage(pkg *Package, f Filter) bool {
hasDecls := false hasDecls := false
for _, src := range pkg.Files { for _, src := range pkg.Files {
@ -385,6 +387,38 @@ func FilterPackage(pkg *Package, f Filter) bool {
return hasDecls return hasDecls
} }
// exportFilter is a special filter function to extract exported nodes.
func exportFilter(name string) bool {
return IsExported(name)
}
// TODO(gri): Remove the FileExports and PackageExports (above).
// FilterFileExports trims the AST for a Go source file in place such that
// only exported nodes remain: all top-level identifiers which are not exported
// and their associated information (such as type, initial value, or function
// body) are removed. Non-exported fields and methods of exported types are
// stripped, and the function bodies of exported functions are set to nil.
// The File.Comments list is not changed.
//
// FilterFileExports returns true if there are exported declarationa;
// it returns false otherwise.
//
func FilterFileExports(src *File) bool {
return FilterFile(src, exportFilter)
}
// FilterPackageExports trims the AST for a Go package in place such that
// only exported nodes remain. The pkg.Files list is not changed, so that
// file names and top-level package comments don't get lost.
//
// FilterPackageExports returns true if there are exported declarations;
// it returns false otherwise.
//
func FilterPackageExports(pkg *Package) bool {
return FilterPackage(pkg, exportFilter)
}
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Merging of package files // Merging of package files

View File

@ -26,7 +26,7 @@ import (
// For a short test run, limit the number of files to a few. // For a short test run, limit the number of files to a few.
// Set to a large value to test all files under GOROOT. // Set to a large value to test all files under GOROOT.
const maxFiles = 10 const maxFiles = 10000
type visitor struct { type visitor struct {
t *testing.T t *testing.T
@ -72,7 +72,7 @@ func (v *visitor) VisitFile(path string, f *os.FileInfo) {
} }
b1 := ast.FileExports(f1) b1 := ast.FileExports(f1)
b2 := ast.FilterFile(f2, ast.IsExported) b2 := ast.FilterFileExports(f2)
if b1 != b2 { if b1 != b2 {
v.t.Errorf("filtering failed (a): %s", path) v.t.Errorf("filtering failed (a): %s", path)
return return