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  }