From d370e1674e6e806c332a32cd2000feb821a7cf87 Mon Sep 17 00:00:00 2001 From: caixw Date: Tue, 19 Nov 2024 12:07:59 +0800 Subject: [PATCH] =?UTF-8?q?feat(message/extract):=20=E6=B7=BB=E5=8A=A0?= =?UTF-8?q?=E6=8F=90=E5=8F=96=20struct=20tag=20=E5=86=85=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- go.mod | 8 +++--- go.sum | 16 +++++------ message/extract/extract.go | 31 +++++++++++++++++++++- message/extract/extract_test.go | 5 ++-- message/extract/options.go | 4 +++ message/extract/testdata/go.mod | 2 +- message/extract/testdata/go.sum | 4 +-- message/extract/testdata/locale/structs.go | 15 +++++++++++ 8 files changed, 67 insertions(+), 18 deletions(-) create mode 100644 message/extract/testdata/locale/structs.go diff --git a/go.mod b/go.mod index ef11343..b483365 100644 --- a/go.mod +++ b/go.mod @@ -5,11 +5,11 @@ go 1.23.0 require ( github.com/issue9/assert/v4 v4.3.1 github.com/issue9/sliceutil v0.17.0 - golang.org/x/text v0.19.0 - golang.org/x/tools v0.26.0 + golang.org/x/text v0.20.0 + golang.org/x/tools v0.27.0 ) require ( - golang.org/x/mod v0.21.0 // indirect - golang.org/x/sync v0.8.0 // indirect + golang.org/x/mod v0.22.0 // indirect + golang.org/x/sync v0.9.0 // indirect ) diff --git a/go.sum b/go.sum index b33f0a0..ac64aa6 100644 --- a/go.sum +++ b/go.sum @@ -2,11 +2,11 @@ github.com/issue9/assert/v4 v4.3.1 h1:dHYODk1yV7j/1baIB6K6UggI4r1Hfuljqic7PaDbwL github.com/issue9/assert/v4 v4.3.1/go.mod h1:v7qDRXi7AsaZZNh8eAK2rkLJg5/clztqQGA1DRv9Lv4= github.com/issue9/sliceutil v0.17.0 h1:EtmVlldkAyGxS0O2TnxcAu3pgLJw74I5eh9DHT7TOZs= github.com/issue9/sliceutil v0.17.0/go.mod h1:CVpH4f228pICY7JImlztUPe/zf2w0EicEleU9YfFe00= -golang.org/x/mod v0.21.0 h1:vvrHzRwRfVKSiLrG+d4FMl/Qi4ukBCE6kZlTUkDYRT0= -golang.org/x/mod v0.21.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= -golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= -golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= -golang.org/x/tools v0.26.0 h1:v/60pFQmzmT9ExmjDv2gGIfi3OqfKoEP6I5+umXlbnQ= -golang.org/x/tools v0.26.0/go.mod h1:TPVVj70c7JJ3WCazhD8OdXcZg/og+b9+tH/KxylGwH0= +golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4= +golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= +golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ= +golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= +golang.org/x/tools v0.27.0 h1:qEKojBykQkQ4EynWy4S8Weg69NumxKdn40Fce3uc/8o= +golang.org/x/tools v0.27.0/go.mod h1:sUi0ZgbwW9ZPAq26Ekut+weQPR5eIM6GQLQ1Yjm1H0Q= diff --git a/message/extract/extract.go b/message/extract/extract.go index e8fba36..5f1aae5 100644 --- a/message/extract/extract.go +++ b/message/extract/extract.go @@ -12,6 +12,7 @@ import ( "go/token" "go/types" "path/filepath" + "reflect" "slices" "strconv" "strings" @@ -33,6 +34,7 @@ type extractor struct { fset *token.FileSet funcs []fn root string + tag string mux sync.Mutex msg []message.Message @@ -108,10 +110,13 @@ func (ex *extractor) inspectDir(ctx context.Context, dir string) error { ast.Inspect(f, func(n ast.Node) bool { switch expr := n.(type) { - case *ast.TypeSpec, *ast.ImportSpec: + case *ast.ImportSpec: return false case *ast.CallExpr: return ex.inspect(expr, info) + case *ast.StructType: + ex.inspectStructTag(expr) + return true default: return true } @@ -123,6 +128,24 @@ func (ex *extractor) inspectDir(ctx context.Context, dir string) error { return nil } +func (ex *extractor) inspectStructTag(st *ast.StructType) { + if ex.tag == "" { + return + } + + for _, f := range st.Fields.List { + if f.Tag == nil { + continue + } + + val := f.Tag.Value + if tag := reflect.StructTag(val[1 : len(val)-1]).Get(ex.tag); tag != "" && tag != "-" { + p := ex.fset.Position(f.Pos()) + ex.append(tag, p) + } + } +} + // 遍历 expr 表达式 // // 返回值表示是否需要访问子元素 @@ -232,6 +255,12 @@ func (ex *extractor) appendMsg(expr *ast.CallExpr) { return } + ex.append(key, p) +} + +func (ex *extractor) append(key string, p token.Position) { + path := ex.trimPath(p.Filename) + ex.mux.Lock() defer ex.mux.Unlock() diff --git a/message/extract/extract_test.go b/message/extract/extract_test.go index ca795a3..17685a1 100644 --- a/message/extract/extract_test.go +++ b/message/extract/extract_test.go @@ -100,7 +100,7 @@ func TestExtract(t *testing.T) { t.Log("\n\n") }) - // 添加了 locale.Printer.Print + // 添加了 locale.Printer.Print,以及 struct tag t.Run("localeutilx3,localex2", func(t *testing.T) { o := &Options{ Root: "./testdata", @@ -114,13 +114,14 @@ func TestExtract(t *testing.T) { "github.com/issue9/localeutil/testdata/locale.String", // 别名,ref.String 指向此值 "github.com/issue9/localeutil/testdata/locale.Printer.Print", // ref.Printer 指向此值 }, + Tag: "comment", } l, err := Extract(context.Background(), o) a.NotError(err).NotNil(l). NotNil(l) m := l.Messages - a.Length(m, 19) + a.Length(m, 23) for _, mm := range m { t.Log(mm.Key) diff --git a/message/extract/options.go b/message/extract/options.go index 86d27e5..7f2c8e8 100644 --- a/message/extract/options.go +++ b/message/extract/options.go @@ -73,6 +73,9 @@ type Options struct { // // 如果为空将不输出任何内容,格式错误将会触发 panic。 Funcs []string + + // 指定用于提取 struct tag 中的特定内容作为翻译项 + Tag string } // [Options.Funcs] 转换后的表示 @@ -101,6 +104,7 @@ func (o *Options) buildExtractor() (*extractor, error) { infoLog: o.InfoLog, fset: token.NewFileSet(), funcs: split(o.Funcs...), + tag: o.Tag, root: abs, msg: make([]message.Message, 0, 100), diff --git a/message/extract/testdata/go.mod b/message/extract/testdata/go.mod index 7e6b025..78d395e 100644 --- a/message/extract/testdata/go.mod +++ b/message/extract/testdata/go.mod @@ -3,7 +3,7 @@ module github.com/issue9/localeutil/testdata require github.com/issue9/localeutil v1.0.0 // NOTE: 需要保证与根目录中 go.mod 的 text 具有相同的版本,否则测试会失败! -require golang.org/x/text v0.19.0 // indirect +require golang.org/x/text v0.20.0 // indirect replace github.com/issue9/localeutil => ../../.. diff --git a/message/extract/testdata/go.sum b/message/extract/testdata/go.sum index 407b3f4..c5463fe 100644 --- a/message/extract/testdata/go.sum +++ b/message/extract/testdata/go.sum @@ -1,4 +1,4 @@ github.com/issue9/assert/v4 v4.3.1 h1:dHYODk1yV7j/1baIB6K6UggI4r1Hfuljqic7PaDbwLg= github.com/issue9/assert/v4 v4.3.1/go.mod h1:v7qDRXi7AsaZZNh8eAK2rkLJg5/clztqQGA1DRv9Lv4= -golang.org/x/text v0.19.0 h1:kTxAhCbGbxhK0IwgSKiMO5awPoDQ0RpfiVYBfK860YM= -golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= +golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug= +golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4= diff --git a/message/extract/testdata/locale/structs.go b/message/extract/testdata/locale/structs.go new file mode 100644 index 0000000..f46ff49 --- /dev/null +++ b/message/extract/testdata/locale/structs.go @@ -0,0 +1,15 @@ +// SPDX-FileCopyrightText: 2024 caixw +// +// SPDX-License-Identifier: MIT + +package locale + +type X struct { + F1 string `comment:"x_1"` + F2 string `comment:"x_2"` +} + +type Y struct { + F1 string `comment:"y_1"` + F2 *X `comment:"y_2"` +}