feat: references check
... and fixes: parse fields without tags and other logical errors
This commit is contained in:
@@ -6,18 +6,18 @@ import (
|
||||
)
|
||||
|
||||
type Field struct {
|
||||
Name string
|
||||
Type ast.Expr
|
||||
Tags *string
|
||||
Options []string // contains options like "autoCreateTime" or "null"
|
||||
Params []string // contains params like "foreignKey:CustomerId" or "constrain:OnDelete:Cascade"
|
||||
Position token.Pos
|
||||
Comment string
|
||||
Name string
|
||||
Type ast.Expr
|
||||
Tags *string
|
||||
Options []string // contains options like "autoCreateTime" or "null"
|
||||
Params []string // contains params like "foreignKey:CustomerId" or "constrain:OnDelete:Cascade"
|
||||
Pos token.Pos
|
||||
Comment string
|
||||
}
|
||||
|
||||
type Model struct {
|
||||
Name string
|
||||
Fields map[string]Field
|
||||
Position token.Pos
|
||||
Comment string
|
||||
Name string
|
||||
Fields map[string]Field
|
||||
Pos token.Pos
|
||||
Comment string
|
||||
}
|
||||
|
||||
77
common/modelsParser.go
Normal file
77
common/modelsParser.go
Normal file
@@ -0,0 +1,77 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"github.com/fatih/structtag"
|
||||
"go/ast"
|
||||
"golang.org/x/tools/go/analysis"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func ParseModels(pass *analysis.Pass, models *map[string]Model) {
|
||||
for _, file := range pass.Files {
|
||||
ast.Inspect(file, func(node ast.Node) bool {
|
||||
typeSpec, ok := node.(*ast.TypeSpec)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
structure, ok := typeSpec.Type.(*ast.StructType)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
if err := CheckUnnamedModel(*typeSpec); err != nil {
|
||||
pass.Reportf(structure.Pos(), err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
var model Model
|
||||
model.Name = typeSpec.Name.Name
|
||||
model.Comment = typeSpec.Comment.Text()
|
||||
model.Pos = structure.Pos()
|
||||
model.Fields = make(map[string]Field)
|
||||
|
||||
for _, field := range structure.Fields.List {
|
||||
var structField Field
|
||||
if err := CheckUnnamedField(typeSpec.Name.Name, *field); err != nil {
|
||||
pass.Reportf(field.Pos(), err.Error())
|
||||
return false
|
||||
}
|
||||
|
||||
structField.Name = field.Names[0].Name
|
||||
structField.Pos = field.Pos()
|
||||
structField.Comment = field.Comment.Text()
|
||||
structField.Type = field.Type
|
||||
|
||||
if field.Tag != nil {
|
||||
structField.Tags = &field.Tag.Value
|
||||
|
||||
tags, err := structtag.Parse(NormalizeStructTags(field.Tag.Value))
|
||||
if err != nil {
|
||||
pass.Reportf(field.Pos(), "Invalid structure tag: %s\n", err)
|
||||
return false
|
||||
}
|
||||
if tags != nil {
|
||||
gormTag, parseErr := tags.Get("gorm")
|
||||
if gormTag != nil && parseErr == nil {
|
||||
gormTag.Options = append([]string{gormTag.Name}, gormTag.Options...)
|
||||
for _, opt := range gormTag.Options {
|
||||
if strings.Contains(opt, ":") {
|
||||
structField.Params = append(structField.Params, opt)
|
||||
} else {
|
||||
structField.Options = append(structField.Options, opt)
|
||||
}
|
||||
}
|
||||
}
|
||||
if parseErr != nil {
|
||||
pass.Reportf(field.Pos(), "Invalid structure tag: %s\n", parseErr)
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
model.Fields[structField.Name] = structField
|
||||
(*models)[model.Name] = model
|
||||
}
|
||||
return false
|
||||
})
|
||||
}
|
||||
}
|
||||
21
common/resolveBaseType.go
Normal file
21
common/resolveBaseType.go
Normal file
@@ -0,0 +1,21 @@
|
||||
package common
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
)
|
||||
|
||||
func ResolveBaseType(expr ast.Expr) *string {
|
||||
switch e := expr.(type) {
|
||||
case *ast.Ident:
|
||||
return &e.Name
|
||||
case *ast.StarExpr:
|
||||
return ResolveBaseType(e.X)
|
||||
case *ast.ArrayType:
|
||||
return ResolveBaseType(e.Elt)
|
||||
case *ast.SelectorExpr:
|
||||
return ResolveBaseType(e.X)
|
||||
case *ast.ParenExpr:
|
||||
return ResolveBaseType(e.X)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user