github.com/morlay/goqcloud@v0.0.0-20181123023149-b00e0b0b9afc/generator/type_schema.go (about)

     1  package generator
     2  
     3  import (
     4  	"sort"
     5  	"strings"
     6  
     7  	"github.com/go-courier/codegen"
     8  )
     9  
    10  type TypeSchema struct {
    11  	ImportPath     string
    12  	Name           string
    13  	Desc           string
    14  	Type           *BasicType
    15  	Items          *TypeSchema
    16  	AdditionalProp *TypeSchema
    17  	AllOf          []*TypeSchema
    18  	Props          map[string]*TypeSchema
    19  	Required       bool
    20  	Tag            string
    21  }
    22  
    23  func (s *TypeSchema) IsRef() bool {
    24  	return s.Type == nil && !s.IsArray() && !s.IsMap() && !s.IsObject()
    25  }
    26  
    27  func (s *TypeSchema) IsArray() bool {
    28  	return s.Items != nil
    29  }
    30  
    31  func (s *TypeSchema) IsObject() bool {
    32  	return s.Props != nil || len(s.AllOf) > 0
    33  }
    34  
    35  func (s *TypeSchema) IsMap() bool {
    36  	return s.AdditionalProp != nil
    37  }
    38  
    39  func (s *TypeSchema) Write(file *codegen.File) {
    40  	file.WriteBlock(
    41  		codegen.Comments(s.Desc),
    42  		codegen.DeclType(
    43  			codegen.Var(s.SnippetType(file), s.Name),
    44  		),
    45  	)
    46  }
    47  
    48  func (s *TypeSchema) SnippetType(file *codegen.File) codegen.SnippetType {
    49  	if s.IsArray() {
    50  		return codegen.Slice(s.Items.SnippetType(file))
    51  	}
    52  
    53  	if s.IsObject() {
    54  		fields := make([]*codegen.SnippetField, 0)
    55  
    56  		for _, embedType := range s.AllOf {
    57  			fields = append(fields, codegen.Var(embedType.SnippetType(file)))
    58  		}
    59  
    60  		names := make([]string, 0)
    61  		for name := range s.Props {
    62  			names = append(names, name)
    63  		}
    64  		sort.Strings(names)
    65  
    66  		for _, name := range names {
    67  			prop := s.Props[name]
    68  
    69  			tags := map[string][]string{}
    70  			tag := s.Tag
    71  			if tag == "" {
    72  				tag = "json"
    73  			}
    74  			tags[tag] = append(tags[tag], name)
    75  			if !prop.Required {
    76  				tags[tag] = append(tags[tag], "omitempty")
    77  			}
    78  
    79  			fields = append(fields, codegen.Var(prop.SnippetType(file), name).WithTags(tags).WithComments(prop.Desc))
    80  		}
    81  
    82  		return codegen.Struct(fields...)
    83  	}
    84  
    85  	maybeStarType := func(tpe codegen.SnippetType) codegen.SnippetType {
    86  		if !s.Required {
    87  			return codegen.Star(tpe)
    88  		}
    89  		return tpe
    90  	}
    91  
    92  	if s.Name != "" {
    93  		if s.ImportPath != "" {
    94  			return maybeStarType(codegen.Type(file.Use(s.ImportPath, s.Name)))
    95  		}
    96  		return maybeStarType(codegen.Type(s.Name))
    97  
    98  	}
    99  
   100  	if s.Type != nil {
   101  		switch *s.Type {
   102  		case BasicTypeBoolean:
   103  			return maybeStarType(codegen.Bool)
   104  		case BasicTypeString:
   105  			return maybeStarType(codegen.String)
   106  		case BasicTypeInteger:
   107  			return maybeStarType(codegen.Int64)
   108  		case BasicTypeFloat:
   109  			return maybeStarType(codegen.Float64)
   110  		case BasicTypeTimestamp, BasicTypeDate:
   111  			return maybeStarType(codegen.Type(file.Use("time", "Time")))
   112  		}
   113  	}
   114  
   115  	return codegen.Interface()
   116  }
   117  
   118  func (s *TypeSchema) AddProp(name string, propSchema *TypeSchema) {
   119  	if s.Props == nil {
   120  		s.Props = map[string]*TypeSchema{}
   121  	}
   122  	if s.Props[name] == nil {
   123  		s.Props[name] = propSchema
   124  	}
   125  }
   126  
   127  type BasicType string
   128  
   129  const (
   130  	BasicTypeDate      BasicType = "Date"
   131  	BasicTypeTimestamp BasicType = "Timestamp"
   132  	BasicTypeString    BasicType = "String"
   133  	BasicTypeInteger   BasicType = "Integer"
   134  	BasicTypeBoolean   BasicType = "Boolean"
   135  	BasicTypeFloat     BasicType = "Float"
   136  )
   137  
   138  const arrayPrefix = "Array of "
   139  
   140  func IsArrayType(tpe string) bool {
   141  	return strings.HasPrefix(tpe, arrayPrefix)
   142  }
   143  
   144  func IndirectType(tpe string) (basicType *BasicType) {
   145  	t := BasicType(strings.TrimLeft(tpe, arrayPrefix))
   146  	return &t
   147  }