add filter rule

This commit is contained in:
Masaaki Goshima 2021-11-20 17:00:52 +09:00
parent bcaf36681a
commit d11fc7fe6c
No known key found for this signature in database
GPG Key ID: 6A53785055537153
2 changed files with 89 additions and 25 deletions

View File

@ -168,6 +168,27 @@ func (c *StructCode) ToOpcode() []*Opcode {
return []*Opcode{} return []*Opcode{}
} }
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
fields := make([]*StructFieldCode, 0, len(c.fields))
for _, field := range c.fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil {
structCode.removeFieldsByTags(tags)
if len(structCode.fields) > 0 {
fields = append(fields, field)
}
continue
}
}
if tags.ExistsKey(field.key) {
continue
}
fields = append(fields, field)
}
c.fields = fields
}
type StructFieldCode struct { type StructFieldCode struct {
typ *runtime.Type typ *runtime.Type
key string key string
@ -181,7 +202,14 @@ type StructFieldCode struct {
isNextOpPtrType bool isNextOpPtrType bool
} }
func (c *StructFieldCode) toInlineCode() []*StructFieldCode { func (c *StructFieldCode) getAnonymousStruct() *StructCode {
if !c.isAnonymous {
return nil
}
code, ok := c.value.(*StructCode)
if ok {
return code
}
return nil return nil
} }
@ -486,50 +514,87 @@ func compileStruct2(ctx *compileContext, isPtr bool) (*StructCode, error) {
return nil, err return nil, err
} }
if field.isAnonymous { if field.isAnonymous {
structCode, ok := field.value.(*StructCode) structCode := field.getAnonymousStruct()
if ok { if structCode != nil {
for _, field := range structCode.fields { structCode.removeFieldsByTags(tags)
if tags.ExistsKey(field.key) {
continue
}
fields = append(fields, field)
}
} else {
fields = append(fields, field)
} }
} else {
fields = append(fields, field)
} }
fields = append(fields, field)
} }
fieldMap := getFieldMap(fields)
duplicatedFieldMap := getDuplicatedFieldMap(fieldMap)
code.fields = filteredDuplicatedFields(fields, duplicatedFieldMap)
return code, nil
}
func getFieldMap(fields []*StructFieldCode) map[string][]*StructFieldCode {
fieldMap := map[string][]*StructFieldCode{} fieldMap := map[string][]*StructFieldCode{}
for _, field := range fields { for _, field := range fields {
if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil {
for k, v := range getFieldMap(structCode.fields) {
fieldMap[k] = append(fieldMap[k], v...)
}
continue
}
}
fieldMap[field.key] = append(fieldMap[field.key], field) fieldMap[field.key] = append(fieldMap[field.key], field)
} }
removeFieldKey := map[string]struct{}{} return fieldMap
}
func getDuplicatedFieldMap(fieldMap map[string][]*StructFieldCode) map[*StructFieldCode]struct{} {
duplicatedFieldMap := map[*StructFieldCode]struct{}{}
for _, fields := range fieldMap { for _, fields := range fieldMap {
if len(fields) == 1 { if len(fields) == 1 {
continue continue
} }
var foundTaggedKey bool if isTaggedKeyOnly(fields) {
for _, field := range fields { for _, field := range fields {
if field.isTaggedKey { if field.isTaggedKey {
if foundTaggedKey { continue
removeFieldKey[field.key] = struct{}{}
break
} }
foundTaggedKey = true duplicatedFieldMap[field] = struct{}{}
}
} else {
for _, field := range fields {
duplicatedFieldMap[field] = struct{}{}
} }
} }
} }
return duplicatedFieldMap
}
func filteredDuplicatedFields(fields []*StructFieldCode, duplicatedFieldMap map[*StructFieldCode]struct{}) []*StructFieldCode {
filteredFields := make([]*StructFieldCode, 0, len(fields)) filteredFields := make([]*StructFieldCode, 0, len(fields))
for _, field := range fields { for _, field := range fields {
if _, exists := removeFieldKey[field.key]; exists { if field.isAnonymous {
structCode := field.getAnonymousStruct()
if structCode != nil {
structCode.fields = filteredDuplicatedFields(structCode.fields, duplicatedFieldMap)
if len(structCode.fields) > 0 {
filteredFields = append(filteredFields, field)
}
continue
}
}
if _, exists := duplicatedFieldMap[field]; exists {
continue continue
} }
filteredFields = append(filteredFields, field) filteredFields = append(filteredFields, field)
} }
code.fields = filteredFields return filteredFields
return code, nil }
func isTaggedKeyOnly(fields []*StructFieldCode) bool {
var taggedKeyFieldCount int
for _, field := range fields {
if field.isTaggedKey {
taggedKeyFieldCount++
}
}
return taggedKeyFieldCount == 1
} }
func typeToStructTags(typ *runtime.Type) runtime.StructTags { func typeToStructTags(typ *runtime.Type) runtime.StructTags {

View File

@ -1316,7 +1316,6 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
fieldPtrIndex := ctx.ptrIndex fieldPtrIndex := ctx.ptrIndex
ctx.incIndex() ctx.incIndex()
fmt.Println("fieldOpcodeIndex = ", fieldOpcodeIndex)
nilcheck := true nilcheck := true
addrForMarshaler := false addrForMarshaler := false
isIndirectSpecialCase := isPtr && i == 0 && fieldNum == 1 isIndirectSpecialCase := isPtr && i == 0 && fieldNum == 1