From d00624f6b14c86d65efa180cb12d2efa24f7a72b Mon Sep 17 00:00:00 2001 From: Tachikoma Date: Wed, 26 Feb 2014 12:50:39 +0800 Subject: [PATCH 1/2] =?UTF-8?q?use=20importer=20instead=20of=20gcimporter,?= =?UTF-8?q?=20to=20not=20only=20gc-generated=20file,=20but=20also=20go=20s?= =?UTF-8?q?ource=20file.=20Scenario:=20If=20a=20project=20proj=20has=20two?= =?UTF-8?q?=20package=20:=20proj/a=20and=20proj/b,=20proj/b=20import=20pro?= =?UTF-8?q?j/a,=20and=20proj/a=20is=20not=20=E2=80=9Cgo=20install=E2=80=9D?= =?UTF-8?q?ed.=20When=20use=20gcimporter=20only,=20gen=20proj/b=20will=20f?= =?UTF-8?q?ailed=20with=20=E2=80=9Cproj/a=20is=20not=20found=20for=20impor?= =?UTF-8?q?t=E2=80=9D.=20It=20will=20work=20with=20importer.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- package.go | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/package.go b/package.go index 92b521b..e6b5a2c 100644 --- a/package.go +++ b/package.go @@ -3,6 +3,7 @@ package main import ( _ "code.google.com/p/go.tools/go/gcimporter" "code.google.com/p/go.tools/go/types" + "code.google.com/p/go.tools/importer" "errors" "fmt" "go/ast" @@ -29,6 +30,28 @@ type GenTag struct { Negated bool } +func checkTypes(path string, fset *token.FileSet, files []*ast.File) (*types.Package, error) { + /* + * Use customized types.Config instead of types.Check + * By default, types.Check will use gcimporter, which will only import gc-generated files (*.a) + * The customized types.Config will use importer, instead of gcimporter. importer will import gc-generated files (*.a) and source files (*.go). + */ + typesConfig := types.Config{} + typesConfig.Import = func(imports map[string]*types.Package, path string) (*types.Package, error) { + impConfig := importer.Config{} + impConfig.TypeChecker = typesConfig + impConfig.Build = &build.Default + imp := importer.New(&impConfig) + pkgInfo, err := imp.LoadPackage(path) + if nil != err { + return nil, err + } + return pkgInfo.Pkg, nil + } + + return typesConfig.Check(path, fset, files, nil) +} + // Returns one gen Package per Go package found in current directory func getPackages() (result []*Package) { fset := token.NewFileSet() @@ -41,7 +64,7 @@ func getPackages() (result []*Package) { for name, astPackage := range astPackages { pkg := &Package{Name: name} - typesPkg, err := types.Check(name, fset, getAstFiles(astPackage, rootDir)) + typesPkg, err := checkTypes(name, fset, getAstFiles(astPackage, rootDir)) if err != nil { errs = append(errs, err) } From d0a62a15b8a1bf618e61cc8f65faf53e83b52a42 Mon Sep 17 00:00:00 2001 From: Tachikoma Date: Wed, 26 Feb 2014 12:51:40 +0800 Subject: [PATCH 2/2] use go1.2 isComparable code, to support go.tools for go1.2 --- predicates.go | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/predicates.go b/predicates.go index 5fe9323..7d618d9 100644 --- a/predicates.go +++ b/predicates.go @@ -13,7 +13,25 @@ import ( ) func isComparable(typ types.Type) bool { - return types.Comparable(typ) + // From : https://code.google.com/p/go/source/browse/go/types/predicates.go?repo=tools&name=release-branch.go1.2 + switch t := typ.Underlying().(type) { + case *types.Basic: + // assume invalid types to be comparable + // to avoid follow-up errors + return t.Kind() != types.UntypedNil + case *types.Pointer, *types.Interface, *types.Chan: + return true + case *types.Struct: + for i := 0; i < t.NumFields(); i++ { + if !isComparable(t.Field(i).Type()) { + return false + } + } + return true + case *types.Array: + return isComparable(t.Elem()) + } + return false } func isNumeric(typ types.Type) bool {