github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcSwift/reflect.go (about)

     1  package kmgRpcSwift
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/bronze1man/kmg/kmgGoSource/kmgGoParser"
     7  	"github.com/bronze1man/kmg/kmgStrings"
     8  	"log"
     9  	"strconv"
    10  )
    11  
    12  func reflectToTplConfig(req *GenerateRequest) *tplConfig {
    13  	config := &tplConfig{
    14  		ClassName:     req.OutClassName,
    15  		innerClassMap: map[string]*InnerClass{},
    16  	}
    17  	if req.ApiNameFilterCb == nil {
    18  		req.ApiNameFilterCb = func(name string) bool {
    19  			return true
    20  		}
    21  	}
    22  
    23  	pkg := kmgGoParser.NewProgramFromDefault().GetPackage(req.ObjectPkgPath)
    24  	namedTyp := pkg.LookupNamedType(req.ObjectName)
    25  	if namedTyp == nil {
    26  		panic(fmt.Errorf("can not find this object. [%s]", req.ObjectName))
    27  	}
    28  	objTyp := kmgGoParser.Type(namedTyp)
    29  	if req.ObjectIsPointer {
    30  		objTyp = kmgGoParser.NewPointer(objTyp)
    31  	}
    32  	//获取 object 上面所有的方法
    33  	methodList := pkg.GetNamedTypeMethodSet(namedTyp)
    34  	for _, methodObj := range methodList {
    35  		log.Println(methodObj.Name)
    36  		log.Println(methodObj.OutParameter)
    37  		log.Println(methodObj.InParameter)
    38  		log.Println(methodObj.ReceiverType.GetKind())
    39  		if !methodObj.IsExport() {
    40  			continue
    41  		}
    42  		if !req.ApiNameFilterCb(methodObj.Name) {
    43  			continue
    44  		}
    45  		api := Api{
    46  			Name: methodObj.Name,
    47  		}
    48  		RequestInnerClass := &InnerClass{
    49  			Name:     api.Name + "RpcRequest",
    50  			IsPublic: false,
    51  		}
    52  		for _, pairObj := range methodObj.InParameter {
    53  			pair := NameTypePair{
    54  				Name: kmgStrings.FirstLetterToUpper(pairObj.Name),
    55  			}
    56  			pair.TypeStr = config.addType(pairObj.Type)
    57  			api.InArgsList = append(api.InArgsList, pair)
    58  			RequestInnerClass.FieldList = append(RequestInnerClass.FieldList, pair)
    59  		}
    60  		config.addInnerClass(RequestInnerClass)
    61  		/*
    62  		 * 在java中,如果输出参数的类型是error,会转到exception里面
    63  		 * 在java中,如果输出参数去除error后,没有参数了,java函数不会返回参数
    64  		 * 在java中,如果输出参数除去error后,还有1个,直接返回这个类型,此时此参数依然按照前面的说法进行向前兼容.
    65  		 * 在java中,如果输出参数除去error后,还有2个及2个以上,返回一个class,这个class包含这些个参数.
    66  		 */
    67  		notErrorOutParameter := []NameTypePair{}
    68  		for i, pairObj := range methodObj.OutParameter {
    69  			builtintyp, ok := pairObj.Type.(kmgGoParser.BuiltinType)
    70  			if !(ok && string(builtintyp) == "error") {
    71  				name := kmgStrings.FirstLetterToUpper(pairObj.Name)
    72  				if name == "" {
    73  					name = "Out_" + strconv.Itoa(i)
    74  				}
    75  				notErrorOutParameter = append(notErrorOutParameter, NameTypePair{
    76  					Name:    name,
    77  					TypeStr: config.addType(pairObj.Type),
    78  				})
    79  			}
    80  		}
    81  		if len(notErrorOutParameter) == 0 {
    82  			api.OutTypeString = "void"
    83  		} else {
    84  			responseInnerClass := &InnerClass{
    85  				Name:      api.Name + "RpcResponse",
    86  				FieldList: notErrorOutParameter,
    87  				IsPublic:  false,
    88  			}
    89  			config.addInnerClass(responseInnerClass)
    90  
    91  			if len(notErrorOutParameter) == 1 {
    92  				api.OutTypeString = notErrorOutParameter[0].TypeStr
    93  				api.OutTypeFieldName = notErrorOutParameter[0].Name
    94  			} else {
    95  				api.OutTypeString = responseInnerClass.Name
    96  			}
    97  		}
    98  		config.ApiList = append(config.ApiList, api)
    99  	}
   100  	return config
   101  }
   102  
   103  func (config *tplConfig) addType(typi kmgGoParser.Type) string {
   104  	switch typ := typi.(type) {
   105  	//case kmgGoParser.FuncType:
   106  	//	panic("TODO")
   107  	case kmgGoParser.PointerType:
   108  		return config.addType(typ.Elem)
   109  	case *kmgGoParser.NamedType:
   110  		if typ.Name == "Time" && typ.PackagePath == "time" {
   111  			return "NSDate"
   112  		}
   113  		name := typ.Name
   114  		ntyp := config.innerClassMap[name]
   115  		if ntyp != nil {
   116  			return name
   117  		}
   118  		switch utyp := typ.GetUnderType().(type) {
   119  		case kmgGoParser.StructType:
   120  			innerClass := &InnerClass{
   121  				Name:     name,
   122  				IsPublic: true,
   123  			}
   124  			config.addInnerClass(innerClass) // 避免循环引用导致出现bug.
   125  			for i := range utyp.Field {
   126  				innerClass.FieldList = append(innerClass.FieldList, NameTypePair{
   127  					Name:    utyp.Field[i].Name,
   128  					TypeStr: config.addType(utyp.Field[i].Elem),
   129  				})
   130  			}
   131  			return name
   132  		default:
   133  			return config.addType(utyp)
   134  		}
   135  	case kmgGoParser.BuiltinType:
   136  		s, ok := builtinTypeMap[string(typ)]
   137  		if !ok {
   138  			panic("not support BuiltinType " + string(typ))
   139  		}
   140  		return s
   141  	case kmgGoParser.SliceType:
   142  		return "[" + config.addType(typ.Elem) + "]"
   143  	default:
   144  		panic(fmt.Errorf("TODO %T", typi))
   145  	}
   146  }
   147  
   148  var builtinTypeMap = map[string]string{
   149  	"string":  "NSString",
   150  	"int":     "Int",
   151  	"int64":   "Int",
   152  	"float64": "Float",
   153  	"bool":    "Bool",
   154  	"byte":    "UInt8",
   155  }