github.com/aacfactory/fns@v1.2.86-0.20240310083819-80d667fc0a17/cmd/generates/sources/types.go (about) 1 /* 2 * Copyright 2023 Wang Min Xiang 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 * 16 */ 17 18 package sources 19 20 import ( 21 "context" 22 "fmt" 23 "github.com/aacfactory/errors" 24 "go/ast" 25 "golang.org/x/sync/singleflight" 26 "reflect" 27 "sync" 28 ) 29 30 const ( 31 BasicKind = TypeKind(iota + 1) 32 BuiltinKind 33 IdentKind 34 InterfaceKind 35 StructKind 36 StructFieldKind 37 PointerKind 38 ArrayKind 39 MapKind 40 AnyKind 41 ParadigmKind 42 ParadigmElementKind 43 ReferenceKind 44 ) 45 46 type TypeKind int 47 48 func (kind TypeKind) String() string { 49 switch kind { 50 case BasicKind: 51 return "basic" 52 case BuiltinKind: 53 return "builtin" 54 case IdentKind: 55 return "ident" 56 case InterfaceKind: 57 return "interface" 58 case StructKind: 59 return "struct" 60 case StructFieldKind: 61 return "struct_field" 62 case PointerKind: 63 return "pointer" 64 case ArrayKind: 65 return "array" 66 case MapKind: 67 return "map" 68 case AnyKind: 69 return "any" 70 case ParadigmKind: 71 return "paradigm" 72 case ParadigmElementKind: 73 return "paradigm_element" 74 case ReferenceKind: 75 return "reference" 76 } 77 return "unknown" 78 } 79 80 type TypeParadigm struct { 81 Name string 82 Types []*Type 83 } 84 85 func (tp *TypeParadigm) String() (v string) { 86 types := "" 87 if tp.Types != nil && len(tp.Types) > 0 { 88 for _, typ := range tp.Types { 89 types = types + "| " + typ.String() 90 } 91 if types != "" { 92 types = types[2:] 93 } 94 } 95 v = fmt.Sprintf("[%s %s]", tp.Name, types) 96 return 97 } 98 99 var AnyType = &Type{ 100 Kind: AnyKind, 101 Path: "", 102 Name: "", 103 Annotations: nil, 104 Paradigms: nil, 105 Tags: nil, 106 Elements: nil, 107 } 108 109 type Type struct { 110 Kind TypeKind 111 Path string 112 Name string 113 Annotations Annotations 114 Paradigms []*TypeParadigm 115 Tags map[string]string 116 Elements []*Type 117 ParadigmsPacked *Type 118 } 119 120 func (typ *Type) Flats() (v map[string]*Type) { 121 v = make(map[string]*Type) 122 switch typ.Kind { 123 case BuiltinKind, AnyKind: 124 if _, has := v[typ.Key()]; !has { 125 v[typ.Key()] = typ 126 } 127 break 128 case IdentKind, PointerKind, ArrayKind: 129 if _, has := v[typ.Key()]; !has { 130 v[typ.Key()] = typ 131 vv := typ.Elements[0].Flats() 132 for k, t := range vv { 133 if _, has = vv[k]; !has { 134 v[k] = t 135 } 136 } 137 } 138 break 139 case InterfaceKind: 140 if _, has := v[typ.Key()]; !has { 141 v[typ.Key()] = typ 142 } 143 break 144 case StructKind: 145 if _, has := v[typ.Key()]; !has { 146 v[typ.Key()] = typ 147 if typ.Elements != nil && len(typ.Elements) > 0 { 148 for _, element := range typ.Elements { 149 vv := element.Elements[0].Flats() 150 for k, t := range vv { 151 if _, has = vv[k]; !has { 152 v[k] = t 153 } 154 } 155 } 156 } 157 } 158 break 159 case MapKind: 160 if _, has := v[typ.Key()]; !has { 161 v[typ.Key()] = typ 162 vv := typ.Elements[0].Flats() 163 for k, t := range vv { 164 if _, has = vv[k]; !has { 165 v[k] = t 166 } 167 } 168 vv = typ.Elements[1].Flats() 169 for k, t := range vv { 170 if _, has = vv[k]; !has { 171 v[k] = t 172 } 173 } 174 } 175 break 176 case ParadigmKind: 177 if _, has := v[typ.Key()]; !has { 178 v[typ.Key()] = typ 179 vv := typ.Elements[0].Flats() 180 for k, t := range vv { 181 if _, has = vv[k]; !has { 182 v[k] = t 183 } 184 } 185 for _, paradigm := range typ.Paradigms { 186 for _, pt := range paradigm.Types { 187 vv = pt.Flats() 188 for k, t := range vv { 189 if _, has = vv[k]; !has { 190 v[k] = t 191 } 192 } 193 } 194 } 195 } 196 197 if typ.ParadigmsPacked != nil { 198 vv := typ.ParadigmsPacked.Flats() 199 for k, t := range vv { 200 if _, has := vv[k]; !has { 201 v[k] = t 202 } 203 } 204 } 205 break 206 default: 207 break 208 } 209 return 210 } 211 212 func (typ *Type) String() (v string) { 213 if typ.Path != "" && typ.Name != "" { 214 v = typ.Key() 215 return 216 } 217 switch typ.Kind { 218 case BasicKind: 219 v = typ.Name 220 break 221 case BuiltinKind, IdentKind, InterfaceKind, StructKind, StructFieldKind, PointerKind, ReferenceKind: 222 v = typ.Key() 223 break 224 case ArrayKind: 225 v = fmt.Sprintf("[]%s", typ.Elements[0].Key()) 226 break 227 case MapKind: 228 v = fmt.Sprintf("map[%s]%s", typ.Elements[0].String(), typ.Elements[1].String()) 229 break 230 case AnyKind: 231 v = "any" 232 break 233 case ParadigmElementKind: 234 elements := "" 235 for _, element := range typ.Elements { 236 elements = elements + "| " + element.String() 237 } 238 if elements != "" { 239 elements = elements[2:] 240 } 241 v = fmt.Sprintf("[%s %s]", typ.Name, elements) 242 break 243 default: 244 v = typ.Key() 245 break 246 } 247 return 248 } 249 250 func (typ *Type) Key() (key string) { 251 key = formatTypeKey(typ.Path, typ.Name) 252 return 253 } 254 255 func formatTypeKey(path string, name string) (key string) { 256 key = fmt.Sprintf("%s.%s", path, name) 257 return 258 } 259 260 func (typ *Type) GetTopPaths() (paths []string) { 261 paths = make([]string, 0, 1) 262 switch typ.Kind { 263 case StructKind: 264 paths = append(paths, typ.Path) 265 case PointerKind, ArrayKind: 266 paths = append(paths, typ.Elements[0].GetTopPaths()...) 267 break 268 case MapKind: 269 paths = append(paths, typ.Elements[0].GetTopPaths()...) 270 paths = append(paths, typ.Elements[1].GetTopPaths()...) 271 break 272 default: 273 break 274 } 275 return 276 } 277 278 func (typ *Type) Basic() (name string, ok bool) { 279 if typ.Kind == BasicKind { 280 name = typ.Name 281 ok = true 282 return 283 } 284 if typ.Kind == IdentKind { 285 name, ok = typ.Elements[0].Basic() 286 return 287 } 288 return 289 } 290 291 func (typ *Type) Clone() (v *Type) { 292 v = &Type{ 293 Kind: typ.Kind, 294 Path: typ.Path, 295 Name: typ.Name, 296 Annotations: typ.Annotations, 297 Paradigms: typ.Paradigms, 298 Tags: typ.Tags, 299 Elements: nil, 300 ParadigmsPacked: typ.ParadigmsPacked, 301 } 302 if typ.Elements != nil && len(typ.Elements) > 0 { 303 v.Elements = make([]*Type, 0, 1) 304 for _, element := range typ.Elements { 305 v.Elements = append(v.Elements, element.Clone()) 306 } 307 } 308 return 309 } 310 311 func (typ *Type) packParadigms(ctx context.Context) (err error) { 312 if typ.ParadigmsPacked != nil { 313 return 314 } 315 switch typ.Kind { 316 case IdentKind, PointerKind, ArrayKind: 317 if typ.Elements == nil || len(typ.Elements) == 0 { 318 err = errors.Warning("element is nil") 319 break 320 } 321 err = typ.Elements[0].packParadigms(ctx) 322 break 323 case MapKind: 324 if typ.Elements == nil || len(typ.Elements) != 2 { 325 err = errors.Warning("element is nil or length is not 2") 326 break 327 } 328 err = typ.Elements[0].packParadigms(ctx) 329 if err != nil { 330 break 331 } 332 err = typ.Elements[1].packParadigms(ctx) 333 if err != nil { 334 break 335 } 336 break 337 case StructKind: 338 if typ.Paradigms == nil || len(typ.Paradigms) == 0 { 339 break 340 } 341 for _, field := range typ.Elements { 342 err = field.packParadigms(ctx) 343 if err != nil { 344 break 345 } 346 } 347 break 348 case StructFieldKind: 349 err = typ.Elements[0].packParadigms(ctx) 350 if err != nil { 351 err = errors.Warning("sources: pack struct field paradigms failed").WithMeta("name", typ.Name).WithCause(err) 352 break 353 } 354 break 355 case ParadigmKind: 356 var topParadigms []*TypeParadigm 357 packing := ctx.Value("packing") 358 if packing != nil { 359 isPacking := false 360 topParadigms, isPacking = packing.([]*TypeParadigm) 361 if !isPacking { 362 err = errors.Warning("sources: context packing value must be []*TypeParadigm") 363 break 364 } 365 } 366 367 pt := typ.Elements[0] 368 paradigms := make([]*TypeParadigm, 0, 1) 369 paradigmKeys := "" 370 stop := false 371 for i, paradigm := range typ.Paradigms { 372 if paradigm.Types[0].Kind == ParadigmElementKind { 373 if topParadigms == nil || len(topParadigms) == 0 { 374 // 其所在类型也是个泛型,不用盒化 375 stop = true 376 break 377 } 378 matched := false 379 for _, topParadigm := range topParadigms { 380 if topParadigm.Name == paradigm.Name { 381 paradigm = topParadigm 382 matched = true 383 break 384 } 385 } 386 if !matched { 387 err = errors.Warning("sources: can not found paradigm instance from top paradigm instances") 388 break 389 } 390 } 391 paradigms = append(paradigms, &TypeParadigm{ 392 Name: pt.Paradigms[i].Name, 393 Types: paradigm.Types, 394 }) 395 paradigmKeys = paradigmKeys + "+" + paradigm.Types[0].Key() 396 } 397 if err != nil { 398 break 399 } 400 if stop { 401 break 402 } 403 packed := pt.Clone() 404 err = packed.packParadigms(context.WithValue(ctx, "packing", paradigms)) 405 if err != nil { 406 break 407 } 408 packed.Name = packed.Name + paradigmKeys 409 typ.ParadigmsPacked = packed 410 break 411 case ParadigmElementKind: 412 if typ.ParadigmsPacked != nil { 413 break 414 } 415 var topParadigms []*TypeParadigm 416 packing := ctx.Value("packing") 417 if packing != nil { 418 isPacking := false 419 topParadigms, isPacking = packing.([]*TypeParadigm) 420 if !isPacking { 421 err = errors.Warning("sources: context packing value must be []*TypeParadigm") 422 break 423 } 424 } 425 if topParadigms == nil || len(topParadigms) == 0 { 426 err = errors.Warning("sources: there is no packing in context") 427 break 428 } 429 packed := false 430 for _, paradigm := range topParadigms { 431 if paradigm.Name == typ.Name { 432 typ.ParadigmsPacked = paradigm.Types[0] 433 packed = true 434 break 435 } 436 } 437 if !packed { 438 err = errors.Warning("sources: pack missed") 439 } 440 break 441 default: 442 break 443 } 444 if err != nil { 445 err = errors.Warning("sources: type pack paradigms failed"). 446 WithMeta("path", typ.Path). 447 WithMeta("name", typ.Name). 448 WithMeta("kind", typ.Kind.String()). 449 WithCause(err) 450 return 451 } 452 453 return 454 } 455 456 type TypeScope struct { 457 Path string 458 Mod *Module 459 Imports Imports 460 GenericDoc string 461 } 462 463 type Types struct { 464 values sync.Map 465 group singleflight.Group 466 } 467 468 func (types *Types) parseType(ctx context.Context, spec *ast.TypeSpec, scope *TypeScope) (typ *Type, err error) { 469 path := scope.Path 470 name := spec.Name.Name 471 472 key := formatTypeKey(path, name) 473 474 processing := ctx.Value(key) 475 if processing != nil { 476 typ = &Type{ 477 Kind: ReferenceKind, 478 Path: path, 479 Name: name, 480 Annotations: nil, 481 Paradigms: nil, 482 Tags: nil, 483 Elements: nil, 484 } 485 return 486 } 487 488 result, doErr, _ := types.group.Do(key, func() (v interface{}, err error) { 489 stored, loaded := types.values.Load(key) 490 if loaded { 491 v = stored.(*Type) 492 return 493 } 494 ctx = context.WithValue(ctx, key, "processing") 495 var result *Type 496 switch spec.Type.(type) { 497 case *ast.Ident: 498 identType, parseIdentTypeErr := types.ParseExpr(ctx, spec.Type, scope) 499 if parseIdentTypeErr != nil { 500 err = errors.Warning("sources: parse ident type spec failed"). 501 WithMeta("path", path).WithMeta("name", name). 502 WithCause(parseIdentTypeErr) 503 break 504 } 505 // annotations 506 doc := "" 507 if spec.Doc != nil && spec.Doc.Text() != "" { 508 doc = spec.Doc.Text() 509 } else { 510 doc = scope.GenericDoc 511 } 512 annotations, parseAnnotationsErr := ParseAnnotations(doc) 513 if parseAnnotationsErr != nil { 514 err = errors.Warning("sources: parse ident type failed"). 515 WithMeta("path", path).WithMeta("name", name). 516 WithCause(parseAnnotationsErr) 517 return 518 } 519 result = &Type{ 520 Kind: IdentKind, 521 Path: path, 522 Name: name, 523 Annotations: annotations, 524 Paradigms: nil, 525 Tags: nil, 526 Elements: []*Type{identType}, 527 } 528 break 529 case *ast.StructType: 530 result, err = types.parseStructType(ctx, spec, scope) 531 break 532 case *ast.InterfaceType: 533 // annotations 534 doc := "" 535 if spec.Doc != nil && spec.Doc.Text() != "" { 536 doc = spec.Doc.Text() 537 } else { 538 doc = scope.GenericDoc 539 } 540 annotations, parseAnnotationsErr := ParseAnnotations(doc) 541 if parseAnnotationsErr != nil { 542 err = errors.Warning("sources: parse interface type failed"). 543 WithMeta("path", path).WithMeta("name", name). 544 WithCause(parseAnnotationsErr) 545 return 546 } 547 result = &Type{ 548 Kind: InterfaceKind, 549 Path: path, 550 Name: name, 551 Annotations: annotations, 552 Paradigms: nil, 553 Tags: nil, 554 Elements: nil, 555 } 556 break 557 case *ast.ArrayType: 558 arrayType := spec.Type.(*ast.ArrayType) 559 arrayElementType, parseArrayElementTypeErr := types.ParseExpr(ctx, arrayType.Elt, scope) 560 if parseArrayElementTypeErr != nil { 561 err = errors.Warning("sources: parse array type spec failed"). 562 WithMeta("path", path).WithMeta("name", name). 563 WithCause(parseArrayElementTypeErr) 564 break 565 } 566 // annotations 567 doc := "" 568 if spec.Doc != nil && spec.Doc.Text() != "" { 569 doc = spec.Doc.Text() 570 } else { 571 doc = scope.GenericDoc 572 } 573 annotations, parseAnnotationsErr := ParseAnnotations(doc) 574 if parseAnnotationsErr != nil { 575 err = errors.Warning("sources: parse array type failed"). 576 WithMeta("path", path).WithMeta("name", name). 577 WithCause(parseAnnotationsErr) 578 return 579 } 580 result = &Type{ 581 Kind: ArrayKind, 582 Path: path, 583 Name: name, 584 Annotations: annotations, 585 Paradigms: nil, 586 Tags: nil, 587 Elements: []*Type{arrayElementType}, 588 } 589 break 590 case *ast.MapType: 591 mapType := spec.Type.(*ast.MapType) 592 keyElement, parseKeyErr := types.ParseExpr(ctx, mapType.Key, scope) 593 if parseKeyErr != nil { 594 err = errors.Warning("sources: parse map type spec failed"). 595 WithMeta("path", path).WithMeta("name", name). 596 WithCause(parseKeyErr) 597 break 598 } 599 if _, basic := keyElement.Basic(); !basic { 600 err = errors.Warning("sources: parse map type spec failed"). 601 WithMeta("path", path).WithMeta("name", name). 602 WithCause(errors.Warning("sources: key kind of map kind field must be basic")) 603 break 604 } 605 valueElement, parseValueErr := types.ParseExpr(ctx, mapType.Value, scope) 606 if parseValueErr != nil { 607 err = errors.Warning("sources: parse map type spec failed"). 608 WithMeta("path", path).WithMeta("name", name). 609 WithCause(parseValueErr) 610 break 611 } 612 // annotations 613 doc := "" 614 if spec.Doc != nil && spec.Doc.Text() != "" { 615 doc = spec.Doc.Text() 616 } else { 617 doc = scope.GenericDoc 618 } 619 annotations, parseAnnotationsErr := ParseAnnotations(doc) 620 if parseAnnotationsErr != nil { 621 err = errors.Warning("sources: parse map type failed"). 622 WithMeta("path", path).WithMeta("name", name). 623 WithCause(parseAnnotationsErr) 624 return 625 } 626 result = &Type{ 627 Kind: MapKind, 628 Path: path, 629 Name: name, 630 Annotations: annotations, 631 Paradigms: nil, 632 Tags: nil, 633 Elements: []*Type{keyElement, valueElement}, 634 } 635 break 636 case *ast.IndexExpr, *ast.IndexListExpr: 637 result, err = types.ParseExpr(ctx, spec.Type, scope) 638 if err != nil { 639 break 640 } 641 result.Path = path 642 result.Name = name 643 if result.ParadigmsPacked != nil { 644 result.ParadigmsPacked.Path = path 645 result.ParadigmsPacked.Name = name 646 } 647 // annotations 648 doc := "" 649 if spec.Doc != nil && spec.Doc.Text() != "" { 650 doc = spec.Doc.Text() 651 } else { 652 doc = scope.GenericDoc 653 } 654 annotations, parseAnnotationsErr := ParseAnnotations(doc) 655 if parseAnnotationsErr != nil { 656 err = errors.Warning("sources: parse map type failed"). 657 WithMeta("path", path).WithMeta("name", name). 658 WithCause(parseAnnotationsErr) 659 return 660 } 661 result.Annotations = annotations 662 break 663 default: 664 err = errors.Warning("sources: unsupported type spec").WithMeta("path", path).WithMeta("name", name).WithMeta("type", reflect.TypeOf(spec.Type).String()) 665 break 666 } 667 if err != nil { 668 return 669 } 670 types.values.Store(key, result) 671 v = result 672 return 673 }) 674 types.group.Forget(key) 675 if doErr != nil { 676 err = doErr 677 return 678 } 679 typ = result.(*Type) 680 return 681 } 682 683 func (types *Types) parseTypeParadigms(ctx context.Context, params *ast.FieldList, scope *TypeScope) (paradigms []*TypeParadigm, err error) { 684 paradigms = make([]*TypeParadigm, 0, 1) 685 for _, param := range params.List { 686 paradigm, paradigmErr := types.parseTypeParadigm(ctx, param, scope) 687 if paradigmErr != nil { 688 err = paradigmErr 689 return 690 } 691 paradigms = append(paradigms, paradigm) 692 } 693 return 694 } 695 696 func (types *Types) parseTypeParadigm(ctx context.Context, param *ast.Field, scope *TypeScope) (paradigm *TypeParadigm, err error) { 697 if param.Names != nil && len(param.Names) > 1 { 698 err = errors.Warning("sources: parse paradigm failed").WithCause(errors.Warning("too many names")) 699 return 700 } 701 name := "" 702 if param.Names != nil { 703 name = param.Names[0].Name 704 } 705 paradigm = &TypeParadigm{ 706 Name: name, 707 Types: make([]*Type, 0, 1), 708 } 709 if param.Type == nil { 710 return 711 } 712 713 switch param.Type.(type) { 714 case *ast.BinaryExpr: 715 exprs := types.parseTypeParadigmBinaryExpr(param.Type.(*ast.BinaryExpr)) 716 for _, expr := range exprs { 717 typ, parseTypeErr := types.ParseExpr(ctx, expr, scope) 718 if parseTypeErr != nil { 719 err = errors.Warning("sources: parse paradigm failed").WithMeta("name", name).WithCause(parseTypeErr) 720 return 721 } 722 paradigm.Types = append(paradigm.Types, typ) 723 } 724 break 725 default: 726 typ, parseTypeErr := types.ParseExpr(ctx, param.Type, scope) 727 if parseTypeErr != nil { 728 err = errors.Warning("sources: parse paradigm failed").WithMeta("name", name).WithCause(parseTypeErr) 729 return 730 } 731 paradigm.Types = append(paradigm.Types, typ) 732 break 733 } 734 return 735 } 736 737 func (types *Types) parseTypeParadigmBinaryExpr(bin *ast.BinaryExpr) (exprs []ast.Expr) { 738 exprs = make([]ast.Expr, 0, 1) 739 xBin, isXBin := bin.X.(*ast.BinaryExpr) 740 if isXBin { 741 exprs = append(exprs, types.parseTypeParadigmBinaryExpr(xBin)...) 742 } else { 743 exprs = append(exprs, bin.X) 744 } 745 yBin, isYBin := bin.Y.(*ast.BinaryExpr) 746 if isYBin { 747 exprs = append(exprs, types.parseTypeParadigmBinaryExpr(yBin)...) 748 } else { 749 exprs = append(exprs, bin.Y) 750 } 751 return 752 } 753 754 func (types *Types) ParseExpr(ctx context.Context, x ast.Expr, scope *TypeScope) (typ *Type, err error) { 755 switch x.(type) { 756 case *ast.Ident: 757 expr := x.(*ast.Ident) 758 if expr.Obj == nil { 759 if expr.Name == "any" { 760 typ = AnyType 761 break 762 } 763 isBasic := expr.Name == "string" || 764 expr.Name == "bool" || 765 expr.Name == "int" || expr.Name == "int8" || expr.Name == "int16" || expr.Name == "int32" || expr.Name == "int64" || 766 expr.Name == "uint" || expr.Name == "uint8" || expr.Name == "uint16" || expr.Name == "uint32" || expr.Name == "uint64" || 767 expr.Name == "float32" || expr.Name == "float64" || 768 expr.Name == "complex64" || expr.Name == "complex128" || 769 expr.Name == "byte" 770 if isBasic { 771 typ = &Type{ 772 Kind: BasicKind, 773 Path: "", 774 Name: expr.Name, 775 Annotations: Annotations{}, 776 Paradigms: make([]*TypeParadigm, 0, 1), 777 Elements: make([]*Type, 0, 1), 778 } 779 break 780 } else { 781 typ, err = scope.Mod.ParseType(ctx, scope.Path, expr.Name) 782 //err = errors.Warning("sources: kind of ident expr object must be type and decl must not be nil") 783 break 784 } 785 } 786 if expr.Obj.Kind != ast.Typ || expr.Obj.Decl == nil { 787 err = errors.Warning("sources: kind of ident expr object must be type and decl must not be nil") 788 break 789 } 790 switch expr.Obj.Decl.(type) { 791 case *ast.Field: 792 // paradigms 793 field := expr.Obj.Decl.(*ast.Field) 794 paradigm, parseParadigmsErr := types.parseTypeParadigm(ctx, field, scope) 795 if parseParadigmsErr != nil { 796 err = parseParadigmsErr 797 break 798 } 799 typ = &Type{ 800 Kind: ParadigmElementKind, 801 Path: "", 802 Name: paradigm.Name, 803 Annotations: nil, 804 Paradigms: nil, 805 Tags: nil, 806 Elements: paradigm.Types, 807 } 808 break 809 case *ast.TypeSpec: 810 // type 811 spec := expr.Obj.Decl.(*ast.TypeSpec) 812 typ, err = scope.Mod.ParseType(ctx, scope.Path, spec.Name.Name) 813 break 814 default: 815 err = errors.Warning("sources: unsupported ident expr object decl").WithMeta("decl", reflect.TypeOf(expr.Obj.Decl).String()) 816 break 817 } 818 break 819 case *ast.InterfaceType: 820 typ = AnyType 821 break 822 case *ast.SelectorExpr: 823 expr := x.(*ast.SelectorExpr) 824 ident, isIdent := expr.X.(*ast.Ident) 825 if !isIdent { 826 err = errors.Warning("sources: x type of selector field must be ident").WithMeta("selector_x", reflect.TypeOf(expr.X).String()) 827 break 828 } 829 // path 830 importer, hasImporter := scope.Imports.Find(ident.Name) 831 if !hasImporter { 832 err = errors.Warning("sources: import of selector field was not found").WithMeta("import", ident.Name) 833 break 834 } 835 // name 836 name := expr.Sel.Name 837 builtin, isBuiltin := scope.Mod.GetBuiltinType(importer.Path, name) 838 if isBuiltin { 839 typ = builtin 840 break 841 } 842 // find in mod 843 typ, err = scope.Mod.ParseType(ctx, importer.Path, expr.Sel.Name) 844 break 845 case *ast.StarExpr: 846 expr := x.(*ast.StarExpr) 847 starElement, parseStarErr := types.ParseExpr(ctx, expr.X, scope) 848 if parseStarErr != nil { 849 err = parseStarErr 850 break 851 } 852 typ = &Type{ 853 Kind: PointerKind, 854 Path: "", 855 Name: "", 856 Annotations: nil, 857 Paradigms: nil, 858 Tags: nil, 859 Elements: []*Type{starElement}, 860 } 861 break 862 case *ast.ArrayType: 863 expr := x.(*ast.ArrayType) 864 arrayElement, parseArrayErr := types.ParseExpr(ctx, expr.Elt, scope) 865 if parseArrayErr != nil { 866 err = parseArrayErr 867 break 868 } 869 typ = &Type{ 870 Kind: ArrayKind, 871 Path: "", 872 Name: "", 873 Annotations: nil, 874 Paradigms: nil, 875 Tags: nil, 876 Elements: []*Type{arrayElement}, 877 } 878 break 879 case *ast.MapType: 880 expr := x.(*ast.MapType) 881 keyElement, parseKeyErr := types.ParseExpr(ctx, expr.Key, scope) 882 if parseKeyErr != nil { 883 err = parseKeyErr 884 break 885 } 886 if _, basic := keyElement.Basic(); !basic { 887 err = errors.Warning("sources: key kind of map kind field must be basic") 888 break 889 } 890 valueElement, parseValueErr := types.ParseExpr(ctx, expr.Value, scope) 891 if parseValueErr != nil { 892 err = parseValueErr 893 break 894 } 895 typ = &Type{ 896 Kind: MapKind, 897 Path: "", 898 Name: "", 899 Annotations: nil, 900 Paradigms: nil, 901 Tags: nil, 902 Elements: []*Type{keyElement, valueElement}, 903 } 904 break 905 case *ast.IndexExpr: 906 expr := x.(*ast.IndexExpr) 907 paradigmType, parseParadigmTypeErr := types.ParseExpr(ctx, expr.Index, scope) 908 if parseParadigmTypeErr != nil { 909 err = parseParadigmTypeErr 910 break 911 } 912 paradigms := []*TypeParadigm{{ 913 Name: "", 914 Types: []*Type{paradigmType}, 915 }} 916 xType, parseXErr := types.ParseExpr(ctx, expr.X, scope) 917 if parseXErr != nil { 918 err = parseXErr 919 break 920 } 921 if xType.Paradigms == nil || len(xType.Paradigms) != len(paradigms) { 922 err = errors.Warning("sources: parse index expr failed").WithCause(errors.Warning("sources: invalid paradigms in x type")) 923 return 924 } 925 for i, paradigm := range xType.Paradigms { 926 paradigms[i].Name = paradigm.Name 927 } 928 typ = &Type{ 929 Kind: ParadigmKind, 930 Path: "", 931 Name: "", 932 Annotations: nil, 933 Paradigms: paradigms, 934 Tags: nil, 935 Elements: []*Type{xType}, 936 ParadigmsPacked: nil, 937 } 938 packErr := typ.packParadigms(ctx) 939 if packErr != nil { 940 err = packErr 941 break 942 } 943 break 944 case *ast.IndexListExpr: 945 expr := x.(*ast.IndexListExpr) 946 paradigmTypes := make([]*Type, 0, 1) 947 for _, index := range expr.Indices { 948 paradigmType, parseParadigmTypeErr := types.ParseExpr(ctx, index, scope) 949 if parseParadigmTypeErr != nil { 950 err = parseParadigmTypeErr 951 break 952 } 953 paradigmTypes = append(paradigmTypes, paradigmType) 954 } 955 paradigms := make([]*TypeParadigm, 0, 1) 956 for _, paradigmType := range paradigmTypes { 957 paradigms = append(paradigms, &TypeParadigm{ 958 Name: "", 959 Types: []*Type{paradigmType}, 960 }) 961 } 962 xType, parseXErr := types.ParseExpr(ctx, expr.X, scope) 963 if parseXErr != nil { 964 err = parseXErr 965 break 966 } 967 if xType.Paradigms == nil || len(xType.Paradigms) != len(paradigms) { 968 err = errors.Warning("sources: parse index list expr failed").WithCause(errors.Warning("sources: invalid paradigms in x type")) 969 return 970 } 971 for i, paradigm := range xType.Paradigms { 972 paradigms[i].Name = paradigm.Name 973 } 974 typ = &Type{ 975 Kind: ParadigmKind, 976 Path: "", 977 Name: "", 978 Annotations: nil, 979 Paradigms: paradigms, 980 Tags: nil, 981 Elements: []*Type{xType}, 982 ParadigmsPacked: nil, 983 } 984 packErr := typ.packParadigms(ctx) 985 if packErr != nil { 986 err = packErr 987 break 988 } 989 break 990 default: 991 err = errors.Warning("sources: unsupported field type").WithMeta("type", reflect.TypeOf(x).String()) 992 return 993 } 994 return 995 } 996 997 func (types *Types) parseStructType(ctx context.Context, spec *ast.TypeSpec, scope *TypeScope) (typ *Type, err error) { 998 path := scope.Path 999 name := spec.Name.Name 1000 st, typeOk := spec.Type.(*ast.StructType) 1001 if !typeOk { 1002 err = errors.Warning("sources: parse struct type failed"). 1003 WithMeta("path", path).WithMeta("name", name). 1004 WithCause(errors.Warning("type of spec is not ast.StructType").WithMeta("type", reflect.TypeOf(spec.Type).String())) 1005 return 1006 } 1007 typ = &Type{ 1008 Kind: StructKind, 1009 Path: path, 1010 Name: name, 1011 Annotations: nil, 1012 Paradigms: nil, 1013 Tags: nil, 1014 Elements: nil, 1015 } 1016 // annotations 1017 doc := "" 1018 if spec.Doc != nil && spec.Doc.Text() != "" { 1019 doc = spec.Doc.Text() 1020 } else { 1021 doc = scope.GenericDoc 1022 } 1023 annotations, parseAnnotationsErr := ParseAnnotations(doc) 1024 if parseAnnotationsErr != nil { 1025 err = errors.Warning("sources: parse struct type failed"). 1026 WithMeta("path", path).WithMeta("name", name). 1027 WithCause(parseAnnotationsErr) 1028 return 1029 } 1030 typ.Annotations = annotations 1031 // paradigms 1032 if spec.TypeParams != nil && spec.TypeParams.NumFields() > 0 { 1033 paradigms, parseParadigmsErr := types.parseTypeParadigms(ctx, spec.TypeParams, scope) 1034 if parseParadigmsErr != nil { 1035 err = errors.Warning("sources: parse struct type failed"). 1036 WithMeta("path", path).WithMeta("name", name). 1037 WithCause(parseParadigmsErr) 1038 return 1039 } 1040 typ.Paradigms = paradigms 1041 } 1042 // elements 1043 if st.Fields != nil && st.Fields.NumFields() > 0 { 1044 typ.Elements = make([]*Type, 0, 1) 1045 for i, field := range st.Fields.List { 1046 if field.Names != nil && len(field.Names) > 1 { 1047 err = errors.Warning("sources: parse struct type failed"). 1048 WithMeta("path", path).WithMeta("name", name). 1049 WithCause(errors.Warning("sources: too many names of one field")).WithMeta("field_no", fmt.Sprintf("%d", i)) 1050 return 1051 } 1052 if field.Names == nil || len(field.Names) == 0 { 1053 // compose 1054 if field.Type != nil { 1055 fieldElementType, parseFieldElementTypeErr := types.ParseExpr(ctx, field.Type, scope) 1056 if parseFieldElementTypeErr != nil { 1057 err = errors.Warning("sources: parse struct type failed"). 1058 WithMeta("path", path).WithMeta("name", name). 1059 WithCause(parseFieldElementTypeErr).WithMeta("field_no", fmt.Sprintf("%d", i)) 1060 return 1061 } 1062 typ.Elements = append(typ.Elements, &Type{ 1063 Kind: StructFieldKind, 1064 Path: "", 1065 Name: "", 1066 Annotations: nil, 1067 Paradigms: nil, 1068 Tags: nil, 1069 Elements: []*Type{fieldElementType}, 1070 }) 1071 } else { 1072 err = errors.Warning("sources: parse struct type failed"). 1073 WithMeta("path", path).WithMeta("name", name). 1074 WithCause(errors.Warning("sources: unsupported field")).WithMeta("field_no", fmt.Sprintf("%d", i)) 1075 return 1076 } 1077 return 1078 } 1079 if !ast.IsExported(field.Names[0].Name) { 1080 continue 1081 } 1082 ft := &Type{ 1083 Kind: StructFieldKind, 1084 Path: "", 1085 Name: "", 1086 Annotations: nil, 1087 Paradigms: nil, 1088 Tags: nil, 1089 Elements: nil, 1090 } 1091 // name 1092 ft.Name = field.Names[0].Name 1093 // tag 1094 if field.Tag != nil && field.Tag.Value != "" { 1095 ft.Tags = parseFieldTag(field.Tag.Value) 1096 } 1097 // annotations 1098 if field.Doc != nil && field.Doc.Text() != "" { 1099 fieldAnnotations, parseFieldAnnotationsErr := ParseAnnotations(field.Doc.Text()) 1100 if parseFieldAnnotationsErr != nil { 1101 err = errors.Warning("sources: parse struct type failed"). 1102 WithMeta("path", path).WithMeta("name", name). 1103 WithCause(parseFieldAnnotationsErr). 1104 WithMeta("field_no", fmt.Sprintf("%d", i)). 1105 WithMeta("field", ft.Name) 1106 return 1107 } 1108 ft.Annotations = fieldAnnotations 1109 } 1110 // element 1111 fieldElementType, parseFieldElementTypeErr := types.ParseExpr(ctx, field.Type, scope) 1112 if parseFieldElementTypeErr != nil { 1113 err = errors.Warning("sources: parse struct type failed"). 1114 WithMeta("path", path).WithMeta("name", name). 1115 WithCause(parseFieldElementTypeErr). 1116 WithMeta("field_no", fmt.Sprintf("%d", i)). 1117 WithMeta("field", ft.Name) 1118 return 1119 } 1120 ft.Elements = []*Type{fieldElementType} 1121 typ.Elements = append(typ.Elements, ft) 1122 } 1123 } 1124 return 1125 } 1126 1127 func (types *Types) IsContextType(expr ast.Expr, imports Imports) (ok bool) { 1128 e, isSelector := expr.(*ast.SelectorExpr) 1129 if !isSelector { 1130 return 1131 } 1132 if e.X == nil { 1133 return 1134 } 1135 ident, isIdent := e.X.(*ast.Ident) 1136 if !isIdent { 1137 return 1138 } 1139 pkg := ident.Name 1140 if pkg == "" { 1141 return 1142 } 1143 if e.Sel == nil { 1144 return 1145 } 1146 ok = e.Sel.Name == "Context" 1147 if !ok { 1148 return 1149 } 1150 importer, has := imports.Find(pkg) 1151 if !has { 1152 return 1153 } 1154 ok = importer.Path == "github.com/aacfactory/fns/context" 1155 return 1156 } 1157 1158 func (types *Types) IsCodeErrorType(expr ast.Expr, imports Imports) (ok bool) { 1159 switch e := expr.(type) { 1160 case *ast.Ident: 1161 ok = e.Name == "error" 1162 break 1163 case *ast.SelectorExpr: 1164 if e.X == nil { 1165 return 1166 } 1167 ident, isIdent := e.X.(*ast.Ident) 1168 if !isIdent { 1169 return 1170 } 1171 pkg := ident.Name 1172 if pkg == "" { 1173 return 1174 } 1175 if e.Sel == nil { 1176 return 1177 } 1178 ok = e.Sel.Name == "CodeError" 1179 if !ok { 1180 return 1181 } 1182 importer, has := imports.Find(pkg) 1183 if !has { 1184 return 1185 } 1186 ok = importer.Path == "github.com/aacfactory/errors" 1187 break 1188 default: 1189 return 1190 } 1191 return 1192 }