feat: null safety

This commit is contained in:
2024-12-29 16:35:38 +07:00
commit b32eafb43d
13 changed files with 249 additions and 0 deletions

68
common/nullSafetyCheck.go Normal file
View File

@@ -0,0 +1,68 @@
package common
import (
"errors"
"github.com/fatih/structtag"
"go/ast"
"golang.org/x/tools/go/analysis"
)
func isPointerType(typeExpr ast.Expr) bool {
isPointer := false
if _, ok := typeExpr.(*ast.StarExpr); ok {
isPointer = true
}
return isPointer
}
func isGormValueNullable(tags *structtag.Tags) (*bool, error) {
gormTag, err := tags.Get("gorm")
if gormTag == nil {
return nil, nil
}
gormTag.Options = append([]string{gormTag.Name}, gormTag.Options...)
if err != nil {
return nil, nil
}
nullTagExist := gormTag.HasOption("null")
notNullTagExist := gormTag.HasOption("not null")
if nullTagExist == notNullTagExist && nullTagExist == true {
return nil, errors.New(`tags "null" and "not null" are specified at one field`)
}
if nullTagExist {
return PointerOf(true), nil
} else if notNullTagExist {
return PointerOf(false), nil
} else {
return PointerOf(false), nil
}
}
func CheckFieldNullConsistency(pass analysis.Pass, field ast.Field, structName string, structTags string) {
tags, err := structtag.Parse(structTags)
if err != nil {
pass.Reportf(field.Pos(), "Invalid structure tag: %s", err)
}
if tags == nil {
return
}
isFieldNullable := isPointerType(field.Type)
isColumnNullable, err := isGormValueNullable(tags)
if err != nil {
pass.Reportf(field.Pos(), "Null safety error: %s", err)
}
if isColumnNullable == nil {
return
}
if isFieldNullable != *isColumnNullable {
pass.Reportf(field.Pos(), "Null safety error in \"%s\" model, field \"%s\": column nullable policy doesn't match to tag nullable policy", structName, field.Names[0].Name)
}
}