feat: one-to-many, belongs-to

This commit is contained in:
2025-03-17 23:47:01 +07:00
parent db9ef0f935
commit 9d14fa7c57
8 changed files with 156 additions and 45 deletions

View File

@@ -1,15 +1,25 @@
package relationsCheck
import (
"go/token"
"go/types"
"golang.org/x/tools/go/analysis"
"gormlint/common"
"strings"
)
var alreadyReported = make(map[token.Pos]bool)
func checkManyToOne(pass *analysis.Pass, nestedField common.Field, model common.Model, relatedModel common.Model) bool {
/* Return true, if found problems */
foreignKey := nestedField.Tags.GetParamOr("foreignKey", model.Name+"Id")
references := nestedField.Tags.GetParamOr("references", "Id")
if alreadyReported[nestedField.Pos] {
return true
}
if !relatedModel.HasField(foreignKey) {
pass.Reportf(
nestedField.Pos,
@@ -18,8 +28,10 @@ func checkManyToOne(pass *analysis.Pass, nestedField common.Field, model common.
relatedModel.Name,
model.Name,
)
alreadyReported[nestedField.Pos] = true
return true
}
if !model.HasField(references) {
pass.Reportf(
nestedField.Pos,
@@ -28,20 +40,31 @@ func checkManyToOne(pass *analysis.Pass, nestedField common.Field, model common.
model.Name,
relatedModel.Name,
)
return true
}
foreignKeyType := types.ExprString(relatedModel.Fields[foreignKey].Type)
referencesType := types.ExprString(model.Fields[references].Type)
if !strings.Contains(foreignKeyType, "int") {
// TODO: process UUID as foreign key type
pass.Reportf(relatedModel.Fields[foreignKey].Pos, "Foreign key `%s` has invalid type", foreignKeyType)
alreadyReported[nestedField.Pos] = true
return true
}
if !strings.Contains(referencesType, "int") {
pass.Reportf(model.Fields[references].Pos, "References key `%s` has invalid type", referencesType)
foreignKeyField := relatedModel.Fields[foreignKey]
referencesField := model.Fields[references]
foreignKeyType := types.ExprString(foreignKeyField.Type)
referencesType := types.ExprString(referencesField.Type)
if alreadyReported[foreignKeyField.Pos] || alreadyReported[referencesField.Pos] {
return true
}
if !strings.Contains(foreignKeyType, "int") && !alreadyReported[foreignKeyField.Pos] {
// TODO: process UUID as foreign key type
pass.Reportf(foreignKeyField.Pos, "Foreign key `%s` has invalid type", foreignKeyType)
alreadyReported[foreignKeyField.Pos] = true
return true
}
if !strings.Contains(referencesType, "int") && !alreadyReported[referencesField.Pos] {
pass.Reportf(referencesField.Pos, "References key `%s` has invalid type", referencesType)
alreadyReported[referencesField.Pos] = true
return true
}
return false
}