Skip to content

Commit

Permalink
修复本目录下的Mixin不会使用的问题
Browse files Browse the repository at this point in the history
  • Loading branch information
azhai committed May 19, 2022
1 parent 6b0f9b6 commit 2e55d99
Show file tree
Hide file tree
Showing 5 changed files with 184 additions and 153 deletions.
1 change: 0 additions & 1 deletion cmd/xg/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ func main() {
}
}

settings.Reverse.PrepareMixins()
rver := reverse.NewGoReverser(settings.Reverse)
// 生成顶部目录下init单个文件
if err = rver.GenModelInitFile("init"); err != nil {
Expand Down
37 changes: 15 additions & 22 deletions execute.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,21 +77,6 @@ func (c ReverseConfig) GetTemplateName(name string) string {
}
}

func (c ReverseConfig) PrepareMixins() (mixinNames []string) {
if c.MixinDir == "" {
return
}
files, _ := rewrite.FindFiles(c.MixinDir, ".go")
for filename := range files {
if strings.HasSuffix(filename, "_test.go") {
continue
}
newNames := rewrite.AddFormerMixins(filename, c.MixinNS, "")
mixinNames = append(mixinNames, newNames...)
}
return
}

// Reverser model反转器
type Reverser struct {
currOutDir string
Expand All @@ -101,6 +86,7 @@ type Reverser struct {

// NewGoReverser 创建Golang反转器
func NewGoReverser(target ReverseConfig) *Reverser {
rewrite.PrepareMixins(target.MixinDir, target.MixinNS)
return &Reverser{lang: golang, target: target}
}

Expand Down Expand Up @@ -288,18 +274,25 @@ func FilterTables(tables []*schemas.Table, includes, excludes []string, tailDigi
}

// ApplyDirMixins 将已知的Mixin嵌入到匹配的Model中
func ApplyDirMixins(currDir string, verbose bool) error {
cps := rewrite.NewComposer()
func ApplyDirMixins(currDir string, verbose bool) (err error) {
files, _ := rewrite.FindFiles(currDir, ".go")
if verbose && len(files) > 0 {
fmt.Println("")
}
var err error
notTestFiles := make([]string, 0)
cps := rewrite.NewComposer()
for filename := range files {
_err := rewrite.ParseAndMixinFile(cps, filename, verbose)
if _err != nil {
err = _err
if strings.HasSuffix(filename, "_test.go") {
continue
}
rewrite.AddFormerMixins(cps, filename, "", "")
notTestFiles = append(notTestFiles, filename)
}
return err
for _, filename := range notTestFiles {
err = cps.ParseAndMixinFile(filename, verbose)
if err != nil {
return
}
}
return
}
214 changes: 111 additions & 103 deletions rewrite/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,14 @@ import (
"github.com/azhai/xgen/utils/enums"
)

const MODEL_EXTENDS = "`json:\",inline\" xorm:\"extends\"`"
const (
AdaptivePkgName = "#"
ModelExtends = "`json:\",inline\" xorm:\"extends\"`"
)

var globaltComposer = GlobaltComposer()
var (
globaltComposer = GlobaltComposer() // 公共Mixins
)

type Composer struct {
subNames []string
Expand Down Expand Up @@ -77,7 +82,7 @@ func (c *Composer) RemoveSubstitute(name string) {
}
}

// RemoveSubstitute 删除可替换Model
// SubstituteSummary 替换和改写Model
func (c *Composer) SubstituteSummary(summary *ModelSummary, verbose bool) []*ModelSummary {
var subs []*ModelSummary
if c.Global != nil && len(c.Global.subNames) > 0 {
Expand All @@ -88,39 +93,70 @@ func (c *Composer) SubstituteSummary(summary *ModelSummary, verbose bool) []*Mod
continue // 不要替换自己
}
if sub, ok := c.subModels[subName]; ok {
if ScanAndUseMixins(summary, sub, verbose) {
if summary.ScanAndUseMixins(sub, verbose) {
subs = append(subs, sub)
}
}
}
return subs
}

// AddFormerMixins
func AddFormerMixins(fileName, nameSpace, alias string) []string {
// ParseAndMixinFile 使用Mixin改写文件
func (c *Composer) ParseAndMixinFile(fileName string, verbose bool) error {
cp, err := NewFileParser(fileName)
if err != nil {
return nil
if verbose {
fmt.Println(fileName, " error: ", err)
}
return err
}
var mixinNames []string
var changed bool
imports := make(map[string]string)
for _, node := range cp.AllDeclNode("type") {
if len(node.Fields) == 0 {
continue
}
name := node.GetName()
if !strings.HasSuffix(name, "Core") && !strings.HasSuffix(name, "Mixin") {
continue // 以Core或Mixin结尾的类才会嵌入Model中
summary := &ModelSummary{Name: node.GetName()}
_ = summary.ParseFields(cp, node)
if summary.Isomorph() {
summary.IsExists = true
} else {
for _, sub := range c.SubstituteSummary(summary, verbose) {
imports[sub.Import] = sub.Alias
}
}
summary := &ModelSummary{Import: nameSpace, Alias: alias}
if alias == "" {
alias = cp.GetPackage()
c.RegisterSubstitute(summary)
if summary.IsChanged {
changed = true
ReplaceModelFields(cp, node, summary)
}
summary.Name = fmt.Sprintf("%s.%s", alias, name)
_ = summary.ParseFields(cp, node)
globaltComposer.RegisterSubstitute(summary)
mixinNames = append(mixinNames, summary.Name)
}
return mixinNames
if changed { // 加入相关的 mixin imports 并美化代码
err = cp.ResetImports(fileName, imports)
}
if verbose {
if changed {
fmt.Println("+", fileName)
} else {
fmt.Println("-", fileName)
}
}
return err
}

// GetLineFeature 提取 struct field 的名称与类型作为特征
func GetLineFeature(code string) string {
ps := strings.Fields(code)
if len(ps) == 1 {
return ps[0]
}
if strings.HasSuffix(ps[1], "json:\",inline\"") {
return ps[0] + ":inline"
}
if strings.HasSuffix(ps[1], "xorm:\"extends\"") {
return ps[0] + ":inline"
}
return ps[0] + ":" + ps[1]
}

// ModelSummary Model摘要
Expand Down Expand Up @@ -161,7 +197,7 @@ func (s ModelSummary) GetSortedFeatures() []string {
return s.sortedFeatures
}

// Isomorph 已经是
// Isomorph 已经是其他Model的同构体,没有嵌入的空间
func (s *ModelSummary) Isomorph() bool {
features := s.GetSortedFeatures()
return len(features) == 1 && strings.HasSuffix(features[0], ":inline")
Expand All @@ -170,7 +206,7 @@ func (s *ModelSummary) Isomorph() bool {
// GetSubstitute
func (s *ModelSummary) GetSubstitute() string {
if s.Substitute == "" {
s.Substitute = fmt.Sprintf("*%s %s", s.Name, MODEL_EXTENDS)
s.Substitute = fmt.Sprintf("*%s %s", s.Name, ModelExtends)
}
return s.Substitute
}
Expand All @@ -194,134 +230,106 @@ func (s *ModelSummary) ParseFields(cp *CodeParser, node *DeclNode) int {
return size
}

// GetLineFeature 提取 struct field 的名称与类型作为特征
func GetLineFeature(code string) string {
ps := strings.Fields(code)
if len(ps) == 1 {
return ps[0]
}
if strings.HasSuffix(ps[1], "json:\",inline\"") {
return ps[0] + ":inline"
}
if strings.HasSuffix(ps[1], "xorm:\"extends\"") {
return ps[0] + ":inline"
}
return ps[0] + ":" + ps[1]
}

// ReplaceModelFields
func ReplaceModelFields(cp *CodeParser, node *DeclNode, summary *ModelSummary) {
var last ast.Node
max := len(node.Fields) - 1
first, lastField := ast.Node(node.Fields[0]), node.Fields[max]
if lastField.Comment != nil {
last = ast.Node(lastField.Comment)
} else {
last = ast.Node(lastField)
}
cp.AddReplace(first, last, summary.GetInnerCode())
}

// ReplaceSummary
func ReplaceSummary(summary, sub *ModelSummary) *ModelSummary {
func (s *ModelSummary) ReplaceSummary(sub *ModelSummary) bool {
var features, lines []string
find, sted := false, sub.GetSortedFeatures()
for i, ft := range summary.Features {
for i, ft := range s.Features {
if !enums.InStringList(ft, sted) {
features = append(features, ft)
lines = append(lines, summary.FieldLines[i])
lines = append(lines, s.FieldLines[i])
} else if !find {
subst := sub.GetSubstitute()
features = append(features, subst)
lines = append(lines, subst)
find = true
summary.IsChanged = true
s.IsChanged = true
}
}
summary.Features, summary.FieldLines = features, lines
return summary
s.Features, s.FieldLines = features, lines
return s.IsChanged
}

// ScanAndUseMixins
func ScanAndUseMixins(summary, sub *ModelSummary, verbose bool) (needImport bool) {
func (s *ModelSummary) ScanAndUseMixins(sub *ModelSummary, verbose bool) (needImport bool) {
sted := sub.GetSortedFeatures()
sorted := summary.GetSortedFeatures()
sorted := s.GetSortedFeatures()
// 函数 IsSubsetList(..., ..., true) 用于排除异名同构的Model
if enums.IsSubsetList(sted, sorted, false) { // 正向替换
summary = ReplaceSummary(summary, sub)
s.ReplaceSummary(sub)
if len(sorted) == len(sted) { //完全相等
summary.IsExists = true
s.IsExists = true
}
if sub.Import != "" {
needImport = true
}
if verbose {
fmt.Println("*", summary.Name, " <- ", sub.Name)
fmt.Println("*", s.Name, " <- ", sub.Name)
}
} else if strings.HasPrefix(sub.Name, "xquery.") {
return // 早于反向替换,避免陷入死胡同
} else if enums.IsSubsetList(sorted, sted, true) { // 反向替换
ReplaceSummary(sub, summary)
sub.ReplaceSummary(s)
if verbose {
fmt.Println("*", summary.Name, " -> ", sub.Name)
fmt.Println("*", s.Name, " -> ", sub.Name)
}
}
return
}

// ParseAndMixinFile
func ParseAndMixinFile(cps *Composer, fileName string, verbose bool) error {
// ReplaceModelFields
func ReplaceModelFields(cp *CodeParser, node *DeclNode, summary *ModelSummary) {
var last ast.Node
max := len(node.Fields) - 1
first, lastField := ast.Node(node.Fields[0]), node.Fields[max]
if lastField.Comment != nil {
last = ast.Node(lastField.Comment)
} else {
last = ast.Node(lastField)
}
cp.AddReplace(first, last, summary.GetInnerCode())
}

// AddFormerMixins
func AddFormerMixins(cps *Composer, fileName, nameSpace, alias string) []string {
cp, err := NewFileParser(fileName)
if err != nil {
if verbose {
fmt.Println(fileName, " error: ", err)
}
return err
return nil
}
var changed bool
imports := make(map[string]string)
for _, node := range cp.AllDeclNode("type") {
var mixinNames []string
// 以Core或Mixin结尾的类才会嵌入Model中
for _, node := range cp.FindDeclNode("type", "*Core", "*Mixin") {
if len(node.Fields) == 0 {
continue
}
summary := &ModelSummary{Import: nameSpace, Alias: alias}
if alias == AdaptivePkgName {
alias = cp.GetPackage()
}
name := node.GetName()
//if strings.Contains(cp.GetNodeCode(node), MODEL_EXTENDS) {
// continue // 避免重复处理 model
//}

summary := &ModelSummary{Name: name}
_ = summary.ParseFields(cp, node)
if summary.Isomorph() {
summary.IsExists = true
if alias == "" {
summary.Name = name
} else {
for _, sub := range cps.SubstituteSummary(summary, verbose) {
imports[sub.Import] = sub.Alias
}
summary.Name = fmt.Sprintf("%s.%s", alias, name)
}
summary.ParseFields(cp, node)
cps.RegisterSubstitute(summary)
if summary.IsChanged {
changed = true
ReplaceModelFields(cp, node, summary)
}
mixinNames = append(mixinNames, summary.Name)
}
if verbose {
if changed {
fmt.Println("+", fileName)
} else {
fmt.Println("-", fileName)
}
return mixinNames
}

func PrepareMixins(mixinDir, mixinNS string) (mixinNames []string) {
if _, isExists := utils.FileSize(mixinDir); !isExists {
return
}
if changed { // 加入相关的 mixin imports 并美化代码
cs := cp.CodeSource
if code, chg := cs.AltSource(); chg {
cs.SetSource(code)
}
if cs, err = ResetImports(cs, imports); err != nil {
return err
}
if err = cs.WriteTo(fileName); err != nil {
return err
files, _ := FindFiles(mixinDir, ".go")
for filename := range files {
if strings.HasSuffix(filename, "_test.go") {
continue
}
newNames := AddFormerMixins(globaltComposer, filename, mixinNS, AdaptivePkgName)
mixinNames = append(mixinNames, newNames...)
}
return nil
return
}
Loading

0 comments on commit 2e55d99

Please sign in to comment.