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  }