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

     1  package kmgGoSource
     2  
     3  import (
     4  	"fmt"
     5  	"go/ast"
     6  	"path"
     7  	"reflect"
     8  
     9  	"github.com/bronze1man/kmg/kmgCmd"
    10  	_ "golang.org/x/tools/go/gcimporter"
    11  	"golang.org/x/tools/go/types"
    12  )
    13  
    14  func MustGetGoTypesFromReflect(typ reflect.Type) types.Type {
    15  	switch typ.Kind() {
    16  	case reflect.Ptr:
    17  		return types.NewPointer(MustGetGoTypesFromReflect(typ.Elem()))
    18  	case reflect.Struct:
    19  		if typ.PkgPath() == "" {
    20  			panic(fmt.Errorf(`[MustGetGoTypesFromReflect] Not implement typ.PkgPath=="" name[%s]`,
    21  				typ.Name()))
    22  		}
    23  		//此处没有办法获取Package的实际Package名称
    24  		pkg := MustNewGoTypesMainPackageFromImportPath(typ.PkgPath())
    25  		typObj := pkg.Scope().Lookup(typ.Name())
    26  		return typObj.Type()
    27  	default:
    28  		panic(fmt.Errorf("[MustGetGoTypesFromReflect] Not implement Kind [%s]",
    29  			typ.Kind().String()))
    30  	}
    31  }
    32  
    33  // 类型名称定义
    34  // github.com/bronze1man/kmg/kmgGoSource/testPackage.Demo
    35  func MustGetGoTypeFromPkgPathAndTypeName(pkgPath string, typ string) types.Type {
    36  	pkg := MustNewGoTypesMainPackageFromImportPath(pkgPath)
    37  	typObj := pkg.Scope().Lookup(typ)
    38  	return typObj.Type()
    39  }
    40  
    41  func MustWriteGoTypes(thisPackagePath string, typi types.Type) (s string, addPkgPathList []string) {
    42  	switch typ := typi.(type) {
    43  	case *types.Basic:
    44  		return typ.String(), nil
    45  	case *types.Named:
    46  		if typ.Obj().Pkg() == nil {
    47  			return typ.Obj().Name(), nil
    48  		}
    49  		typPkgPath := typ.Obj().Pkg().Path()
    50  		if thisPackagePath == typPkgPath {
    51  			return typ.Obj().Name(), nil
    52  		}
    53  		return path.Base(typPkgPath) + "." + typ.Obj().Name(), []string{typPkgPath}
    54  	case *types.Pointer:
    55  		s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem())
    56  		return "*" + s, addPkgPathList
    57  	case *types.Slice:
    58  		s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem())
    59  		return "[]" + s, addPkgPathList
    60  	case *types.Interface:
    61  		return typ.String(), nil
    62  		//s, addPkgPathList = MustWriteGoTypes(thisPackagePath, typ.Elem())
    63  		//return "[]" + s, addPkgPathList
    64  	default:
    65  		panic(fmt.Errorf("[MustWriteGoTypes] Not implement go/types [%T] [%s]",
    66  			typi, typi.String()))
    67  	}
    68  	return "", nil
    69  }
    70  
    71  func MustGetMethodListFromGoTypes(typ types.Type) (output []*types.Selection) {
    72  	methodSet := types.NewMethodSet(typ)
    73  	num := methodSet.Len()
    74  	if num == 0 {
    75  		return nil
    76  	}
    77  	output = make([]*types.Selection, num)
    78  	for i := range output {
    79  		output[i] = methodSet.At(i)
    80  	}
    81  	return output
    82  }
    83  
    84  //返回这个导入路径的主Package的types.Package对象
    85  //TODO 解决测试package的问题
    86  func MustNewGoTypesMainPackageFromImportPath(importPath string) *types.Package {
    87  	//TODO 去掉可编译要求?
    88  	kmgCmd.CmdSlice([]string{"kmg", "go", "install", importPath}).MustRun()
    89  	kmgCmd.CmdSlice([]string{"kmg", "go", "test", "-i", importPath}).MustRun()
    90  	//TODO 解决需要预先创建pkg的问题.
    91  	astPkg, fset := MustNewMainAstPackageFromImportPath(importPath)
    92  	astFileList := []*ast.File{}
    93  	for _, file := range astPkg.Files {
    94  		astFileList = append(astFileList, file)
    95  	}
    96  	//os.Chdir(kmgConfig.DefaultEnv().ProjectPath)
    97  	conf := &types.Config{
    98  		IgnoreFuncBodies: true,
    99  	}
   100  	pkg, err := conf.Check(importPath, fset, astFileList, nil)
   101  	if err != nil {
   102  		panic(err)
   103  	}
   104  	return pkg
   105  }