418 lines
8.3 KiB
Go
418 lines
8.3 KiB
Go
/*
|
|
* Copyright 2022 CloudWeGo Authors
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
package model
|
|
|
|
import (
|
|
"errors"
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
type Kind uint
|
|
|
|
const (
|
|
KindInvalid Kind = iota
|
|
KindBool
|
|
KindInt
|
|
KindInt8
|
|
KindInt16
|
|
KindInt32
|
|
KindInt64
|
|
KindUint
|
|
KindUint8
|
|
KindUint16
|
|
KindUint32
|
|
KindUint64
|
|
KindUintptr
|
|
KindFloat32
|
|
KindFloat64
|
|
KindComplex64
|
|
KindComplex128
|
|
KindArray
|
|
KindChan
|
|
KindFunc
|
|
KindInterface
|
|
KindMap
|
|
KindPtr
|
|
KindSlice
|
|
KindString
|
|
KindStruct
|
|
KindUnsafePointer
|
|
)
|
|
|
|
type Category int64
|
|
|
|
const (
|
|
CategoryConstant Category = 1
|
|
CategoryBinary Category = 8
|
|
CategoryMap Category = 9
|
|
CategoryList Category = 10
|
|
CategorySet Category = 11
|
|
CategoryEnum Category = 12
|
|
CategoryStruct Category = 13
|
|
CategoryUnion Category = 14
|
|
CategoryException Category = 15
|
|
CategoryTypedef Category = 16
|
|
CategoryService Category = 17
|
|
)
|
|
|
|
type Model struct {
|
|
FilePath string
|
|
Package string
|
|
Imports map[string]*Model //{{import}}:Model
|
|
|
|
// rendering data
|
|
PackageName string
|
|
// Imports map[string]string //{{alias}}:{{import}}
|
|
Typedefs []TypeDef
|
|
Constants []Constant
|
|
Variables []Variable
|
|
Functions []Function
|
|
Enums []Enum
|
|
Structs []Struct
|
|
Methods []Method
|
|
Oneofs []Oneof
|
|
}
|
|
|
|
func (m Model) IsEmpty() bool {
|
|
return len(m.Typedefs) == 0 && len(m.Constants) == 0 && len(m.Variables) == 0 &&
|
|
len(m.Functions) == 0 && len(m.Enums) == 0 && len(m.Structs) == 0 && len(m.Methods) == 0
|
|
}
|
|
|
|
type Models []*Model
|
|
|
|
func (a *Models) MergeMap(b map[string]*Model) {
|
|
for _, v := range b {
|
|
insert := true
|
|
for _, p := range *a {
|
|
if p == v {
|
|
insert = false
|
|
}
|
|
}
|
|
if insert {
|
|
*a = append(*a, v)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
func (a *Models) MergeArray(b []*Model) {
|
|
for _, v := range b {
|
|
insert := true
|
|
for _, p := range *a {
|
|
if p == v {
|
|
insert = false
|
|
}
|
|
}
|
|
if insert {
|
|
*a = append(*a, v)
|
|
}
|
|
}
|
|
return
|
|
}
|
|
|
|
type RequiredNess int
|
|
|
|
const (
|
|
RequiredNess_Default RequiredNess = 0
|
|
RequiredNess_Required RequiredNess = 1
|
|
RequiredNess_Optional RequiredNess = 2
|
|
)
|
|
|
|
type Type struct {
|
|
Name string
|
|
Scope *Model
|
|
Kind Kind
|
|
Indirect bool
|
|
Category Category
|
|
Extra []*Type // [{key_type},{value_type}] for map, [{element_type}] for list or set
|
|
HasNew bool
|
|
}
|
|
|
|
func (rt *Type) ResolveDefaultValue() string {
|
|
if rt == nil {
|
|
return ""
|
|
}
|
|
switch rt.Kind {
|
|
case KindInt, KindInt8, KindInt16, KindInt32, KindInt64, KindUint, KindUint16, KindUint32, KindUint64,
|
|
KindFloat32, KindFloat64, KindComplex64, KindComplex128:
|
|
return "0"
|
|
case KindBool:
|
|
return "false"
|
|
case KindString:
|
|
return "\"\""
|
|
default:
|
|
return "nil"
|
|
}
|
|
}
|
|
|
|
func (rt *Type) ResolveNameForTypedef(scope *Model) (string, error) {
|
|
if rt == nil {
|
|
return "", errors.New("type is nil")
|
|
}
|
|
name := rt.Name
|
|
if rt.Scope == nil {
|
|
return rt.Name, nil
|
|
}
|
|
|
|
switch rt.Kind {
|
|
case KindArray, KindSlice:
|
|
if len(rt.Extra) != 1 {
|
|
return "", fmt.Errorf("the type: %s should have 1 extra type, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveName, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("[]%s", resolveName)
|
|
case KindMap:
|
|
if len(rt.Extra) != 2 {
|
|
return "", fmt.Errorf("the type: %s should have 2 extra types, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveKey, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
resolveValue, err := rt.Extra[1].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("map[%s]%s", resolveKey, resolveValue)
|
|
case KindChan:
|
|
if len(rt.Extra) != 1 {
|
|
return "", fmt.Errorf("the type: %s should have 1 extra type, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveName, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("chan %s", resolveName)
|
|
}
|
|
|
|
if scope != nil && rt.Scope != &BaseModel && rt.Scope.Package != scope.Package {
|
|
name = rt.Scope.PackageName + "." + name
|
|
}
|
|
return name, nil
|
|
}
|
|
|
|
func (rt *Type) ResolveName(scope *Model) (string, error) {
|
|
if rt == nil {
|
|
return "", fmt.Errorf("type is nil")
|
|
}
|
|
name := rt.Name
|
|
if rt.Scope == nil {
|
|
if rt.Kind == KindStruct {
|
|
return "*" + rt.Name, nil
|
|
}
|
|
return rt.Name, nil
|
|
}
|
|
|
|
if rt.Category == CategoryTypedef {
|
|
if scope != nil && rt.Scope != &BaseModel && rt.Scope.Package != scope.Package {
|
|
name = rt.Scope.PackageName + "." + name
|
|
}
|
|
|
|
if rt.Kind == KindStruct {
|
|
name = "*" + name
|
|
}
|
|
|
|
return name, nil
|
|
}
|
|
|
|
switch rt.Kind {
|
|
case KindArray, KindSlice:
|
|
if len(rt.Extra) != 1 {
|
|
return "", fmt.Errorf("The type: %s should have 1 extra type, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveName, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("[]%s", resolveName)
|
|
case KindMap:
|
|
if len(rt.Extra) != 2 {
|
|
return "", fmt.Errorf("The type: %s should have 2 extra type, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveKey, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
resolveValue, err := rt.Extra[1].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("map[%s]%s", resolveKey, resolveValue)
|
|
case KindChan:
|
|
if len(rt.Extra) != 1 {
|
|
return "", fmt.Errorf("The type: %s should have 1 extra type, but has %d", rt.Name, len(rt.Extra))
|
|
}
|
|
resolveName, err := rt.Extra[0].ResolveName(scope)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
name = fmt.Sprintf("chan %s", resolveName)
|
|
}
|
|
|
|
if scope != nil && rt.Scope != &BaseModel && rt.Scope.Package != scope.Package {
|
|
name = rt.Scope.PackageName + "." + name
|
|
}
|
|
|
|
if rt.Kind == KindStruct {
|
|
name = "*" + name
|
|
}
|
|
return name, nil
|
|
}
|
|
|
|
func (rt *Type) IsBinary() bool {
|
|
return rt.Category == CategoryBinary && (rt.Kind == KindSlice || rt.Kind == KindArray)
|
|
}
|
|
|
|
func (rt *Type) IsBaseType() bool {
|
|
return rt.Kind < KindComplex64
|
|
}
|
|
|
|
func (rt *Type) IsSettable() bool {
|
|
switch rt.Kind {
|
|
case KindArray, KindChan, KindFunc, KindInterface, KindMap, KindPtr, KindSlice, KindUnsafePointer:
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
type TypeDef struct {
|
|
Scope *Model
|
|
Alias string
|
|
Type *Type
|
|
}
|
|
|
|
type Constant struct {
|
|
Scope *Model
|
|
Name string
|
|
Type *Type
|
|
Value Literal
|
|
}
|
|
|
|
type Literal interface {
|
|
Expression() string
|
|
}
|
|
|
|
type Variable struct {
|
|
Scope *Model
|
|
Name string
|
|
Type *Type
|
|
Value Literal
|
|
}
|
|
|
|
type Function struct {
|
|
Scope *Model
|
|
Name string
|
|
Args []Variable
|
|
Rets []Variable
|
|
Code string
|
|
}
|
|
|
|
type Method struct {
|
|
Scope *Model
|
|
ReceiverName string
|
|
ReceiverType *Type
|
|
ByPtr bool
|
|
Function
|
|
}
|
|
|
|
type Enum struct {
|
|
Scope *Model
|
|
Name string
|
|
GoType string
|
|
Values []Constant
|
|
}
|
|
|
|
type Struct struct {
|
|
Scope *Model
|
|
Name string
|
|
Fields []Field
|
|
Category Category
|
|
LeadingComments string
|
|
}
|
|
|
|
type Field struct {
|
|
Scope *Struct
|
|
Name string
|
|
Type *Type
|
|
IsSetDefault bool
|
|
DefaultValue Literal
|
|
Required RequiredNess
|
|
Tags Tags
|
|
LeadingComments string
|
|
TrailingComments string
|
|
IsPointer bool
|
|
}
|
|
|
|
type Oneof struct {
|
|
MessageName string
|
|
OneofName string
|
|
InterfaceName string
|
|
Choices []Choice
|
|
}
|
|
|
|
type Choice struct {
|
|
MessageName string
|
|
ChoiceName string
|
|
Type *Type
|
|
}
|
|
|
|
type Tags []Tag
|
|
|
|
type Tag struct {
|
|
Key string
|
|
Value string
|
|
IsDefault bool // default tag
|
|
}
|
|
|
|
func (ts Tags) String() string {
|
|
ret := make([]string, 0, len(ts))
|
|
for _, t := range ts {
|
|
ret = append(ret, fmt.Sprintf("%v:%q", t.Key, t.Value))
|
|
}
|
|
return strings.Join(ret, " ")
|
|
}
|
|
|
|
func (ts *Tags) Remove(name string) {
|
|
ret := make([]Tag, 0, len(*ts))
|
|
for _, t := range *ts {
|
|
if t.Key != name {
|
|
ret = append(ret, t)
|
|
}
|
|
}
|
|
*ts = ret
|
|
}
|
|
|
|
func (ts Tags) Len() int { return len(ts) }
|
|
|
|
func (ts Tags) Less(i, j int) bool {
|
|
return ts[i].Key < ts[j].Key
|
|
}
|
|
|
|
func (ts Tags) Swap(i, j int) { ts[i], ts[j] = ts[j], ts[i] }
|
|
|
|
func (f Field) GenGoTags() string {
|
|
if len(f.Tags) == 0 {
|
|
return ""
|
|
}
|
|
|
|
return fmt.Sprintf("`%s`", f.Tags.String())
|
|
}
|