Files
gormlint/relationsCheck/checkManyToOne.go
2025-03-18 03:45:42 +07:00

71 lines
1.9 KiB
Go

package relationsCheck
import (
"github.com/kuzgoga/gormlint/common"
"go/token"
"go/types"
"golang.org/x/tools/go/analysis"
"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,
"Expected foreignKey `%s` in model `%s` for 1:M relation with model `%s`",
foreignKey,
relatedModel.Name,
model.Name,
)
alreadyReported[nestedField.Pos] = true
return true
}
if !model.HasField(references) {
pass.Reportf(
nestedField.Pos,
"Expected references `%s` in model `%s` for 1:M relation with model `%s`",
references,
model.Name,
relatedModel.Name,
)
alreadyReported[nestedField.Pos] = true
return true
}
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
}