From e656a184cb32e07cd91bde3f3bcc72a1ac2dd6e8 Mon Sep 17 00:00:00 2001 From: Robert Griesemer Date: Tue, 23 Aug 2011 16:03:42 -0700 Subject: [PATCH] go/ast cleanup: base File/PackageExports on FilterFile/FilterPackage code R=r, rsc CC=golang-dev https://golang.org/cl/4927046 --- src/pkg/go/ast/filter.go | 190 +++---------------------------- src/pkg/go/parser/filter_test.go | 91 --------------- 2 files changed, 14 insertions(+), 267 deletions(-) delete mode 100644 src/pkg/go/parser/filter_test.go diff --git a/src/pkg/go/ast/filter.go b/src/pkg/go/ast/filter.go index 6d00d11970..1bd8990f83 100644 --- a/src/pkg/go/ast/filter.go +++ b/src/pkg/go/ast/filter.go @@ -9,164 +9,34 @@ import "go/token" // ---------------------------------------------------------------------------- // Export filtering -func identListExports(list []*Ident) []*Ident { - j := 0 - for _, x := range list { - if x.IsExported() { - list[j] = x - j++ - } - } - return list[0:j] -} - -func fieldListExports(fields *FieldList) (removedFields bool) { - if fields == nil { - return - } - list := fields.List - j := 0 - for _, f := range list { - exported := false - if len(f.Names) == 0 { - // anonymous field - // (Note that a non-exported anonymous field - // may still refer to a type with exported - // fields, so this is not absolutely correct. - // However, this cannot be done w/o complete - // type information.) - name := fieldName(f.Type) - exported = name != nil && name.IsExported() - } else { - n := len(f.Names) - f.Names = identListExports(f.Names) - if len(f.Names) < n { - removedFields = true - } - exported = len(f.Names) > 0 - } - if exported { - typeExports(f.Type) - list[j] = f - j++ - } - } - if j < len(list) { - removedFields = true - } - fields.List = list[0:j] - return -} - -func paramListExports(fields *FieldList) { - if fields == nil { - return - } - for _, f := range fields.List { - typeExports(f.Type) - } -} - -func typeExports(typ Expr) { - switch t := typ.(type) { - case *ArrayType: - typeExports(t.Elt) - case *StructType: - if fieldListExports(t.Fields) { - t.Incomplete = true - } - case *FuncType: - paramListExports(t.Params) - paramListExports(t.Results) - case *InterfaceType: - if fieldListExports(t.Methods) { - t.Incomplete = true - } - case *MapType: - typeExports(t.Key) - typeExports(t.Value) - case *ChanType: - typeExports(t.Value) - } -} - -func specExports(spec Spec) bool { - switch s := spec.(type) { - case *ValueSpec: - s.Names = identListExports(s.Names) - if len(s.Names) > 0 { - typeExports(s.Type) - return true - } - case *TypeSpec: - if s.Name.IsExported() { - typeExports(s.Type) - return true - } - } - return false -} - -func specListExports(list []Spec) []Spec { - j := 0 - for _, s := range list { - if specExports(s) { - list[j] = s - j++ - } - } - return list[0:j] -} - -func declExports(decl Decl) bool { - switch d := decl.(type) { - case *GenDecl: - d.Specs = specListExports(d.Specs) - return len(d.Specs) > 0 - case *FuncDecl: - d.Body = nil // strip body - return d.Name.IsExported() - } - return false +// exportFilter is a special filter function to extract exported nodes. +func exportFilter(name string) bool { + return IsExported(name) } -// FileExports trims the AST for a Go source file in place such that only -// exported nodes remain: all top-level identifiers which are not exported +// FileExports 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. // -// FileExports returns true if there is an exported declaration; it returns -// false otherwise. +// FileExports returns true if there are exported declarationa; +// it returns false otherwise. // func FileExports(src *File) bool { - j := 0 - for _, d := range src.Decls { - if declExports(d) { - src.Decls[j] = d - j++ - } - } - src.Decls = src.Decls[0:j] - return j > 0 + return FilterFile(src, exportFilter) } -// PackageExports 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. +// PackageExports 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. // -// PackageExports returns true if there is an exported declaration; it -// returns false otherwise. +// PackageExports returns true if there are exported declarations; +// it returns false otherwise. // func PackageExports(pkg *Package) bool { - hasExports := false - for _, f := range pkg.Files { - if FileExports(f) { - hasExports = true - } - } - return hasExports + return FilterPackage(pkg, exportFilter) } // ---------------------------------------------------------------------------- @@ -387,38 +257,6 @@ func FilterPackage(pkg *Package, f Filter) bool { 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 diff --git a/src/pkg/go/parser/filter_test.go b/src/pkg/go/parser/filter_test.go deleted file mode 100644 index 856a1c0c57..0000000000 --- a/src/pkg/go/parser/filter_test.go +++ /dev/null @@ -1,91 +0,0 @@ -// Copyright 2011 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// A test that ensures that ast.FileExports(file) and -// ast.FilterFile(file, ast.IsExported) produce the -// same trimmed AST given the same input file for all -// files under runtime.GOROOT(). -// -// The test is here because it requires parsing, and the -// parser imports AST already (avoid import cycle). - -package parser - -import ( - "bytes" - "go/ast" - "go/printer" - "go/token" - "os" - "path/filepath" - "runtime" - "strings" - "testing" -) - -// For a short test run, limit the number of files to a few. -// Set to a large value to test all files under GOROOT. -const maxFiles = 10000 - -type visitor struct { - t *testing.T - n int -} - -func (v *visitor) VisitDir(path string, f *os.FileInfo) bool { - return true -} - -func str(f *ast.File, fset *token.FileSet) string { - var buf bytes.Buffer - printer.Fprint(&buf, fset, f) - return buf.String() -} - -func (v *visitor) VisitFile(path string, f *os.FileInfo) { - // exclude files that clearly don't make it - if !f.IsRegular() || len(f.Name) > 0 && f.Name[0] == '.' || !strings.HasSuffix(f.Name, ".go") { - return - } - - // should we stop early for quick test runs? - if v.n <= 0 { - return - } - v.n-- - - fset := token.NewFileSet() - - // get two ASTs f1, f2 of identical structure; - // parsing twice is easiest - f1, err := ParseFile(fset, path, nil, ParseComments) - if err != nil { - v.t.Logf("parse error (1): %s", err) - return - } - - f2, err := ParseFile(fset, path, nil, ParseComments) - if err != nil { - v.t.Logf("parse error (2): %s", err) - return - } - - b1 := ast.FileExports(f1) - b2 := ast.FilterFileExports(f2) - if b1 != b2 { - v.t.Errorf("filtering failed (a): %s", path) - return - } - - s1 := str(f1, fset) - s2 := str(f2, fset) - if s1 != s2 { - v.t.Errorf("filtering failed (b): %s", path) - return - } -} - -func TestFilter(t *testing.T) { - filepath.Walk(runtime.GOROOT(), &visitor{t, maxFiles}, nil) -} -- 2.48.1