github.com/keysonZZZ/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgRpc/kmgRpcJava/reflect.go (about) 1 package kmgRpcJava 2 3 import ( 4 "fmt" 5 6 "github.com/bronze1man/kmg/kmgGoSource/kmgGoParser" 7 "github.com/bronze1man/kmg/kmgStrings" 8 "strconv" 9 ) 10 11 func reflectToTplConfig(req *GenerateRequest) *tplConfig { 12 config := &tplConfig{ 13 OutPackageName: req.OutPackageName, 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 //pkg := kmgGoParser.MustParsePackage(kmgConfig.DefaultEnv().GOPATHToString(), req.ObjectPkgPath) 25 namedTyp := pkg.LookupNamedType(req.ObjectName) 26 if namedTyp == nil { 27 panic(fmt.Errorf("can not find this object. [%s]", req.ObjectName)) 28 } 29 objTyp := kmgGoParser.Type(namedTyp) 30 if req.ObjectIsPointer { 31 objTyp = kmgGoParser.NewPointer(objTyp) 32 } 33 //获取 object 上面所有的方法 34 methodList := pkg.GetNamedTypeMethodSet(namedTyp) 35 for _, methodObj := range methodList { 36 if !methodObj.IsExport() { 37 continue 38 } 39 if !req.ApiNameFilterCb(methodObj.Name) { 40 continue 41 } 42 api := Api{ 43 Name: methodObj.Name, 44 } 45 RequestInnerClass := &InnerClass{ 46 Name: api.Name + "RpcRequest", 47 IsPublic: false, 48 } 49 for _, pairObj := range methodObj.InParameter { 50 if isPointerToKmgHttpContext(pairObj.Type) { 51 // 此处忽略掉特殊传入参数 *kmgHttp.Context 52 continue 53 } 54 pair := NameTypePair{ 55 Name: kmgStrings.FirstLetterToUpper(pairObj.Name), 56 } 57 pair.TypeStr = config.addType(pairObj.Type) 58 api.InArgsList = append(api.InArgsList, pair) 59 RequestInnerClass.FieldList = append(RequestInnerClass.FieldList, pair) 60 } 61 config.addInnerClass(RequestInnerClass) 62 /* 63 * 在java中,如果输出参数的类型是error,会转到exception里面 64 * 在java中,如果输出参数去除error后,没有参数了,java函数不会返回参数 65 * 在java中,如果输出参数除去error后,还有1个,直接返回这个类型,此时此参数依然按照前面的说法进行向前兼容. 66 * 在java中,如果输出参数除去error后,还有2个及2个以上,返回一个class,这个class包含这些个参数. 67 */ 68 notErrorOutParameter := []NameTypePair{} 69 for i, pairObj := range methodObj.OutParameter { 70 builtintyp, ok := pairObj.Type.(kmgGoParser.BuiltinType) 71 if !(ok && string(builtintyp) == "error") { 72 name := kmgStrings.FirstLetterToUpper(pairObj.Name) 73 if name == "" { 74 name = "Out_" + strconv.Itoa(i) 75 } 76 notErrorOutParameter = append(notErrorOutParameter, NameTypePair{ 77 Name: name, 78 TypeStr: config.addType(pairObj.Type), 79 }) 80 } 81 } 82 if len(notErrorOutParameter) == 0 { 83 api.OutTypeString = "void" 84 } else { 85 responseInnerClass := &InnerClass{ 86 Name: api.Name + "RpcResponse", 87 FieldList: notErrorOutParameter, 88 IsPublic: true, 89 } 90 config.addInnerClass(responseInnerClass) 91 92 if len(notErrorOutParameter) == 1 { 93 api.OutTypeString = notErrorOutParameter[0].TypeStr 94 api.OutTypeFieldName = notErrorOutParameter[0].Name 95 } else { 96 api.OutTypeString = responseInnerClass.Name 97 } 98 } 99 config.ApiList = append(config.ApiList, api) 100 } 101 return config 102 } 103 104 func isPointerToKmgHttpContext(typi kmgGoParser.Type) bool { 105 typ1, ok := typi.(kmgGoParser.PointerType) 106 if !ok { 107 return false 108 } 109 typ2, ok := typ1.Elem.(*kmgGoParser.NamedType) 110 if !ok { 111 return false 112 } 113 return typ2.Name == "Context" && typ2.PackagePath == "github.com/bronze1man/kmg/kmgNet/kmgHttp" 114 } 115 116 func (config *tplConfig) addType(typi kmgGoParser.Type) string { 117 switch typ := typi.(type) { 118 //case kmgGoParser.FuncType: 119 // panic("TODO") 120 case kmgGoParser.PointerType: 121 return config.addType(typ.Elem) 122 case *kmgGoParser.NamedType: 123 if typ.Name == "Time" && typ.PackagePath == "time" { 124 return "Date" 125 } 126 // TODO 命名重复? 127 name := typ.Name 128 ntyp := config.innerClassMap[name] 129 if ntyp != nil { 130 return name 131 } 132 switch utyp := typ.GetUnderType().(type) { 133 case kmgGoParser.StructType: 134 innerClass := &InnerClass{ 135 Name: name, 136 IsPublic: true, 137 } 138 config.addInnerClass(innerClass) // 避免循环引用导致出现bug. 139 for i := range utyp.Field { 140 innerClass.FieldList = append(innerClass.FieldList, NameTypePair{ 141 Name: utyp.Field[i].Name, 142 TypeStr: config.addType(utyp.Field[i].Elem), 143 }) 144 } 145 return name 146 default: 147 return config.addType(utyp) 148 } 149 case kmgGoParser.BuiltinType: 150 s, ok := builtinTypeMap[string(typ)] 151 if !ok { 152 panic("not support BuiltinType " + string(typ)) 153 } 154 return s 155 case kmgGoParser.SliceType: 156 return "List<" + config.addType(typ.Elem) + ">" 157 default: 158 panic(fmt.Errorf("TODO %T", typi)) 159 } 160 } 161 162 var builtinTypeMap = map[string]string{ 163 "string": "String", 164 "int": "Integer", 165 "int64": "Long", 166 "float64": "Float", 167 "bool": "Boolean", 168 "byte": "Byte", 169 }