github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/Package.go (about)

     1  package kmgGoSource
     2  
     3  import (
     4  	"go/ast"
     5  	"go/doc"
     6  	"go/parser"
     7  	"go/token"
     8  	"strings"
     9  
    10  	"github.com/bronze1man/kmg/kmgConfig"
    11  )
    12  
    13  // 这个东西目前 有2个问题,
    14  // 1.从ast生成回Type.
    15  // 2.运行必须能反射.
    16  // 3.import似乎很难处理.
    17  // 4.把各种类型都加入复杂度比较高(生成struct的时候还是要使用的.)
    18  
    19  // golang.org/x/tools/go/types 和 golang.org/x/tools/go/ssa 的问题
    20  // 1.接口过度复杂和奇葩, 学习成本高.
    21  // 2.写回类型的时候没有import信息
    22  
    23  //表示一个golang里面的package
    24  type Package struct {
    25  	docPkg *doc.Package
    26  }
    27  
    28  func (pkg *Package) getDocTypeByName(name string) *doc.Type {
    29  	for _, docType := range pkg.docPkg.Types {
    30  		if docType.Name == name {
    31  			return docType
    32  		}
    33  	}
    34  	return nil
    35  }
    36  
    37  // 填在import的那个路径的值
    38  func (pkg *Package) PkgPath() string {
    39  	return pkg.docPkg.ImportPath
    40  }
    41  
    42  // package 的名字,填在 package 那个地方的名字
    43  // package kmgReflect
    44  func (pkg *Package) Name() string {
    45  	return pkg.docPkg.Name
    46  }
    47  
    48  //使用importPath获取一个Package,
    49  // 仅支持导入一个目录作为一个package
    50  // 只导入一个package里面的主package,xxx_test不导入.
    51  // 注意: 需要源代码,需要使用kmg配置GOPATH
    52  func MustNewPackageFromImportPath(importPath string) *Package {
    53  	astPkg, _ := MustNewMainAstPackageFromImportPath(importPath)
    54  	docPkg := doc.New(astPkg, importPath, doc.AllMethods)
    55  	return &Package{
    56  		docPkg: docPkg,
    57  	}
    58  }
    59  
    60  func GetImportPathListFromFile(filepath string) (importPathList []string, err error) {
    61  	fset := token.NewFileSet()
    62  	pkgs, err := parser.ParseFile(fset, filepath, nil, parser.ImportsOnly)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  	for _, thisImport := range pkgs.Imports {
    67  		//目前没有找到反序列化golang的双引号的方法,暂时使用简单的办法
    68  		pkgName, err := UnquoteGolangDoubleQuote(thisImport.Path.Value)
    69  		if err != nil {
    70  			return nil, err
    71  		}
    72  		importPathList = append(importPathList, pkgName)
    73  	}
    74  	return importPathList, nil
    75  }
    76  
    77  func MustNewMainAstPackageFromImportPath(importPath string) (pkg *ast.Package, fset *token.FileSet) {
    78  	pkgDir := kmgConfig.DefaultEnv().MustGetPathFromImportPath(importPath)
    79  	fset = token.NewFileSet()
    80  	astPkgMap, err := parser.ParseDir(fset, pkgDir, nil, 0)
    81  	if err != nil {
    82  		panic(err)
    83  	}
    84  	if len(astPkgMap) == 0 {
    85  		panic("can not found package")
    86  	}
    87  	for name, astPkg := range astPkgMap {
    88  		if strings.HasSuffix(name, "_test") {
    89  			continue
    90  		}
    91  		return astPkg, fset
    92  	}
    93  	panic("impossible execute path")
    94  }