Skip to content

Commit

Permalink
support mutiple platform/architect dependent definitions
Browse files Browse the repository at this point in the history
when there are multiple platform/architect implements,
all of them will be printed.

Signed-off-by: Tw <[email protected]>
  • Loading branch information
tw4452852 committed Jan 31, 2015
1 parent a09411a commit 88f30c0
Show file tree
Hide file tree
Showing 4 changed files with 108 additions and 5 deletions.
1 change: 1 addition & 0 deletions go/ast/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ type Object struct {
Decl interface{} // corresponding Field, XxxSpec, FuncDecl, or LabeledStmt; or nil
Data interface{} // object-specific data; or nil
Type interface{} // place holder for type information; may be nil
Next *Object // corresponding platform dependent implement; or nil
}

// NewObj creates a new object of a given kind and name.
Expand Down
71 changes: 71 additions & 0 deletions go/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import (
"fmt"
"regexp"
"strconv"
"strings"
)

// The mode parameter to the Parse* functions is a set of flags (or 0).
Expand Down Expand Up @@ -216,6 +217,11 @@ func (p *parser) declare1(decl ast.Node, scope *ast.Scope, kind ast.ObjKind, ide
}

func (p *parser) redeclared(ident *ast.Ident, prev *ast.Object, reason string) {
if f := p.fset.File(ident.Pos()); f.IsPlatformDependent() {
ident.Obj.Next = prev.Next
prev.Next = ident.Obj
return
}
if p.mode&DeclarationErrors == 0 {
return
}
Expand Down Expand Up @@ -2215,6 +2221,9 @@ func (p *parser) parseFile() *ast.File {
}
initialScope := p.topScope

// get platform dependent info from file name or build tag
platformDependent(p.file, p.comments)

// package clause
doc := p.leadComment
pos := p.expect(token.PACKAGE)
Expand Down Expand Up @@ -2248,3 +2257,65 @@ func (p *parser) parseFile() *ast.File {

return &ast.File{doc, pos, ident, decls, p.fileScope, nil, nil, p.comments}
}

var (
goosSuffixes = []string{
"_dragonfly.go",
"_netbsd.go",
"_openbsd.go",
"_solaris.go",
"_freebsd.go",
"_nacl.go",
"_android.go",
"_plan9.go",
"_darwin.go",
"_linux.go",
"_windows.go",
}
goarchSuffixes = []string{
"_amd64.go",
"_amd64p32.go",
"_arm.go",
"_ppc64.go",
"_ppc64le.go",
"_386.go",
}
buildPrefix = "// +build"
)

// platformDependent sets file is platform dependent or not
func platformDependent(f *token.File, cgs []*ast.CommentGroup) {
if f == nil {
return
}

//TODO: if file already has platform dependent info, return

// get from file name
fn := f.Name()
for _, os := range goosSuffixes {
if strings.HasSuffix(fn, os) {
f.PlatformDependent()
return
}
}
for _, arch := range goarchSuffixes {
if strings.HasSuffix(fn, arch) {
f.PlatformDependent()
return
}
}

// get from build constraint
if cgs == nil {
return
}
for _, cg := range cgs {
for _, c := range cg.List {
if strings.HasPrefix(c.Text, buildPrefix) {
f.PlatformDependent()
return
}
}
}
}
14 changes: 13 additions & 1 deletion go/token/position.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,8 @@ type File struct {
// lines and infos are protected by set.mutex
lines []int
infos []lineInfo

platformDep bool // platformDep indicate whether this file is platform dependent
}

// Name returns the file name of file f as registered with AddFile.
Expand Down Expand Up @@ -314,6 +316,16 @@ func (f *File) info(offset int) (filename string, line, column int) {
return
}

// IsPlatformDependent returns whether this file platform dependent
func (f *File) IsPlatformDependent() bool {
return f.platformDep
}

// PlatformDependent sets this file is platform dependent (default is false)
func (f *File) PlatformDependent() {
f.platformDep = true
}

// A FileSet represents a set of source files.
// Methods of file sets are synchronized; multiple goroutines
// may invoke them concurrently.
Expand Down Expand Up @@ -366,7 +378,7 @@ func (s *FileSet) AddFile(filename string, base, size int) *File {
panic("illegal base or size")
}
// base >= s.base && size >= 0
f := &File{s, filename, base, size, []int{0}, nil}
f := &File{s, filename, base, size, []int{0}, nil, false}
base += size + 1 // +1 because EOF also has a position
if base < 0 {
panic("token.Pos offset overflow (> 2G of source code in file set)")
Expand Down
27 changes: 23 additions & 4 deletions godef.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ var aflag = flag.Bool("a", false, "print public type and member information")
var Aflag = flag.Bool("A", false, "print all type and members information")
var fflag = flag.String("f", "", "Go source filename")
var acmeFlag = flag.Bool("acme", false, "use current acme window")
var pflag = flag.Bool("p", false, "print all platform-dependent definitions")

func fail(s string, a ...interface{}) {
fmt.Fprint(os.Stderr, "godef: "+fmt.Sprintf(s, a...)+"\n")
Expand Down Expand Up @@ -86,7 +87,12 @@ func main() {
src = b
}
pkgScope := ast.NewScope(parser.Universe)
f, err := parser.ParseFile(types.FileSet, filename, src, 0, pkgScope)
var mode uint
if *pflag {
// parse comments to get build constraint
mode |= parser.ParseComments
}
f, err := parser.ParseFile(types.FileSet, filename, src, mode, pkgScope)
if f == nil {
fail("cannot parse %s: %v", filename, err)
}
Expand Down Expand Up @@ -218,8 +224,15 @@ func (o orderedObjects) Swap(i, j int) { o[i], o[j] = o[j], o[i] }

func done(obj *ast.Object, typ types.Type) {
defer os.Exit(0)
pos := types.FileSet.Position(types.DeclPos(obj))
fmt.Printf("%v\n", pos)
if *pflag {
for o := obj; o != nil; o = o.Next {
pos := types.FileSet.Position(types.DeclPos(o))
fmt.Printf("%v\n", pos)
}
} else {
pos := types.FileSet.Position(types.DeclPos(obj))
fmt.Printf("%v\n", pos)
}
if typ.Kind == ast.Bad || !*tflag {
return
}
Expand Down Expand Up @@ -310,14 +323,20 @@ func parseLocalPackage(filename string, src *ast.File, pkgScope *ast.Scope) (*as
return nil, errNoPkgFiles
}

var mode uint
if *pflag {
// parse comments to get build constraint
mode |= parser.ParseComments
}

for _, pf := range list {
file := filepath.Join(d, pf)
if !strings.HasSuffix(pf, ".go") ||
pf == f ||
pkgName(file) != pkg.Name {
continue
}
src, err := parser.ParseFile(types.FileSet, file, nil, 0, pkg.Scope)
src, err := parser.ParseFile(types.FileSet, file, nil, mode, pkg.Scope)
if err == nil {
pkg.Files[file] = src
}
Expand Down

0 comments on commit 88f30c0

Please sign in to comment.