github.com/mailru/activerecord@v1.12.2/internal/pkg/parser/field.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "go/ast" 6 "strconv" 7 "strings" 8 9 "github.com/mailru/activerecord/internal/pkg/arerror" 10 "github.com/mailru/activerecord/internal/pkg/ds" 11 "github.com/mailru/activerecord/pkg/octopus" 12 ) 13 14 // Функция парсинга тегов полей модели 15 func ParseFieldsTag(field *ast.Field, newfield *ds.FieldDeclaration, newindex *ds.IndexDeclaration) error { 16 tagParam, err := splitTag(field, NoCheckFlag, map[TagNameType]ParamValueRule{PrimaryKeyTag: ParamNotNeedValue, UniqueTag: ParamNotNeedValue}) 17 if err != nil { 18 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: string(newfield.Format), Err: err} 19 } 20 21 if len(tagParam) > 0 { 22 for _, kv := range tagParam { 23 switch TagNameType(kv[0]) { 24 case SelectorTag: 25 newindex.Name = newfield.Name 26 newindex.Selector = kv[1] 27 case PrimaryKeyTag: 28 newindex.Name = newfield.Name 29 newindex.Primary = true 30 case UniqueTag: 31 newindex.Name = newfield.Name 32 newindex.Unique = true 33 case MutatorsTag: 34 newfield.Mutators = strings.Split(kv[1], ",") 35 case SizeTag: 36 if kv[1] != "" { 37 size, err := strconv.ParseInt(kv[1], 10, 64) 38 if err != nil { 39 return &arerror.ErrParseTypeFieldTagDecl{Name: newfield.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagValueInvalid} 40 } 41 42 newfield.Size = size 43 } 44 case SerializerTag: 45 newfield.Serializer = strings.Split(kv[1], ",") 46 default: 47 return &arerror.ErrParseTypeFieldTagDecl{Name: newfield.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagUnknown} 48 } 49 } 50 } 51 52 return nil 53 } 54 55 // Функция парсинга полей модели 56 func ParseFields(dst *ds.RecordPackage, fields []*ast.Field) error { 57 for _, field := range fields { 58 if field.Names == nil || len(field.Names) != 1 { 59 return &arerror.ErrParseTypeFieldDecl{Err: arerror.ErrNameDeclaration} 60 } 61 62 newfield := ds.FieldDeclaration{ 63 Name: field.Names[0].Name, 64 Mutators: []string{}, 65 Serializer: []string{}, 66 } 67 68 newindex := ds.IndexDeclaration{ 69 FieldsMap: map[string]ds.IndexField{}, 70 } 71 72 switch t := field.Type.(type) { 73 case *ast.Ident: 74 newfield.Format = octopus.Format(t.String()) 75 case *ast.ArrayType: 76 //Todo точно ли массив надо, а не срез? 77 if t.Elt.(*ast.Ident).Name != "byte" { 78 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseFieldArrayOfNotByte} 79 } 80 81 if t.Len == nil { 82 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseFieldArrayNotSlice} 83 } 84 85 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseFieldBinary} 86 default: 87 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: fmt.Sprintf("%T", t), Err: arerror.ErrUnknown} 88 } 89 90 if err := ParseFieldsTag(field, &newfield, &newindex); err != nil { 91 return fmt.Errorf("error ParseFieldsTag: %w", err) 92 } 93 94 if err := dst.AddField(newfield); err != nil { 95 return err 96 } 97 98 if newindex.Name != "" { 99 newindex.Fields = append(newindex.Fields, len(dst.Fields)-1) 100 newindex.FieldsMap[newfield.Name] = ds.IndexField{IndField: len(dst.Fields) - 1, Order: ds.IndexOrderAsc} 101 102 errIndex := dst.AddIndex(newindex) 103 if errIndex != nil { 104 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: string(newfield.Format), Err: errIndex} 105 } 106 } 107 } 108 109 return nil 110 } 111 112 // ParseProcFieldsTag парсинг тегов полей декларации процедуры 113 func ParseProcFieldsTag(index int, field *ast.Field, newfield *ds.ProcFieldDeclaration) error { 114 tagParam, err := splitTag(field, NoCheckFlag, map[TagNameType]ParamValueRule{PrimaryKeyTag: ParamNotNeedValue, UniqueTag: ParamNotNeedValue}) 115 if err != nil { 116 return &arerror.ErrParseTypeFieldDecl{Name: newfield.Name, FieldType: string(newfield.Format), Err: err} 117 } 118 119 if len(tagParam) > 0 { 120 for _, kv := range tagParam { 121 switch TagNameType(kv[0]) { 122 case ProcInputParamTag: 123 //результат бинарной операции 0|IN => IN; 1|IN => IN; 2|IN => INOUT (3); 124 newfield.Type = newfield.Type | ds.IN 125 case ProcOutputParamTag: 126 //результат бинарной операции 0|OUT => OUT; 1|OUT => INOUT (3); 2|OUT => OUT; 127 newfield.Type = newfield.Type | ds.OUT 128 orderIdx := index 129 130 if len(kv) == 2 { 131 orderIdx, err = strconv.Atoi(kv[1]) 132 if err != nil { 133 return &arerror.ErrParseTypeFieldTagDecl{Name: newfield.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagValueInvalid} 134 } 135 } 136 137 newfield.OrderIndex = orderIdx 138 case SizeTag: 139 if kv[1] != "" { 140 size, err := strconv.ParseInt(kv[1], 10, 64) 141 if err != nil { 142 return &arerror.ErrParseTypeFieldTagDecl{Name: newfield.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagValueInvalid} 143 } 144 145 newfield.Size = size 146 } 147 case SerializerTag: 148 newfield.Serializer = strings.Split(kv[1], ",") 149 default: 150 return &arerror.ErrParseTypeFieldTagDecl{Name: newfield.Name, TagName: kv[0], TagValue: kv[1], Err: arerror.ErrParseTagUnknown} 151 } 152 } 153 } 154 155 return nil 156 } 157 158 // ParseProcFields парсинг полей процедуры 159 func ParseProcFields(dst *ds.RecordPackage, fields []*ast.Field) error { 160 for _, field := range fields { 161 if field.Names == nil || len(field.Names) != 1 { 162 return &arerror.ErrParseTypeFieldDecl{Err: arerror.ErrNameDeclaration} 163 } 164 165 newField := ds.ProcFieldDeclaration{ 166 Name: field.Names[0].Name, 167 Serializer: []string{}, 168 } 169 170 if err := ParseProcFieldsTag(len(dst.ProcOutFields), field, &newField); err != nil { 171 return fmt.Errorf("error ParseFieldsTag: %w", err) 172 } 173 174 switch t := field.Type.(type) { 175 case *ast.Ident: 176 newField.Format = octopus.Format(t.String()) 177 case *ast.ArrayType: 178 if t.Elt.(*ast.Ident).Name != "byte" && t.Elt.(*ast.Ident).Name != "string" { 179 return &arerror.ErrParseTypeFieldDecl{Name: newField.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseProcFieldArraySlice} 180 } 181 182 // если входной параметр slice 183 if newField.Type == ds.IN && t.Len == nil { 184 newField.Format = octopus.Format(fmt.Sprintf("[]%s", t.Elt.(*ast.Ident).Name)) 185 break 186 } 187 188 if t.Len == nil { 189 return &arerror.ErrParseTypeFieldDecl{Name: newField.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseFieldArrayNotSlice} 190 } 191 192 return &arerror.ErrParseTypeFieldDecl{Name: newField.Name, FieldType: t.Elt.(*ast.Ident).Name, Err: arerror.ErrParseFieldBinary} 193 default: 194 return &arerror.ErrParseTypeFieldDecl{Name: newField.Name, FieldType: fmt.Sprintf("%T", t), Err: arerror.ErrUnknown} 195 } 196 197 if err := dst.AddProcField(newField); err != nil { 198 return err 199 } 200 } 201 202 return nil 203 }