github.com/keysonzzz/kmg@v0.0.0-20151121023212-05317bfd7d39/kmgGoSource/kmgGoParser/type.go (about) 1 package kmgGoParser 2 3 import ( 4 "bytes" 5 "fmt" 6 "github.com/bronze1man/kmg/kmgGoSource/kmgGoReader" 7 "strconv" 8 "unicode" 9 "unicode/utf8" 10 ) 11 12 // 13 type FuncOrMethodDeclaration struct { 14 Name string 15 ReceiverType Type 16 InParameter []FuncParameter 17 OutParameter []FuncParameter 18 } 19 20 func (t *FuncOrMethodDeclaration) GetKind() Kind { 21 if t.ReceiverType == nil { 22 return Func 23 } else { 24 return Method 25 } 26 } 27 28 func (t *FuncOrMethodDeclaration) IsExport() bool { 29 runeValue, _ := utf8.DecodeRuneInString(t.Name) 30 return unicode.IsUpper(runeValue) 31 } 32 33 // TODO finish it. 34 type FuncType struct { 35 InParameter []FuncParameter 36 OutParameter []FuncParameter 37 } 38 39 func (t FuncType) GetKind() Kind { 40 return Func 41 } 42 43 type NamedType struct { 44 PackagePath string 45 Name string 46 underType Type //TODO 第二次扫描AST获取此信息 47 Pkg *Package 48 } 49 50 func (t *NamedType) GetKind() Kind { 51 return Named 52 } 53 54 func (t *NamedType) GetUnderType() Type { 55 if t.underType == nil { 56 definer := t.Pkg.Program.GetNamedType(t.PackagePath, t.Name) 57 t.underType = definer.underType 58 } 59 return t.underType 60 } 61 62 //TODO finish it 63 type StructType struct { 64 Field []StructField 65 } 66 67 func (t StructType) GetKind() Kind { 68 return Struct 69 } 70 71 type StructField struct { 72 Name string 73 Elem Type 74 IsAnonymousField bool 75 Tag string 76 } 77 78 type MapType struct { 79 Key Type 80 Value Type 81 } 82 83 func (t MapType) GetKind() Kind { 84 return Map 85 } 86 87 type StringType struct { 88 } 89 90 type InterfaceType struct { 91 } 92 93 func (t InterfaceType) GetKind() Kind { 94 return Interface 95 } 96 97 type PointerType struct { 98 Elem Type 99 } 100 101 func (t PointerType) GetKind() Kind { 102 return Ptr 103 } 104 105 func NewPointer(elem Type) PointerType { 106 return PointerType{Elem: elem} 107 } 108 109 type Type interface { 110 GetKind() Kind 111 } 112 113 type FuncParameter struct { 114 Name string 115 Type Type 116 IsVariadic bool //是否有3个点 117 } 118 119 type SliceType struct { 120 Elem Type 121 } 122 123 func (t SliceType) GetKind() Kind { 124 return Slice 125 } 126 127 // TODO finish it 128 type ArrayType struct { 129 Size int 130 Elem Type 131 } 132 133 func (t ArrayType) GetKind() Kind { 134 return Array 135 } 136 137 type ChanType struct { 138 Dir ChanDir 139 Elem Type 140 } 141 142 func (t ChanType) GetKind() Kind { 143 return Chan 144 } 145 146 // 内置的,没有package前缀的类型. 147 type BuiltinType string 148 149 func (t BuiltinType) GetKind() Kind { 150 return builtinTypeMap[t] 151 } 152 153 func (t BuiltinType) String() string { 154 return string(t) 155 } 156 157 var builtinTypeMap = map[BuiltinType]Kind{ 158 "bool": Bool, 159 "byte": Uint8, 160 "complex128": Complex128, 161 "complex64": Complex64, 162 "error": Interface, // TODO problem? 163 "float32": Float32, 164 "float64": Float64, 165 "int": Int, 166 "int8": Int8, 167 "int16": Int16, 168 "int32": Int32, 169 "int64": Int64, 170 "rune": Int32, 171 "string": String, 172 "uint": Uint, 173 "uint8": Uint8, 174 "uint16": Uint16, 175 "uint32": Uint32, 176 "uint64": Uint64, 177 "uintptr": Uintptr, 178 } 179 180 type Kind uint 181 182 const ( 183 Invalid Kind = iota 184 Bool 185 Int 186 Int8 187 Int16 188 Int32 189 Int64 190 Uint 191 Uint8 192 Uint16 193 Uint32 194 Uint64 195 Uintptr 196 Float32 197 Float64 198 Complex64 199 Complex128 200 Array 201 Chan 202 Func 203 Interface 204 Map 205 Ptr 206 Slice 207 String 208 Struct 209 UnsafePointer 210 Method 211 Named 212 ) 213 214 func (k Kind) String() string { 215 if int(k) < len(kindNames) { 216 return kindNames[k] 217 } 218 return "kind" + strconv.Itoa(int(k)) 219 } 220 221 var kindNames = []string{ 222 Invalid: "invalid", 223 Bool: "bool", 224 Int: "int", 225 Int8: "int8", 226 Int16: "int16", 227 Int32: "int32", 228 Int64: "int64", 229 Uint: "uint", 230 Uint8: "uint8", 231 Uint16: "uint16", 232 Uint32: "uint32", 233 Uint64: "uint64", 234 Uintptr: "uintptr", 235 Float32: "float32", 236 Float64: "float64", 237 Complex64: "complex64", 238 Complex128: "complex128", 239 Array: "array", 240 Chan: "chan", 241 Func: "func", 242 Interface: "interface", 243 Map: "map", 244 Ptr: "ptr", 245 Slice: "slice", 246 String: "string", 247 Struct: "struct", 248 UnsafePointer: "unsafe.Pointer", 249 Method: "method", 250 Named: "Named", 251 } 252 253 type ChanDir int 254 255 const ( 256 RecvDir ChanDir = 1 << iota // <-chan 257 SendDir // chan<- 258 BothDir = RecvDir | SendDir // chan 259 ) 260 261 /* 262 第一个字符可能为 263 letter -> identifier(单独的类型名,带package的类型的package部分) 264 "struct" struct类型开头 265 "func" func类型开头 266 "interface" interface类型开头 267 "*" 指针开头 268 "[" (数组,slice) 开头 269 "map[" map开头 270 "chan " chan开头 271 "chan<- " chan<- 开头 272 "<-chan" chan<- 开头 273 */ 274 func (gofile *File) readType(r *kmgGoReader.Reader) Type { 275 id := readIdentifier(r) 276 if len(id) == 0 { 277 if r.IsMatchAfter([]byte("<-chan")) { 278 r.MustReadMatch([]byte("<-chan")) 279 r.ReadAllSpace() 280 return ChanType{ 281 Dir: RecvDir, 282 Elem: gofile.readType(r), 283 } 284 } 285 b := r.ReadByte() 286 if b == '*' { 287 return PointerType{ 288 Elem: gofile.readType(r), 289 } 290 } else if b == '[' { 291 content := readMatchMiddleParantheses(r) 292 if len(content) == 1 { 293 return SliceType{ 294 Elem: gofile.readType(r), 295 } 296 } else { 297 // 仅跳过 298 return ArrayType{ 299 Elem: gofile.readType(r), 300 } 301 } 302 } else if b == '(' { 303 typ := gofile.readType(r) 304 r.MustReadMatch([]byte(")")) 305 return typ 306 } else { 307 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 308 } 309 } 310 if bytes.Equal(id, []byte("struct")) { 311 return gofile.readStruct(r) 312 } else if bytes.Equal(id, []byte("interface")) { 313 // 仅跳过 314 r.ReadAllSpace() 315 b := r.ReadByte() 316 if b != '{' { 317 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 318 } 319 readMatchBigParantheses(r) 320 return InterfaceType{} 321 } else if bytes.Equal(id, []byte("map")) { 322 b := r.ReadByte() 323 m := MapType{} 324 if b != '[' { 325 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 326 } 327 m.Key = gofile.readType(r) 328 r.MustReadMatch([]byte("]")) 329 m.Value = gofile.readType(r) 330 return m 331 } else if bytes.Equal(id, []byte("func")) { 332 // 仅跳过 333 r.ReadAllSpace() 334 b := r.ReadByte() 335 if b != '(' { 336 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 337 } 338 readMatchSmallParantheses(r) //跳过输入参数 339 r.ReadAllSpaceWithoutLineBreak() 340 run := r.ReadRune() //跳过输出参数 341 if run == '(' { 342 readMatchSmallParantheses(r) 343 } else if run == '\n' { //换行符可以标识这个函数定义结束了. 344 return FuncType{} 345 } else if unicode.IsLetter(run) || run == '[' || run == '*' || run == '<' { 346 r.UnreadRune() //输出参数只有一个类型 347 gofile.readType(r) 348 } else { 349 r.UnreadRune() //读到了其他东西,退回. 350 } 351 return FuncType{} 352 } else if bytes.Equal(id, []byte("chan")) { 353 if r.IsMatchAfter([]byte("<-")) { 354 r.MustReadMatch([]byte("<-")) 355 r.ReadAllSpace() 356 return ChanType{ 357 Dir: SendDir, 358 Elem: gofile.readType(r), 359 } 360 } else { 361 r.ReadAllSpace() 362 return ChanType{ 363 Dir: BothDir, 364 Elem: gofile.readType(r), 365 } 366 } 367 } else { 368 b := r.ReadByte() 369 if b == '.' { 370 pkgPath := string(id) 371 pkgPath, err := gofile.LookupFullPackagePath(pkgPath) 372 if err != nil { 373 fmt.Println(r.GetFileLineInfo(), err.Error()) //TODO 以目前的复杂度暂时无解.需要把所有相关的package都看一遍才能正确. 374 } 375 id2 := readIdentifier(r) 376 return &NamedType{ 377 PackagePath: pkgPath, 378 Name: string(id2), 379 Pkg: gofile.Pkg, 380 } 381 } else { 382 r.UnreadByte() 383 name := string(id) 384 if builtinTypeMap[BuiltinType(name)] != Invalid { 385 return BuiltinType(name) 386 } else { 387 return &NamedType{ 388 PackagePath: gofile.PackagePath, 389 Name: string(id), 390 Pkg: gofile.Pkg, 391 } 392 } 393 } 394 } 395 /* 396 }else if r.IsMatchAfter([]byte("struct")) { //TODO 解决struct后面必须有一个空格的问题. 397 r.ReadAllSpace() 398 b := r.ReadByte() 399 if b!='{' { 400 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 401 } 402 readMatchBigParantheses(r) 403 return StructType{} 404 }else if r.IsMatchAfter([]byte("interface")) { 405 r.ReadAllSpace() 406 b := r.ReadByte() 407 if b!='{' { 408 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 409 } 410 readMatchBigParantheses(r) 411 return InterfaceType{} 412 }else if r.IsMatchAfter([]byte("map[")){ 413 414 }else if r.IsMatchAfter([]byte("func")){ 415 //TODO finish it. 416 } 417 */ 418 } 419 420 func getTypeStructAnonymousName(typ Type) string { 421 ntyp, ok := typ.(*NamedType) 422 if ok { 423 return ntyp.Name 424 } 425 ptyp, ok := typ.(PointerType) 426 if ok { 427 return "*" + getTypeStructAnonymousName(ptyp.Elem) 428 } 429 btyp, ok := typ.(BuiltinType) 430 if ok { 431 return string(btyp) 432 } 433 panic(fmt.Errorf("[getTypeStructAnonymousName] unexpect type %T", typ)) 434 } 435 436 func (gofile *File) readStruct(r *kmgGoReader.Reader) StructType { 437 // 仅跳过 438 r.ReadAllSpace() 439 b := r.ReadByte() 440 if b != '{' { 441 panic(fmt.Errorf("%s unexcept %s", r.GetFileLineInfo(), string(rune(b)))) 442 } 443 lastReadBuf := []bytesAndType{} 444 var lastTag []byte 445 out := StructType{} 446 for { 447 r.ReadAllSpaceWithoutLineBreak() 448 b := r.ReadByte() 449 if b == '}' { 450 return out 451 } else if b == '"' || b == '\'' || b == '`' { 452 r.UnreadByte() 453 lastTag = MustReadGoString(r) 454 } else if b == ',' { 455 continue 456 } else if b == '\n' { 457 if len(lastReadBuf) == 0 { 458 continue 459 } else if len(lastReadBuf) == 1 { 460 typ := lastReadBuf[0].typ 461 name := getTypeStructAnonymousName(typ) 462 out.Field = append(out.Field, StructField{ 463 Name: name, 464 Elem: typ, 465 IsAnonymousField: true, 466 Tag: string(lastTag), 467 }) 468 lastReadBuf = []bytesAndType{} 469 } else if len(lastReadBuf) >= 2 { 470 typ := lastReadBuf[len(lastReadBuf)-1].typ 471 for i := range lastReadBuf[:len(lastReadBuf)-1] { 472 out.Field = append(out.Field, StructField{ 473 Name: string(lastReadBuf[i].originByte), 474 Elem: typ, 475 IsAnonymousField: false, 476 Tag: string(lastTag), 477 }) 478 } 479 lastReadBuf = []bytesAndType{} 480 } 481 } else { 482 r.UnreadByte() 483 startPos := r.Pos() 484 typ := gofile.readType(r) 485 lastReadBuf = append(lastReadBuf, bytesAndType{ 486 originByte: r.BufToCurrent(startPos), 487 typ: typ, 488 }) 489 } 490 } 491 } 492 493 type bytesAndType struct { 494 originByte []byte 495 typ Type 496 }