🎨 清理多余残留文件
This commit is contained in:
@@ -15,7 +15,6 @@
|
||||
│ └── response
|
||||
├── packfile
|
||||
├── resource
|
||||
│ ├── excel
|
||||
│ ├── page
|
||||
│ └── template
|
||||
├── router
|
||||
@@ -42,7 +41,6 @@
|
||||
| `--response` | 出参结构体 | 返回给前端的数据结构体 |
|
||||
| `packfile` | 静态文件打包 | 静态文件打包 |
|
||||
| `resource` | 静态资源文件夹 | 负责存放静态文件 |
|
||||
| `--excel` | excel导入导出默认路径 | excel导入导出默认路径 |
|
||||
| `--page` | 页面静态资源目录 | 历史页面资源输出目录 |
|
||||
| `--template` | 模板 | 模板文件夹,存放的是代码生成器的模板 |
|
||||
| `router` | 路由层 | 路由层 |
|
||||
|
||||
@@ -243,10 +243,6 @@ hua-wei-obs:
|
||||
access-key: you-access-key
|
||||
secret-key: you-secret-key
|
||||
|
||||
# excel configuration
|
||||
excel:
|
||||
dir: ./resource/excel/
|
||||
|
||||
# disk usage configuration
|
||||
disk-list:
|
||||
- mount-point: "/"
|
||||
|
||||
@@ -26,8 +26,6 @@ type Server struct {
|
||||
CloudflareR2 CloudflareR2 `mapstructure:"cloudflare-r2" json:"cloudflare-r2" yaml:"cloudflare-r2"`
|
||||
Minio Minio `mapstructure:"minio" json:"minio" yaml:"minio"`
|
||||
|
||||
Excel Excel `mapstructure:"excel" json:"excel" yaml:"excel"`
|
||||
|
||||
DiskList []DiskList `mapstructure:"disk-list" json:"disk-list" yaml:"disk-list"`
|
||||
|
||||
// 跨域配置
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
package config
|
||||
|
||||
type Excel struct {
|
||||
Dir string `mapstructure:"dir" json:"dir" yaml:"dir"`
|
||||
}
|
||||
@@ -6,9 +6,6 @@ toolchain go1.24.2
|
||||
|
||||
require (
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible
|
||||
github.com/aws/aws-sdk-go v1.55.8
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.2
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.1
|
||||
github.com/casbin/casbin/v2 v2.103.0
|
||||
github.com/casbin/gorm-adapter/v3 v3.32.0
|
||||
github.com/dzwvip/gorm-oracle v0.1.2
|
||||
@@ -37,14 +34,12 @@ require (
|
||||
github.com/swaggo/swag v1.16.4
|
||||
github.com/tencentyun/cos-go-sdk-v5 v0.7.60
|
||||
github.com/unrolled/secure v1.17.0
|
||||
github.com/xuri/excelize/v2 v2.9.0
|
||||
go.mongodb.org/mongo-driver v1.17.2
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
go.uber.org/zap v1.27.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/sync v0.13.0
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/text v0.24.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
gorm.io/driver/mysql v1.5.7
|
||||
gorm.io/driver/postgres v1.5.11
|
||||
@@ -57,15 +52,6 @@ require (
|
||||
github.com/BurntSushi/toml v1.4.0 // indirect
|
||||
github.com/KyleBanks/depth v1.2.1 // indirect
|
||||
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.9 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.18 // indirect
|
||||
github.com/aws/smithy-go v1.24.1 // indirect
|
||||
github.com/bahlo/generic-list-go v0.2.0 // indirect
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.0 // indirect
|
||||
github.com/buger/jsonparser v1.1.1 // indirect
|
||||
@@ -107,7 +93,6 @@ require (
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // indirect
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/klauspost/compress v1.18.0 // indirect
|
||||
@@ -122,7 +107,6 @@ require (
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||
github.com/montanaflynn/stats v0.7.1 // indirect
|
||||
github.com/mozillazg/go-httpheader v0.4.0 // indirect
|
||||
github.com/ncruces/go-strftime v0.1.9 // indirect
|
||||
@@ -130,8 +114,6 @@ require (
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||
github.com/richardlehane/mscfb v1.0.4 // indirect
|
||||
github.com/richardlehane/msoleps v1.0.4 // indirect
|
||||
github.com/rs/xid v1.6.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.7.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
@@ -152,8 +134,6 @@ require (
|
||||
github.com/xdg-go/scram v1.1.2 // indirect
|
||||
github.com/xdg-go/stringprep v1.0.4 // indirect
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6 // indirect
|
||||
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71 // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
@@ -162,6 +142,7 @@ require (
|
||||
golang.org/x/exp v0.0.0-20250106191152-7588d65b2ba8 // indirect
|
||||
golang.org/x/image v0.23.0 // indirect
|
||||
golang.org/x/net v0.35.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/time v0.9.0 // indirect
|
||||
golang.org/x/tools v0.29.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
|
||||
@@ -31,18 +31,6 @@ github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82 h1:7dONQ3WNZ1zy960
|
||||
github.com/alex-ant/gomath v0.0.0-20160516115720-89013a210a82/go.mod h1:nLnM0KdK1CmygvjpDUO6m1TjSsiQtL61juhNsvV/JVI=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible h1:8psS8a+wKfiLt1iVDX79F7Y6wUM49Lcha2FMXt4UM8g=
|
||||
github.com/aliyun/aliyun-oss-go-sdk v3.0.2+incompatible/go.mod h1:T/Aws4fEfogEE9v+HPhhw+CntffsBHJ8nXQCwKr0/g8=
|
||||
github.com/aws/aws-sdk-go v1.55.8/go.mod h1:ZkViS9AqA6otK+JBBNH2++sx1sgxrPKcSzPPvQkUtXk=
|
||||
github.com/aws/aws-sdk-go-v2 v1.41.2/go.mod h1:IvvlAZQXvTXznUPfRVfryiG1fbzE2NGK6m9u39YQ+S4=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.7.5/go.mod h1:nVUlMLVV8ycXSb7mSkcNu9e3v/1TJq2RTlrPwhYWr5c=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.4.18/go.mod h1:w1jdlZXrGKaJcNoL+Nnrj+k5wlpGXqnNrKoP22HvAug=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.7.18/go.mod h1:r/eLGuGCBw6l36ZRWiw6PaZwPXb6YOj+i/7MizNl5/k=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.4.18/go.mod h1:CCXwUKAJdoWr6/NcxZ+zsiPr6oH/Q5aTooRGYieAyj4=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.13.5/go.mod h1:AZLZf2fMaahW5s/wMRciu1sYbdsikT/UHwbUjOdEVTc=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.9.9/go.mod h1:Kzm5e6OmNH8VMkgK9t+ry5jEih4Y8whqs+1hrkxim1I=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.13.18/go.mod h1:XhwkgGG6bHSd00nO/mexWTcTjgd6PjuvWQMqSn2UaEk=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.19.18/go.mod h1:hWe9b4f+djUQGmyiGEeOnZv69dtMSgpDRIvNMvuvzvY=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.96.1/go.mod h1:071TH4M3botFLWDbzQLfBR7tXYi7Fs2RsXSiH7nlUlY=
|
||||
github.com/aws/smithy-go v1.24.1/go.mod h1:LEj2LM3rBRQJxPZTB4KuzZkaZYnZPnvgIhb4pu07mx0=
|
||||
github.com/bahlo/generic-list-go v0.2.0 h1:5sz/EEAK+ls5wF+NeqDpk5+iNdMDXrh3z3nPnH1Wvgk=
|
||||
github.com/bahlo/generic-list-go v0.2.0/go.mod h1:2KvAjgMlE5NNynlg/5iLrrCCZ2+5xWbdbCW3pNTGyYg=
|
||||
github.com/bmatcuk/doublestar/v4 v4.6.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
@@ -206,8 +194,6 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr
|
||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
|
||||
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
|
||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
|
||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||
@@ -263,8 +249,6 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
|
||||
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
|
||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||
github.com/modocache/gover v0.0.0-20171022184752-b58185e213c5/go.mod h1:caMODM3PzxT8aQXRPkAt8xlV/e7d7w8GM5g0fa5F0D8=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||
github.com/mojocn/base64Captcha v1.3.8 h1:rrN9BhCwXKS8ht1e21kvR3iTaMgf4qPC9sRoV52bqEg=
|
||||
github.com/mojocn/base64Captcha v1.3.8/go.mod h1:QFZy927L8HVP3+VV5z2b1EAEiv1KxVJKZbAucVgLUy4=
|
||||
github.com/montanaflynn/stats v0.7.0/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
|
||||
@@ -300,11 +284,6 @@ github.com/redis/go-redis/v9 v9.7.0 h1:HhLSs+B6O021gwzl+locl0zEDnyNkxMtf/Z3NNBMa
|
||||
github.com/redis/go-redis/v9 v9.7.0/go.mod h1:f6zhXITC7JUJIlPEiBOTXxJgPLdZcA93GewI7inzyWw=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||
github.com/richardlehane/mscfb v1.0.4 h1:WULscsljNPConisD5hR0+OyZjwK46Pfyr6mPu5ZawpM=
|
||||
github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7gK3DypaEsUk=
|
||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/richardlehane/msoleps v1.0.4 h1:WuESlvhX3gH2IHcd8UqyCuFY5yiq/GR/yqaSM/9/g00=
|
||||
github.com/richardlehane/msoleps v1.0.4/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
|
||||
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
@@ -386,12 +365,6 @@ github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6
|
||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no=
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM=
|
||||
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6 h1:8m6DWBG+dlFNbx5ynvrE7NgI+Y7OlZVMVTpayoW+rCc=
|
||||
github.com/xuri/efp v0.0.0-20241211021726-c4e992084aa6/go.mod h1:ybY/Jr0T0GTCnYjKqmdwxyxn2BQf2RcQIIvex5QldPI=
|
||||
github.com/xuri/excelize/v2 v2.9.0 h1:1tgOaEq92IOEumR1/JfYS/eR0KHOCsRv/rYXXh6YJQE=
|
||||
github.com/xuri/excelize/v2 v2.9.0/go.mod h1:uqey4QBZ9gdMeWApPLdhm9x+9o2lq4iVmjiLfBS5hdE=
|
||||
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71 h1:hOh7aVDrvGJRxzXrQbDY8E+02oaI//5cHL+97oYpEPw=
|
||||
github.com/xuri/nfp v0.0.0-20250111060730-82a408b9aa71/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 h1:Ed3Oyj9yrmi9087+NczuL5BwkIc4wvTb5zIM+UJPGz4=
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2/go.mod h1:ILOh0sOhIJR3+L/8afwt/kE++YT040gmv5BQTMR2HP4=
|
||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
|
||||
|
||||
@@ -38,7 +38,7 @@ func (a *ApiCreator) New() mcp.Tool {
|
||||
mcp.WithDescription(`创建后端API记录,用于AI编辑器自动添加API接口时自动创建对应的API权限记录。
|
||||
|
||||
**重要限制:**
|
||||
- 当使用gva_auto_generate工具且needCreatedModules=true时,模块创建会自动生成API权限,不应调用此工具
|
||||
- 当使用模块自动生成功能且 needCreatedModules=true 时,模块创建会自动生成 API 权限,不应调用此工具
|
||||
- 仅在以下情况使用:1) 单独创建API(不涉及模块创建);2) AI编辑器自动添加API;3) router下的文件产生路径变化时`),
|
||||
mcp.WithString("path",
|
||||
mcp.Required(),
|
||||
|
||||
@@ -57,7 +57,7 @@ func (m *MenuCreator) New() mcp.Tool {
|
||||
mcp.WithDescription(`创建前端菜单记录,用于AI编辑器自动添加前端页面时自动创建对应的菜单项。
|
||||
|
||||
**重要限制:**
|
||||
- 当使用gva_auto_generate工具且needCreatedModules=true时,模块创建会自动生成菜单项,不应调用此工具
|
||||
- 当使用模块自动生成功能且 needCreatedModules=true 时,模块创建会自动生成菜单项,不应调用此工具
|
||||
- 仅在以下情况使用:1) 单独创建菜单(不涉及模块创建);2) AI编辑器自动添加前端页面时`),
|
||||
mcp.WithNumber("parentId",
|
||||
mcp.Description("父菜单ID,0表示根菜单"),
|
||||
|
||||
@@ -103,7 +103,6 @@ func OperationRecord() gin.HandlerFunc {
|
||||
strings.Contains(c.Writer.Header().Get("Cache-Control"), "must-revalidate, post-check=0, pre-check=0") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/force-download") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/octet-stream") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/vnd.ms-excel") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Type"), "application/download") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Disposition"), "attachment") ||
|
||||
strings.Contains(c.Writer.Header().Get("Content-Transfer-Encoding"), "binary") {
|
||||
|
||||
@@ -1,409 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"git.echol.cn/loser/Go-Web-Template/server/model/system"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"log"
|
||||
)
|
||||
|
||||
// AddImport 增加 import 方法
|
||||
func AddImport(astNode ast.Node, imp string) {
|
||||
impStr := fmt.Sprintf("\"%s\"", imp)
|
||||
ast.Inspect(astNode, func(node ast.Node) bool {
|
||||
if genDecl, ok := node.(*ast.GenDecl); ok {
|
||||
if genDecl.Tok == token.IMPORT {
|
||||
for i := range genDecl.Specs {
|
||||
if impNode, ok := genDecl.Specs[i].(*ast.ImportSpec); ok {
|
||||
if impNode.Path.Value == impStr {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
genDecl.Specs = append(genDecl.Specs, &ast.ImportSpec{
|
||||
Path: &ast.BasicLit{
|
||||
Kind: token.STRING,
|
||||
Value: impStr,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
// FindFunction 查询特定function方法
|
||||
func FindFunction(astNode ast.Node, FunctionName string) *ast.FuncDecl {
|
||||
var funcDeclP *ast.FuncDecl
|
||||
ast.Inspect(astNode, func(node ast.Node) bool {
|
||||
if funcDecl, ok := node.(*ast.FuncDecl); ok {
|
||||
if funcDecl.Name.String() == FunctionName {
|
||||
funcDeclP = funcDecl
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return funcDeclP
|
||||
}
|
||||
|
||||
// FindArray 查询特定数组方法
|
||||
func FindArray(astNode ast.Node, identName, selectorExprName string) *ast.CompositeLit {
|
||||
var assignStmt *ast.CompositeLit
|
||||
ast.Inspect(astNode, func(n ast.Node) bool {
|
||||
switch node := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range node.Rhs {
|
||||
if exprType, ok := expr.(*ast.CompositeLit); ok {
|
||||
if arrayType, ok := exprType.Type.(*ast.ArrayType); ok {
|
||||
sel, ok1 := arrayType.Elt.(*ast.SelectorExpr)
|
||||
x, ok2 := sel.X.(*ast.Ident)
|
||||
if ok1 && ok2 && x.Name == identName && sel.Sel.Name == selectorExprName {
|
||||
assignStmt = exprType
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return assignStmt
|
||||
}
|
||||
|
||||
func CreateMenuStructAst(menus []system.SysBaseMenu) *[]ast.Expr {
|
||||
var menuElts []ast.Expr
|
||||
for i := range menus {
|
||||
elts := []ast.Expr{ // 结构体的字段
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "ParentId"},
|
||||
Value: &ast.BasicLit{Kind: token.INT, Value: "0"},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Path"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Path)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Name"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Name)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Hidden"},
|
||||
Value: &ast.Ident{Name: "false"},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Component"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Component)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Sort"},
|
||||
Value: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%d", menus[i].Sort)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Meta"},
|
||||
Value: &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "Meta"},
|
||||
},
|
||||
Elts: []ast.Expr{
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Title"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Title)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Icon"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", menus[i].Icon)},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 添加菜单参数
|
||||
if len(menus[i].Parameters) > 0 {
|
||||
var paramElts []ast.Expr
|
||||
for _, param := range menus[i].Parameters {
|
||||
paramElts = append(paramElts, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysBaseMenuParameter"},
|
||||
},
|
||||
Elts: []ast.Expr{
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Type"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Type)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Key"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Key)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Value"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", param.Value)},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
elts = append(elts, &ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Parameters"},
|
||||
Value: &ast.CompositeLit{
|
||||
Type: &ast.ArrayType{
|
||||
Elt: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysBaseMenuParameter"},
|
||||
},
|
||||
},
|
||||
Elts: paramElts,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 添加菜单按钮
|
||||
if len(menus[i].MenuBtn) > 0 {
|
||||
var btnElts []ast.Expr
|
||||
for _, btn := range menus[i].MenuBtn {
|
||||
btnElts = append(btnElts, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysBaseMenuBtn"},
|
||||
},
|
||||
Elts: []ast.Expr{
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Name"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", btn.Name)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Desc"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", btn.Desc)},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
elts = append(elts, &ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "MenuBtn"},
|
||||
Value: &ast.CompositeLit{
|
||||
Type: &ast.ArrayType{
|
||||
Elt: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysBaseMenuBtn"},
|
||||
},
|
||||
},
|
||||
Elts: btnElts,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
menuElts = append(menuElts, &ast.CompositeLit{
|
||||
Type: nil,
|
||||
Elts: elts,
|
||||
})
|
||||
}
|
||||
return &menuElts
|
||||
}
|
||||
|
||||
func CreateApiStructAst(apis []system.SysApi) *[]ast.Expr {
|
||||
var apiElts []ast.Expr
|
||||
for i := range apis {
|
||||
elts := []ast.Expr{ // 结构体的字段
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Path"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Path)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Description"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Description)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "ApiGroup"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].ApiGroup)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Method"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", apis[i].Method)},
|
||||
},
|
||||
}
|
||||
apiElts = append(apiElts, &ast.CompositeLit{
|
||||
Type: nil,
|
||||
Elts: elts,
|
||||
})
|
||||
}
|
||||
return &apiElts
|
||||
}
|
||||
|
||||
// CheckImport 检查是否存在Import
|
||||
func CheckImport(file *ast.File, importPath string) bool {
|
||||
for _, imp := range file.Imports {
|
||||
// Remove quotes around the import path
|
||||
path := imp.Path.Value[1 : len(imp.Path.Value)-1]
|
||||
|
||||
if path == importPath {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func clearPosition(astNode ast.Node) {
|
||||
ast.Inspect(astNode, func(n ast.Node) bool {
|
||||
switch node := n.(type) {
|
||||
case *ast.Ident:
|
||||
// 清除位置信息
|
||||
node.NamePos = token.NoPos
|
||||
case *ast.CallExpr:
|
||||
// 清除位置信息
|
||||
node.Lparen = token.NoPos
|
||||
node.Rparen = token.NoPos
|
||||
case *ast.BasicLit:
|
||||
// 清除位置信息
|
||||
node.ValuePos = token.NoPos
|
||||
case *ast.SelectorExpr:
|
||||
// 清除位置信息
|
||||
node.Sel.NamePos = token.NoPos
|
||||
case *ast.BinaryExpr:
|
||||
node.OpPos = token.NoPos
|
||||
case *ast.UnaryExpr:
|
||||
node.OpPos = token.NoPos
|
||||
case *ast.StarExpr:
|
||||
node.Star = token.NoPos
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
|
||||
func CreateStmt(statement string) *ast.ExprStmt {
|
||||
expr, err := parser.ParseExpr(statement)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
clearPosition(expr)
|
||||
return &ast.ExprStmt{X: expr}
|
||||
}
|
||||
|
||||
func IsBlockStmt(node ast.Node) bool {
|
||||
_, ok := node.(*ast.BlockStmt)
|
||||
return ok
|
||||
}
|
||||
|
||||
func VariableExistsInBlock(block *ast.BlockStmt, varName string) bool {
|
||||
exists := false
|
||||
ast.Inspect(block, func(n ast.Node) bool {
|
||||
switch node := n.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for _, expr := range node.Lhs {
|
||||
if ident, ok := expr.(*ast.Ident); ok && ident.Name == varName {
|
||||
exists = true
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return exists
|
||||
}
|
||||
|
||||
func CreateDictionaryStructAst(dictionaries []system.SysDictionary) *[]ast.Expr {
|
||||
var dictElts []ast.Expr
|
||||
for i := range dictionaries {
|
||||
statusStr := "true"
|
||||
if dictionaries[i].Status != nil && !*dictionaries[i].Status {
|
||||
statusStr = "false"
|
||||
}
|
||||
|
||||
elts := []ast.Expr{
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Name"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", dictionaries[i].Name)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Type"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", dictionaries[i].Type)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Status"},
|
||||
Value: &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "utils"},
|
||||
Sel: &ast.Ident{Name: "Pointer"},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.Ident{Name: statusStr},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Desc"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", dictionaries[i].Desc)},
|
||||
},
|
||||
}
|
||||
|
||||
if len(dictionaries[i].SysDictionaryDetails) > 0 {
|
||||
var detailElts []ast.Expr
|
||||
for _, detail := range dictionaries[i].SysDictionaryDetails {
|
||||
detailStatusStr := "true"
|
||||
if detail.Status != nil && !*detail.Status {
|
||||
detailStatusStr = "false"
|
||||
}
|
||||
|
||||
detailElts = append(detailElts, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysDictionaryDetail"},
|
||||
},
|
||||
Elts: []ast.Expr{
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Label"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", detail.Label)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Value"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", detail.Value)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Extend"},
|
||||
Value: &ast.BasicLit{Kind: token.STRING, Value: fmt.Sprintf("\"%s\"", detail.Extend)},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Status"},
|
||||
Value: &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "utils"},
|
||||
Sel: &ast.Ident{Name: "Pointer"},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.Ident{Name: detailStatusStr},
|
||||
},
|
||||
},
|
||||
},
|
||||
&ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "Sort"},
|
||||
Value: &ast.BasicLit{Kind: token.INT, Value: fmt.Sprintf("%d", detail.Sort)},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
elts = append(elts, &ast.KeyValueExpr{
|
||||
Key: &ast.Ident{Name: "SysDictionaryDetails"},
|
||||
Value: &ast.CompositeLit{
|
||||
Type: &ast.ArrayType{Elt: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysDictionaryDetail"},
|
||||
}},
|
||||
Elts: detailElts,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
dictElts = append(dictElts, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "model"},
|
||||
Sel: &ast.Ident{Name: "SysDictionary"},
|
||||
},
|
||||
Elts: elts,
|
||||
})
|
||||
}
|
||||
return &dictElts
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
func ImportForAutoEnter(path string, funcName string, code string) {
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fileSet := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fileSet, "", src, 0)
|
||||
ast.Inspect(astFile, func(node ast.Node) bool {
|
||||
if typeSpec, ok := node.(*ast.TypeSpec); ok {
|
||||
if typeSpec.Name.Name == funcName {
|
||||
if st, ok := typeSpec.Type.(*ast.StructType); ok {
|
||||
for i := range st.Fields.List {
|
||||
if t, ok := st.Fields.List[i].Type.(*ast.Ident); ok {
|
||||
if t.Name == code {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
sn := &ast.Field{
|
||||
Type: &ast.Ident{Name: code},
|
||||
}
|
||||
st.Fields.List = append(st.Fields.List, sn)
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
var out []byte
|
||||
bf := bytes.NewBuffer(out)
|
||||
err = printer.Fprint(bf, fileSet, astFile)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
_ = os.WriteFile(path, bf.Bytes(), 0666)
|
||||
}
|
||||
@@ -1,181 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"golang.org/x/text/cases"
|
||||
"golang.org/x/text/language"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Visitor struct {
|
||||
ImportCode string
|
||||
StructName string
|
||||
PackageName string
|
||||
GroupName string
|
||||
}
|
||||
|
||||
func (vi *Visitor) Visit(node ast.Node) ast.Visitor {
|
||||
switch n := node.(type) {
|
||||
case *ast.GenDecl:
|
||||
// 查找有没有import context包
|
||||
// Notice:没有考虑没有import任何包的情况
|
||||
if n.Tok == token.IMPORT && vi.ImportCode != "" {
|
||||
vi.addImport(n)
|
||||
// 不需要再遍历子树
|
||||
return nil
|
||||
}
|
||||
if n.Tok == token.TYPE && vi.StructName != "" && vi.PackageName != "" && vi.GroupName != "" {
|
||||
vi.addStruct(n)
|
||||
return nil
|
||||
}
|
||||
case *ast.FuncDecl:
|
||||
if n.Name.Name == "Routers" {
|
||||
vi.addFuncBodyVar(n)
|
||||
return nil
|
||||
}
|
||||
|
||||
}
|
||||
return vi
|
||||
}
|
||||
|
||||
func (vi *Visitor) addStruct(genDecl *ast.GenDecl) ast.Visitor {
|
||||
for i := range genDecl.Specs {
|
||||
switch n := genDecl.Specs[i].(type) {
|
||||
case *ast.TypeSpec:
|
||||
if strings.Index(n.Name.Name, "Group") > -1 {
|
||||
switch t := n.Type.(type) {
|
||||
case *ast.StructType:
|
||||
f := &ast.Field{
|
||||
Names: []*ast.Ident{
|
||||
{
|
||||
Name: vi.StructName,
|
||||
Obj: &ast.Object{
|
||||
Kind: ast.Var,
|
||||
Name: vi.StructName,
|
||||
},
|
||||
},
|
||||
},
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: vi.PackageName,
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: vi.GroupName,
|
||||
},
|
||||
},
|
||||
}
|
||||
t.Fields.List = append(t.Fields.List, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return vi
|
||||
}
|
||||
|
||||
func (vi *Visitor) addImport(genDecl *ast.GenDecl) ast.Visitor {
|
||||
// 是否已经import
|
||||
hasImported := false
|
||||
for _, v := range genDecl.Specs {
|
||||
importSpec := v.(*ast.ImportSpec)
|
||||
// 如果已经包含
|
||||
if importSpec.Path.Value == strconv.Quote(vi.ImportCode) {
|
||||
hasImported = true
|
||||
}
|
||||
}
|
||||
if !hasImported {
|
||||
genDecl.Specs = append(genDecl.Specs, &ast.ImportSpec{
|
||||
Path: &ast.BasicLit{
|
||||
Kind: token.STRING,
|
||||
Value: strconv.Quote(vi.ImportCode),
|
||||
},
|
||||
})
|
||||
}
|
||||
return vi
|
||||
}
|
||||
|
||||
func (vi *Visitor) addFuncBodyVar(funDecl *ast.FuncDecl) ast.Visitor {
|
||||
hasVar := false
|
||||
for _, v := range funDecl.Body.List {
|
||||
switch varSpec := v.(type) {
|
||||
case *ast.AssignStmt:
|
||||
for i := range varSpec.Lhs {
|
||||
switch nn := varSpec.Lhs[i].(type) {
|
||||
case *ast.Ident:
|
||||
if nn.Name == vi.PackageName+"Router" {
|
||||
hasVar = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasVar {
|
||||
assignStmt := &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
&ast.Ident{
|
||||
Name: vi.PackageName + "Router",
|
||||
Obj: &ast.Object{
|
||||
Kind: ast.Var,
|
||||
Name: vi.PackageName + "Router",
|
||||
},
|
||||
},
|
||||
},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: "router",
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: "RouterGroupApp",
|
||||
},
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: cases.Title(language.English).String(vi.PackageName),
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
funDecl.Body.List = append(funDecl.Body.List, funDecl.Body.List[1])
|
||||
index := 1
|
||||
copy(funDecl.Body.List[index+1:], funDecl.Body.List[index:])
|
||||
funDecl.Body.List[index] = assignStmt
|
||||
}
|
||||
return vi
|
||||
}
|
||||
|
||||
func ImportReference(filepath, importCode, structName, packageName, groupName string) error {
|
||||
fSet := token.NewFileSet()
|
||||
fParser, err := parser.ParseFile(fSet, filepath, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
importCode = strings.TrimSpace(importCode)
|
||||
v := &Visitor{
|
||||
ImportCode: importCode,
|
||||
StructName: structName,
|
||||
PackageName: packageName,
|
||||
GroupName: groupName,
|
||||
}
|
||||
if importCode == "" {
|
||||
ast.Print(fSet, fParser)
|
||||
}
|
||||
|
||||
ast.Walk(v, fParser)
|
||||
|
||||
var output []byte
|
||||
buffer := bytes.NewBuffer(output)
|
||||
err = format.Node(buffer, fSet, fParser)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// 写回数据
|
||||
return os.WriteFile(filepath, buffer.Bytes(), 0o600)
|
||||
}
|
||||
@@ -1,166 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
// AddRegisterTablesAst 自动为 gorm.go 注册一个自动迁移
|
||||
func AddRegisterTablesAst(path, funcName, pk, varName, dbName, model string) {
|
||||
modelPk := fmt.Sprintf("git.echol.cn/loser/Go-Web-Template/server/model/%s", pk)
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fileSet := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fileSet, "", src, 0)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
AddImport(astFile, modelPk)
|
||||
FuncNode := FindFunction(astFile, funcName)
|
||||
if FuncNode != nil {
|
||||
ast.Print(fileSet, FuncNode)
|
||||
}
|
||||
addDBVar(FuncNode.Body, varName, dbName)
|
||||
addAutoMigrate(FuncNode.Body, varName, pk, model)
|
||||
var out []byte
|
||||
bf := bytes.NewBuffer(out)
|
||||
printer.Fprint(bf, fileSet, astFile)
|
||||
|
||||
os.WriteFile(path, bf.Bytes(), 0666)
|
||||
}
|
||||
|
||||
// 增加一个 db库变量
|
||||
func addDBVar(astBody *ast.BlockStmt, varName, dbName string) {
|
||||
if dbName == "" {
|
||||
return
|
||||
}
|
||||
dbStr := fmt.Sprintf("\"%s\"", dbName)
|
||||
|
||||
for i := range astBody.List {
|
||||
if assignStmt, ok := astBody.List[i].(*ast.AssignStmt); ok {
|
||||
if ident, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
|
||||
if ident.Name == varName {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assignNode := &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
&ast.Ident{
|
||||
Name: varName,
|
||||
},
|
||||
},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: "global",
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: "GetGlobalDBByDBName",
|
||||
},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.BasicLit{
|
||||
Kind: token.STRING,
|
||||
Value: dbStr,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
astBody.List = append([]ast.Stmt{assignNode}, astBody.List...)
|
||||
}
|
||||
|
||||
// 为db库变量增加 AutoMigrate 方法
|
||||
func addAutoMigrate(astBody *ast.BlockStmt, dbname string, pk string, model string) {
|
||||
if dbname == "" {
|
||||
dbname = "db"
|
||||
}
|
||||
flag := true
|
||||
ast.Inspect(astBody, func(node ast.Node) bool {
|
||||
// 首先判断需要加入的方法调用语句是否存在 不存在则直接走到下方逻辑
|
||||
switch n := node.(type) {
|
||||
case *ast.CallExpr:
|
||||
// 判断是否找到了AutoMigrate语句
|
||||
if s, ok := n.Fun.(*ast.SelectorExpr); ok {
|
||||
if x, ok := s.X.(*ast.Ident); ok {
|
||||
if s.Sel.Name == "AutoMigrate" && x.Name == dbname {
|
||||
flag = false
|
||||
if !NeedAppendModel(n, pk, model) {
|
||||
return false
|
||||
}
|
||||
// 判断已经找到了AutoMigrate语句
|
||||
n.Args = append(n.Args, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: pk,
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: model,
|
||||
},
|
||||
},
|
||||
})
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
//然后判断 pk.model是否存在 如果存在直接跳出 如果不存在 则向已经找到的方法调用语句的node里面push一条
|
||||
})
|
||||
|
||||
if flag {
|
||||
exprStmt := &ast.ExprStmt{
|
||||
X: &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: dbname,
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: "AutoMigrate",
|
||||
},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: pk,
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: model,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
astBody.List = append(astBody.List, exprStmt)
|
||||
}
|
||||
}
|
||||
|
||||
// NeedAppendModel 为automigrate增加实参
|
||||
func NeedAppendModel(callNode ast.Node, pk string, model string) bool {
|
||||
flag := true
|
||||
ast.Inspect(callNode, func(node ast.Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *ast.SelectorExpr:
|
||||
if x, ok := n.X.(*ast.Ident); ok {
|
||||
if n.Sel.Name == model && x.Name == pk {
|
||||
flag = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return flag
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func init() {
|
||||
global.GVA_CONFIG.AutoCode.Root, _ = filepath.Abs("../../../")
|
||||
global.GVA_CONFIG.AutoCode.Server = "server"
|
||||
}
|
||||
@@ -1,172 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
)
|
||||
|
||||
func RollBackAst(pk, model string) {
|
||||
RollGormBack(pk, model)
|
||||
RollRouterBack(pk, model)
|
||||
}
|
||||
|
||||
func RollGormBack(pk, model string) {
|
||||
|
||||
// 首先分析存在多少个ttt作为调用方的node块
|
||||
// 如果多个 仅仅删除对应块即可
|
||||
// 如果单个 那么还需要剔除import
|
||||
path := filepath.Join(resolveServerRoot(), "initialize", "gorm_biz.go")
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fileSet := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fileSet, "", src, 0)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
var n *ast.CallExpr
|
||||
var k int = -1
|
||||
var pkNum = 0
|
||||
ast.Inspect(astFile, func(node ast.Node) bool {
|
||||
if node, ok := node.(*ast.CallExpr); ok {
|
||||
for i := range node.Args {
|
||||
pkOK := false
|
||||
modelOK := false
|
||||
ast.Inspect(node.Args[i], func(item ast.Node) bool {
|
||||
if ii, ok := item.(*ast.Ident); ok {
|
||||
if ii.Name == pk {
|
||||
pkOK = true
|
||||
pkNum++
|
||||
}
|
||||
if ii.Name == model {
|
||||
modelOK = true
|
||||
}
|
||||
}
|
||||
if pkOK && modelOK {
|
||||
n = node
|
||||
k = i
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
if k > -1 {
|
||||
n.Args = append(append([]ast.Expr{}, n.Args[:k]...), n.Args[k+1:]...)
|
||||
}
|
||||
if pkNum == 1 {
|
||||
var imI int = -1
|
||||
var gp *ast.GenDecl
|
||||
ast.Inspect(astFile, func(node ast.Node) bool {
|
||||
if gen, ok := node.(*ast.GenDecl); ok {
|
||||
for i := range gen.Specs {
|
||||
if imspec, ok := gen.Specs[i].(*ast.ImportSpec); ok {
|
||||
if imspec.Path.Value == "\"git.echol.cn/loser/Go-Web-Template/server/model/"+pk+"\"" {
|
||||
gp = gen
|
||||
imI = i
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if imI > -1 {
|
||||
gp.Specs = append(append([]ast.Spec{}, gp.Specs[:imI]...), gp.Specs[imI+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
var out []byte
|
||||
bf := bytes.NewBuffer(out)
|
||||
printer.Fprint(bf, fileSet, astFile)
|
||||
os.Remove(path)
|
||||
os.WriteFile(path, bf.Bytes(), 0666)
|
||||
|
||||
}
|
||||
|
||||
func RollRouterBack(pk, model string) {
|
||||
|
||||
// 首先抓到所有的代码块结构 {}
|
||||
// 分析结构中是否存在一个变量叫做 pk+Router
|
||||
// 然后获取到代码块指针 对内部需要回滚的代码进行剔除
|
||||
path := filepath.Join(resolveServerRoot(), "initialize", "router_biz.go")
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fileSet := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fileSet, "", src, 0)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
var block *ast.BlockStmt
|
||||
var routerStmt *ast.FuncDecl
|
||||
|
||||
ast.Inspect(astFile, func(node ast.Node) bool {
|
||||
if n, ok := node.(*ast.FuncDecl); ok {
|
||||
if n.Name.Name == "initBizRouter" {
|
||||
routerStmt = n
|
||||
}
|
||||
}
|
||||
|
||||
if n, ok := node.(*ast.BlockStmt); ok {
|
||||
ast.Inspect(n, func(bNode ast.Node) bool {
|
||||
if in, ok := bNode.(*ast.Ident); ok {
|
||||
if in.Name == pk+"Router" {
|
||||
block = n
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return true
|
||||
}
|
||||
return true
|
||||
})
|
||||
var k int
|
||||
for i := range block.List {
|
||||
if stmtNode, ok := block.List[i].(*ast.ExprStmt); ok {
|
||||
ast.Inspect(stmtNode, func(node ast.Node) bool {
|
||||
if n, ok := node.(*ast.Ident); ok {
|
||||
if n.Name == "Init"+model+"Router" {
|
||||
k = i
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
block.List = append(append([]ast.Stmt{}, block.List[:k]...), block.List[k+1:]...)
|
||||
|
||||
if len(block.List) == 1 {
|
||||
// 说明这个块就没任何意义了
|
||||
block.List = nil
|
||||
}
|
||||
|
||||
for i, n := range routerStmt.Body.List {
|
||||
if n, ok := n.(*ast.BlockStmt); ok {
|
||||
if n.List == nil {
|
||||
routerStmt.Body.List = append(append([]ast.Stmt{}, routerStmt.Body.List[:i]...), routerStmt.Body.List[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var out []byte
|
||||
bf := bytes.NewBuffer(out)
|
||||
printer.Fprint(bf, fileSet, astFile)
|
||||
os.Remove(path)
|
||||
os.WriteFile(path, bf.Bytes(), 0666)
|
||||
}
|
||||
@@ -1,135 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func AppendNodeToList(stmts []ast.Stmt, stmt ast.Stmt, index int) []ast.Stmt {
|
||||
return append(stmts[:index], append([]ast.Stmt{stmt}, stmts[index:]...)...)
|
||||
}
|
||||
|
||||
func AddRouterCode(path, funcName, pk, model string) {
|
||||
src, err := os.ReadFile(path)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
fileSet := token.NewFileSet()
|
||||
astFile, err := parser.ParseFile(fileSet, "", src, parser.ParseComments)
|
||||
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
}
|
||||
|
||||
FuncNode := FindFunction(astFile, funcName)
|
||||
|
||||
pkName := strings.ToUpper(pk[:1]) + pk[1:]
|
||||
routerName := fmt.Sprintf("%sRouter", pk)
|
||||
modelName := fmt.Sprintf("Init%sRouter", model)
|
||||
var bloctPre *ast.BlockStmt
|
||||
for i := len(FuncNode.Body.List) - 1; i >= 0; i-- {
|
||||
if block, ok := FuncNode.Body.List[i].(*ast.BlockStmt); ok {
|
||||
bloctPre = block
|
||||
}
|
||||
}
|
||||
ast.Print(fileSet, FuncNode)
|
||||
if ok, b := needAppendRouter(FuncNode, pk); ok {
|
||||
routerNode :=
|
||||
&ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
&ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
&ast.Ident{Name: routerName},
|
||||
},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: "router"},
|
||||
Sel: &ast.Ident{Name: "RouterGroupApp"},
|
||||
},
|
||||
Sel: &ast.Ident{Name: pkName},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
FuncNode.Body.List = AppendNodeToList(FuncNode.Body.List, routerNode, len(FuncNode.Body.List)-1)
|
||||
bloctPre = routerNode
|
||||
} else {
|
||||
bloctPre = b
|
||||
}
|
||||
|
||||
if needAppendInit(FuncNode, routerName, modelName) {
|
||||
bloctPre.List = append(bloctPre.List,
|
||||
&ast.ExprStmt{
|
||||
X: &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: routerName},
|
||||
Sel: &ast.Ident{Name: modelName},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.Ident{
|
||||
Name: "privateGroup",
|
||||
},
|
||||
&ast.Ident{
|
||||
Name: "publicGroup",
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
var out []byte
|
||||
bf := bytes.NewBuffer(out)
|
||||
printer.Fprint(bf, fileSet, astFile)
|
||||
os.WriteFile(path, bf.Bytes(), 0666)
|
||||
}
|
||||
|
||||
func needAppendRouter(funcNode ast.Node, pk string) (bool, *ast.BlockStmt) {
|
||||
flag := true
|
||||
var block *ast.BlockStmt
|
||||
ast.Inspect(funcNode, func(node ast.Node) bool {
|
||||
switch n := node.(type) {
|
||||
case *ast.BlockStmt:
|
||||
for i := range n.List {
|
||||
if assignNode, ok := n.List[i].(*ast.AssignStmt); ok {
|
||||
if identNode, ok := assignNode.Lhs[0].(*ast.Ident); ok {
|
||||
if identNode.Name == fmt.Sprintf("%sRouter", pk) {
|
||||
flag = false
|
||||
block = n
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return true
|
||||
})
|
||||
return flag, block
|
||||
}
|
||||
|
||||
func needAppendInit(funcNode ast.Node, routerName string, modelName string) bool {
|
||||
flag := true
|
||||
ast.Inspect(funcNode, func(node ast.Node) bool {
|
||||
switch n := funcNode.(type) {
|
||||
case *ast.CallExpr:
|
||||
if selectNode, ok := n.Fun.(*ast.SelectorExpr); ok {
|
||||
x, xok := selectNode.X.(*ast.Ident)
|
||||
if xok && x.Name == routerName && selectNode.Sel.Name == modelName {
|
||||
flag = false
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
return flag
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/printer"
|
||||
"go/token"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestAst(t *testing.T) {
|
||||
filename := filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "plugin.go")
|
||||
fileSet := token.NewFileSet()
|
||||
file, err := parser.ParseFile(fileSet, filename, nil, parser.ParseComments)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
err = ast.Print(fileSet, file)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
return
|
||||
}
|
||||
err = printer.Fprint(os.Stdout, token.NewFileSet(), file)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
package ast
|
||||
|
||||
type Type string
|
||||
|
||||
func (r Type) String() string {
|
||||
return string(r)
|
||||
}
|
||||
|
||||
func (r Type) Group() string {
|
||||
switch r {
|
||||
case TypePackageApiEnter:
|
||||
return "ApiGroup"
|
||||
case TypePackageRouterEnter:
|
||||
return "RouterGroup"
|
||||
case TypePackageServiceEnter:
|
||||
return "ServiceGroup"
|
||||
case TypePackageApiModuleEnter:
|
||||
return "ApiGroup"
|
||||
case TypePackageRouterModuleEnter:
|
||||
return "RouterGroup"
|
||||
case TypePackageServiceModuleEnter:
|
||||
return "ServiceGroup"
|
||||
default:
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
TypePackageApiEnter = "PackageApiEnter" // server/api/v1/enter.go
|
||||
TypePackageRouterEnter = "PackageRouterEnter" // server/router/enter.go
|
||||
TypePackageServiceEnter = "PackageServiceEnter" // server/service/enter.go
|
||||
TypePackageApiModuleEnter = "PackageApiModuleEnter" // server/api/v1/{package}/enter.go
|
||||
TypePackageRouterModuleEnter = "PackageRouterModuleEnter" // server/router/{package}/enter.go
|
||||
TypePackageServiceModuleEnter = "PackageServiceModuleEnter" // server/service/{package}/enter.go
|
||||
TypePackageInitializeGorm = "PackageInitializeGorm" // server/initialize/gorm_biz.go
|
||||
TypePackageInitializeRouter = "PackageInitializeRouter" // server/initialize/router_biz.go
|
||||
)
|
||||
@@ -1,62 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"os"
|
||||
)
|
||||
|
||||
// ExtractFuncSourceByPosition 根据文件路径与行号,提取包含该行的整个方法源码
|
||||
// 返回:方法名、完整源码、起止行号
|
||||
func ExtractFuncSourceByPosition(filePath string, line int) (name string, source string, startLine int, endLine int, err error) {
|
||||
// 读取源文件
|
||||
src, readErr := os.ReadFile(filePath)
|
||||
if readErr != nil {
|
||||
err = fmt.Errorf("read file failed: %w", readErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 解析 AST
|
||||
fset := token.NewFileSet()
|
||||
file, parseErr := parser.ParseFile(fset, filePath, src, parser.ParseComments)
|
||||
if parseErr != nil {
|
||||
err = fmt.Errorf("parse file failed: %w", parseErr)
|
||||
return
|
||||
}
|
||||
|
||||
// 在 AST 中定位包含指定行号的函数声明
|
||||
var target *ast.FuncDecl
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
fd, ok := n.(*ast.FuncDecl)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
s := fset.Position(fd.Pos()).Line
|
||||
e := fset.Position(fd.End()).Line
|
||||
if line >= s && line <= e {
|
||||
target = fd
|
||||
startLine = s
|
||||
endLine = e
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if target == nil {
|
||||
err = fmt.Errorf("no function encloses line %d in %s", line, filePath)
|
||||
return
|
||||
}
|
||||
|
||||
// 使用字节偏移精确提取源码片段(包含注释与原始格式)
|
||||
start := fset.Position(target.Pos()).Offset
|
||||
end := fset.Position(target.End()).Offset
|
||||
if start < 0 || end > len(src) || start >= end {
|
||||
err = fmt.Errorf("invalid offsets for function: start=%d end=%d len=%d", start, end, len(src))
|
||||
return
|
||||
}
|
||||
source = string(src[start:end])
|
||||
name = target.Name.Name
|
||||
return
|
||||
}
|
||||
@@ -1,94 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Import struct {
|
||||
Base
|
||||
ImportPath string // 导包路径
|
||||
}
|
||||
|
||||
func NewImport(importPath string) *Import {
|
||||
return &Import{ImportPath: importPath}
|
||||
}
|
||||
|
||||
func (a *Import) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
|
||||
func (a *Import) Rollback(file *ast.File) error {
|
||||
if a.ImportPath == "" {
|
||||
return nil
|
||||
}
|
||||
for i := 0; i < len(file.Decls); i++ {
|
||||
v1, o1 := file.Decls[i].(*ast.GenDecl)
|
||||
if o1 {
|
||||
if v1.Tok != token.IMPORT {
|
||||
break
|
||||
}
|
||||
for j := 0; j < len(v1.Specs); j++ {
|
||||
v2, o2 := v1.Specs[j].(*ast.ImportSpec)
|
||||
if o2 && strings.HasSuffix(a.ImportPath, v2.Path.Value) {
|
||||
v1.Specs = append(v1.Specs[:j], v1.Specs[j+1:]...)
|
||||
if len(v1.Specs) == 0 {
|
||||
file.Decls = append(file.Decls[:i], file.Decls[i+1:]...)
|
||||
} // 如果没有import声明,就删除, 如果不删除则会出现import()
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Import) Injection(file *ast.File) error {
|
||||
if a.ImportPath == "" {
|
||||
return nil
|
||||
}
|
||||
var has bool
|
||||
for i := 0; i < len(file.Decls); i++ {
|
||||
v1, o1 := file.Decls[i].(*ast.GenDecl)
|
||||
if o1 {
|
||||
if v1.Tok != token.IMPORT {
|
||||
break
|
||||
}
|
||||
for j := 0; j < len(v1.Specs); j++ {
|
||||
v2, o2 := v1.Specs[j].(*ast.ImportSpec)
|
||||
if o2 && strings.HasSuffix(a.ImportPath, v2.Path.Value) {
|
||||
has = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !has {
|
||||
spec := &ast.ImportSpec{
|
||||
Path: &ast.BasicLit{Kind: token.STRING, Value: a.ImportPath},
|
||||
}
|
||||
v1.Specs = append(v1.Specs, spec)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
}
|
||||
if !has {
|
||||
decls := file.Decls
|
||||
file.Decls = make([]ast.Decl, 0, len(file.Decls)+1)
|
||||
decl := &ast.GenDecl{
|
||||
Tok: token.IMPORT,
|
||||
Specs: []ast.Spec{
|
||||
&ast.ImportSpec{
|
||||
Path: &ast.BasicLit{Kind: token.STRING, Value: a.ImportPath},
|
||||
},
|
||||
},
|
||||
}
|
||||
file.Decls = append(file.Decls, decl)
|
||||
file.Decls = append(file.Decls, decls...)
|
||||
} // 如果没有import声明,就创建一个, 主要要放在第一个
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Import) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
return a.Base.Format(filename, writer, file)
|
||||
}
|
||||
@@ -1,17 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Ast interface {
|
||||
// Parse 解析文件/代码
|
||||
Parse(filename string, writer io.Writer) (file *ast.File, err error)
|
||||
// Rollback 回滚
|
||||
Rollback(file *ast.File) error
|
||||
// Injection 注入
|
||||
Injection(file *ast.File) error
|
||||
// Format 格式化输出
|
||||
Format(filename string, writer io.Writer, file *ast.File) error
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"go/ast"
|
||||
"go/format"
|
||||
"go/parser"
|
||||
"go/token"
|
||||
"io"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type Base struct {
|
||||
FileSet *token.FileSet
|
||||
}
|
||||
|
||||
func (a *Base) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
a.FileSet = token.NewFileSet()
|
||||
if writer != nil {
|
||||
file, err = parser.ParseFile(a.FileSet, filename, nil, parser.ParseComments)
|
||||
} else {
|
||||
file, err = parser.ParseFile(a.FileSet, filename, writer, parser.ParseComments)
|
||||
}
|
||||
if err != nil {
|
||||
return nil, errors.Wrapf(err, "[filepath:%s]打开/解析文件失败!", filename)
|
||||
}
|
||||
return file, nil
|
||||
}
|
||||
|
||||
func (a *Base) Rollback(file *ast.File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Base) Injection(file *ast.File) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Base) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
fileSet := a.FileSet
|
||||
if fileSet == nil {
|
||||
fileSet = token.NewFileSet()
|
||||
}
|
||||
if writer == nil {
|
||||
open, err := os.OpenFile(filename, os.O_WRONLY|os.O_TRUNC, 0666)
|
||||
defer open.Close()
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "[filepath:%s]打开文件失败!", filename)
|
||||
}
|
||||
writer = open
|
||||
}
|
||||
err := format.Node(writer, fileSet, file)
|
||||
if err != nil {
|
||||
return errors.Wrapf(err, "[filepath:%s]注入失败!", filename)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RelativePath 绝对路径转相对路径
|
||||
func (a *Base) RelativePath(filePath string) string {
|
||||
server := resolveServerRoot()
|
||||
hasServer := strings.Index(filePath, server)
|
||||
if hasServer != -1 {
|
||||
filePath = strings.TrimPrefix(filePath, server)
|
||||
keys := strings.Split(filePath, string(filepath.Separator))
|
||||
filePath = path.Join(keys...)
|
||||
}
|
||||
return filePath
|
||||
}
|
||||
|
||||
// AbsolutePath 相对路径转绝对路径
|
||||
func (a *Base) AbsolutePath(filePath string) string {
|
||||
server := resolveServerRoot()
|
||||
keys := strings.Split(filePath, "/")
|
||||
filePath = filepath.Join(keys...)
|
||||
filePath = filepath.Join(server, filePath)
|
||||
return filePath
|
||||
}
|
||||
|
||||
func resolveProjectRoot() string {
|
||||
if cwd, err := os.Getwd(); err == nil {
|
||||
if filepath.Base(cwd) == "server" {
|
||||
return filepath.Dir(cwd)
|
||||
}
|
||||
if _, err := os.Stat(filepath.Join(cwd, "server")); err == nil {
|
||||
return cwd
|
||||
}
|
||||
return cwd
|
||||
}
|
||||
return "."
|
||||
}
|
||||
|
||||
func resolveServerRoot() string {
|
||||
root := resolveProjectRoot()
|
||||
if filepath.Base(root) == "server" {
|
||||
return root
|
||||
}
|
||||
return filepath.Join(root, "server")
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PackageEnter 模块化入口
|
||||
type PackageEnter struct {
|
||||
Base
|
||||
Type Type // 类型
|
||||
Path string // 文件路径
|
||||
ImportPath string // 导包路径
|
||||
StructName string // 结构体名称
|
||||
PackageName string // 包名
|
||||
RelativePath string // 相对路径
|
||||
PackageStructName string // 包结构体名称
|
||||
}
|
||||
|
||||
func (a *PackageEnter) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
if filename == "" {
|
||||
if a.RelativePath == "" {
|
||||
filename = a.Path
|
||||
a.RelativePath = a.Base.RelativePath(a.Path)
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
a.Path = a.Base.AbsolutePath(a.RelativePath)
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
|
||||
func (a *PackageEnter) Rollback(file *ast.File) error {
|
||||
// 无需回滚
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageEnter) Injection(file *ast.File) error {
|
||||
_ = NewImport(a.ImportPath).Injection(file)
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
genDecl, ok := n.(*ast.GenDecl)
|
||||
if !ok || genDecl.Tok != token.TYPE {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, spec := range genDecl.Specs {
|
||||
typeSpec, specok := spec.(*ast.TypeSpec)
|
||||
if !specok || typeSpec.Name.Name != a.Type.Group() {
|
||||
continue
|
||||
}
|
||||
|
||||
structType, structTypeOK := typeSpec.Type.(*ast.StructType)
|
||||
if !structTypeOK {
|
||||
continue
|
||||
}
|
||||
|
||||
for _, field := range structType.Fields.List {
|
||||
if len(field.Names) == 1 && field.Names[0].Name == a.StructName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
field := &ast.Field{
|
||||
Names: []*ast.Ident{{Name: a.StructName}},
|
||||
Type: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: a.PackageName},
|
||||
Sel: &ast.Ident{Name: a.PackageStructName},
|
||||
},
|
||||
}
|
||||
structType.Fields.List = append(structType.Fields.List, field)
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageEnter) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
if filename == "" {
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Format(filename, writer, file)
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackageEnter_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
PackageStructName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试ExampleApiGroup回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageApiEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/api/v1/example"`,
|
||||
StructName: "ExampleApiGroup",
|
||||
PackageName: "example",
|
||||
PackageStructName: "ApiGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试ExampleRouterGroup回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageRouterEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "router", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router/example"`,
|
||||
StructName: "Example",
|
||||
PackageName: "example",
|
||||
PackageStructName: "RouterGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试ExampleServiceGroup回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageServiceEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/service/example"`,
|
||||
StructName: "ExampleServiceGroup",
|
||||
PackageName: "example",
|
||||
PackageStructName: "ServiceGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
PackageStructName: tt.fields.PackageStructName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageEnter_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
PackageStructName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试ExampleApiGroup注入",
|
||||
fields: fields{
|
||||
Type: TypePackageApiEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/api/v1/example"`,
|
||||
StructName: "ExampleApiGroup",
|
||||
PackageName: "example",
|
||||
PackageStructName: "ApiGroup",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试ExampleRouterGroup注入",
|
||||
fields: fields{
|
||||
Type: TypePackageRouterEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "router", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router/example"`,
|
||||
StructName: "Example",
|
||||
PackageName: "example",
|
||||
PackageStructName: "RouterGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试ExampleServiceGroup注入",
|
||||
fields: fields{
|
||||
Type: TypePackageServiceEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/service/example"`,
|
||||
StructName: "ExampleServiceGroup",
|
||||
PackageName: "example",
|
||||
PackageStructName: "ServiceGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
PackageStructName: tt.fields.PackageStructName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Format() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,196 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PackageInitializeGorm 包初始化gorm
|
||||
type PackageInitializeGorm struct {
|
||||
Base
|
||||
Type Type // 类型
|
||||
Path string // 文件路径
|
||||
ImportPath string // 导包路径
|
||||
Business string // 业务库 gva => gva, 不要传"gva"
|
||||
StructName string // 结构体名称
|
||||
PackageName string // 包名
|
||||
RelativePath string // 相对路径
|
||||
IsNew bool // 是否使用new关键字 true: new(PackageName.StructName) false: &PackageName.StructName{}
|
||||
}
|
||||
|
||||
func (a *PackageInitializeGorm) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
if filename == "" {
|
||||
if a.RelativePath == "" {
|
||||
filename = a.Path
|
||||
a.RelativePath = a.Base.RelativePath(a.Path)
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
a.Path = a.Base.AbsolutePath(a.RelativePath)
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
|
||||
func (a *PackageInitializeGorm) Rollback(file *ast.File) error {
|
||||
packageNameNum := 0
|
||||
// 寻找目标结构
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
// 总调用的db变量根据business来决定
|
||||
varDB := a.Business + "Db"
|
||||
|
||||
if a.Business == "" {
|
||||
varDB = "db"
|
||||
}
|
||||
|
||||
callExpr, ok := n.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查是不是 db.AutoMigrate() 方法
|
||||
selExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok || selExpr.Sel.Name != "AutoMigrate" {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查调用方是不是 db
|
||||
ident, ok := selExpr.X.(*ast.Ident)
|
||||
if !ok || ident.Name != varDB {
|
||||
return true
|
||||
}
|
||||
|
||||
// 删除结构体参数
|
||||
for i := 0; i < len(callExpr.Args); i++ {
|
||||
if com, comok := callExpr.Args[i].(*ast.CompositeLit); comok {
|
||||
if selector, exprok := com.Type.(*ast.SelectorExpr); exprok {
|
||||
if x, identok := selector.X.(*ast.Ident); identok {
|
||||
if x.Name == a.PackageName {
|
||||
packageNameNum++
|
||||
if selector.Sel.Name == a.StructName {
|
||||
callExpr.Args = append(callExpr.Args[:i], callExpr.Args[i+1:]...)
|
||||
i--
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
if packageNameNum == 1 {
|
||||
_ = NewImport(a.ImportPath).Rollback(file)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageInitializeGorm) Injection(file *ast.File) error {
|
||||
_ = NewImport(a.ImportPath).Injection(file)
|
||||
bizModelDecl := FindFunction(file, "bizModel")
|
||||
if bizModelDecl != nil {
|
||||
a.addDbVar(bizModelDecl.Body)
|
||||
}
|
||||
// 寻找目标结构
|
||||
ast.Inspect(file, func(n ast.Node) bool {
|
||||
// 总调用的db变量根据business来决定
|
||||
varDB := a.Business + "Db"
|
||||
|
||||
if a.Business == "" {
|
||||
varDB = "db"
|
||||
}
|
||||
|
||||
callExpr, ok := n.(*ast.CallExpr)
|
||||
if !ok {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查是不是 db.AutoMigrate() 方法
|
||||
selExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok || selExpr.Sel.Name != "AutoMigrate" {
|
||||
return true
|
||||
}
|
||||
|
||||
// 检查调用方是不是 db
|
||||
ident, ok := selExpr.X.(*ast.Ident)
|
||||
if !ok || ident.Name != varDB {
|
||||
return true
|
||||
}
|
||||
|
||||
// 添加结构体参数
|
||||
callExpr.Args = append(callExpr.Args, &ast.CompositeLit{
|
||||
Type: &ast.SelectorExpr{
|
||||
X: ast.NewIdent(a.PackageName),
|
||||
Sel: ast.NewIdent(a.StructName),
|
||||
},
|
||||
})
|
||||
return true
|
||||
})
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageInitializeGorm) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
if filename == "" {
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Format(filename, writer, file)
|
||||
}
|
||||
|
||||
// 创建businessDB变量
|
||||
func (a *PackageInitializeGorm) addDbVar(astBody *ast.BlockStmt) {
|
||||
for i := range astBody.List {
|
||||
if assignStmt, ok := astBody.List[i].(*ast.AssignStmt); ok {
|
||||
if ident, ok := assignStmt.Lhs[0].(*ast.Ident); ok {
|
||||
if (a.Business == "" && ident.Name == "db") || ident.Name == a.Business+"Db" {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 添加 businessDb := global.GetGlobalDBByDBName("business") 变量
|
||||
assignNode := &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{
|
||||
&ast.Ident{
|
||||
Name: a.Business + "Db",
|
||||
},
|
||||
},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{
|
||||
&ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: "global",
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: "GetGlobalDBByDBName",
|
||||
},
|
||||
},
|
||||
Args: []ast.Expr{
|
||||
&ast.BasicLit{
|
||||
Kind: token.STRING,
|
||||
Value: fmt.Sprintf("\"%s\"", a.Business),
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// 添加 businessDb.AutoMigrate() 方法
|
||||
autoMigrateCall := &ast.ExprStmt{
|
||||
X: &ast.CallExpr{
|
||||
Fun: &ast.SelectorExpr{
|
||||
X: &ast.Ident{
|
||||
Name: a.Business + "Db",
|
||||
},
|
||||
Sel: &ast.Ident{
|
||||
Name: "AutoMigrate",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
returnNode := astBody.List[len(astBody.List)-1]
|
||||
astBody.List = append(astBody.List[:len(astBody.List)-1], assignNode, autoMigrateCall, returnNode)
|
||||
}
|
||||
@@ -1,171 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackageInitializeGorm_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 &example.ExaFileUploadAndDownload{} 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaFileUploadAndDownload",
|
||||
PackageName: "example",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 &example.ExaCustomer{} 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaCustomer",
|
||||
PackageName: "example",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(example.ExaFileUploadAndDownload) 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaFileUploadAndDownload",
|
||||
PackageName: "example",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(example.ExaCustomer) 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaCustomer",
|
||||
PackageName: "example",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageInitializeGorm{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageInitializeGorm_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 &example.ExaFileUploadAndDownload{} 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaFileUploadAndDownload",
|
||||
PackageName: "example",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 &example.ExaCustomer{} 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaCustomer",
|
||||
PackageName: "example",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(example.ExaFileUploadAndDownload) 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaFileUploadAndDownload",
|
||||
PackageName: "example",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(example.ExaCustomer) 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "gorm_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/model/example"`,
|
||||
StructName: "ExaCustomer",
|
||||
PackageName: "example",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageInitializeGorm{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,150 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PackageInitializeRouter 包初始化路由
|
||||
// ModuleName := PackageName.AppName.GroupName
|
||||
// ModuleName.FunctionName(RouterGroupName)
|
||||
type PackageInitializeRouter struct {
|
||||
Base
|
||||
Type Type // 类型
|
||||
Path string // 文件路径
|
||||
ImportPath string // 导包路径
|
||||
RelativePath string // 相对路径
|
||||
AppName string // 应用名称
|
||||
GroupName string // 分组名称
|
||||
ModuleName string // 模块名称
|
||||
PackageName string // 包名
|
||||
FunctionName string // 函数名
|
||||
RouterGroupName string // 路由分组名称
|
||||
LeftRouterGroupName string // 左路由分组名称
|
||||
RightRouterGroupName string // 右路由分组名称
|
||||
}
|
||||
|
||||
func (a *PackageInitializeRouter) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
if filename == "" {
|
||||
if a.RelativePath == "" {
|
||||
filename = a.Path
|
||||
a.RelativePath = a.Base.RelativePath(a.Path)
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
a.Path = a.Base.AbsolutePath(a.RelativePath)
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
|
||||
func (a *PackageInitializeRouter) Rollback(file *ast.File) error {
|
||||
funcDecl := FindFunction(file, "initBizRouter")
|
||||
exprNum := 0
|
||||
for i := range funcDecl.Body.List {
|
||||
if IsBlockStmt(funcDecl.Body.List[i]) {
|
||||
if VariableExistsInBlock(funcDecl.Body.List[i].(*ast.BlockStmt), a.ModuleName) {
|
||||
for ii, stmt := range funcDecl.Body.List[i].(*ast.BlockStmt).List {
|
||||
// 检查语句是否为 *ast.ExprStmt
|
||||
exprStmt, ok := stmt.(*ast.ExprStmt)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 检查表达式是否为 *ast.CallExpr
|
||||
callExpr, ok := exprStmt.X.(*ast.CallExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 检查是否调用了我们正在寻找的函数
|
||||
selExpr, ok := callExpr.Fun.(*ast.SelectorExpr)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
// 检查调用的函数是否为 systemRouter.InitApiRouter
|
||||
ident, ok := selExpr.X.(*ast.Ident)
|
||||
//只要存在调用则+1
|
||||
if ok && ident.Name == a.ModuleName {
|
||||
exprNum++
|
||||
}
|
||||
//判断是否为目标结构
|
||||
if !ok || ident.Name != a.ModuleName || selExpr.Sel.Name != a.FunctionName {
|
||||
continue
|
||||
}
|
||||
exprNum--
|
||||
// 从语句列表中移除。
|
||||
funcDecl.Body.List[i].(*ast.BlockStmt).List = append(funcDecl.Body.List[i].(*ast.BlockStmt).List[:ii], funcDecl.Body.List[i].(*ast.BlockStmt).List[ii+1:]...)
|
||||
// 如果不再存在任何调用,则删除导入和变量。
|
||||
if exprNum == 0 {
|
||||
funcDecl.Body.List = append(funcDecl.Body.List[:i], funcDecl.Body.List[i+1:]...)
|
||||
}
|
||||
break
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageInitializeRouter) Injection(file *ast.File) error {
|
||||
funcDecl := FindFunction(file, "initBizRouter")
|
||||
hasRouter := false
|
||||
var varBlock *ast.BlockStmt
|
||||
for i := range funcDecl.Body.List {
|
||||
if IsBlockStmt(funcDecl.Body.List[i]) {
|
||||
if VariableExistsInBlock(funcDecl.Body.List[i].(*ast.BlockStmt), a.ModuleName) {
|
||||
hasRouter = true
|
||||
varBlock = funcDecl.Body.List[i].(*ast.BlockStmt)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasRouter {
|
||||
stmt := a.CreateAssignStmt()
|
||||
varBlock = &ast.BlockStmt{
|
||||
List: []ast.Stmt{
|
||||
stmt,
|
||||
},
|
||||
}
|
||||
}
|
||||
routerStmt := CreateStmt(fmt.Sprintf("%s.%s(%s,%s)", a.ModuleName, a.FunctionName, a.LeftRouterGroupName, a.RightRouterGroupName))
|
||||
varBlock.List = append(varBlock.List, routerStmt)
|
||||
if !hasRouter {
|
||||
funcDecl.Body.List = append(funcDecl.Body.List, varBlock)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageInitializeRouter) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
if filename == "" {
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Format(filename, writer, file)
|
||||
}
|
||||
|
||||
func (a *PackageInitializeRouter) CreateAssignStmt() *ast.AssignStmt {
|
||||
//创建左侧变量
|
||||
ident := &ast.Ident{
|
||||
Name: a.ModuleName,
|
||||
}
|
||||
|
||||
//创建右侧的赋值语句
|
||||
selector := &ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: a.PackageName},
|
||||
Sel: &ast.Ident{Name: a.AppName},
|
||||
},
|
||||
Sel: &ast.Ident{Name: a.GroupName},
|
||||
}
|
||||
|
||||
// 创建一个组合的赋值语句
|
||||
stmt := &ast.AssignStmt{
|
||||
Lhs: []ast.Expr{ident},
|
||||
Tok: token.DEFINE,
|
||||
Rhs: []ast.Expr{selector},
|
||||
}
|
||||
|
||||
return stmt
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackageInitializeRouter_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
AppName string
|
||||
GroupName string
|
||||
ModuleName string
|
||||
PackageName string
|
||||
FunctionName string
|
||||
RouterGroupName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 InitCustomerRouter 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "router_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router"`,
|
||||
AppName: "RouterGroupApp",
|
||||
GroupName: "Example",
|
||||
ModuleName: "exampleRouter",
|
||||
PackageName: "router",
|
||||
FunctionName: "InitCustomerRouter",
|
||||
RouterGroupName: "privateGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 InitFileUploadAndDownloadRouter 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "router_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router"`,
|
||||
AppName: "RouterGroupApp",
|
||||
GroupName: "Example",
|
||||
ModuleName: "exampleRouter",
|
||||
PackageName: "router",
|
||||
FunctionName: "InitFileUploadAndDownloadRouter",
|
||||
RouterGroupName: "privateGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageInitializeRouter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
FunctionName: tt.fields.FunctionName,
|
||||
RouterGroupName: tt.fields.RouterGroupName,
|
||||
LeftRouterGroupName: "privateGroup",
|
||||
RightRouterGroupName: "publicGroup",
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageInitializeRouter_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
AppName string
|
||||
GroupName string
|
||||
ModuleName string
|
||||
PackageName string
|
||||
FunctionName string
|
||||
RouterGroupName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
|
||||
{
|
||||
name: "测试 InitCustomerRouter 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "router_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router"`,
|
||||
AppName: "RouterGroupApp",
|
||||
GroupName: "Example",
|
||||
ModuleName: "exampleRouter",
|
||||
PackageName: "router",
|
||||
FunctionName: "InitCustomerRouter",
|
||||
RouterGroupName: "privateGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 InitFileUploadAndDownloadRouter 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "initialize", "router_biz.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/router"`,
|
||||
AppName: "RouterGroupApp",
|
||||
GroupName: "Example",
|
||||
ModuleName: "exampleRouter",
|
||||
PackageName: "router",
|
||||
FunctionName: "InitFileUploadAndDownloadRouter",
|
||||
RouterGroupName: "privateGroup",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageInitializeRouter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
FunctionName: tt.fields.FunctionName,
|
||||
RouterGroupName: tt.fields.RouterGroupName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"go/ast"
|
||||
"go/token"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PackageModuleEnter 模块化入口
|
||||
// ModuleName := PackageName.AppName.GroupName.ServiceName
|
||||
type PackageModuleEnter struct {
|
||||
Base
|
||||
Type Type // 类型
|
||||
Path string // 文件路径
|
||||
ImportPath string // 导包路径
|
||||
RelativePath string // 相对路径
|
||||
StructName string // 结构体名称
|
||||
AppName string // 应用名称
|
||||
GroupName string // 分组名称
|
||||
ModuleName string // 模块名称
|
||||
PackageName string // 包名
|
||||
ServiceName string // 服务名称
|
||||
}
|
||||
|
||||
func (a *PackageModuleEnter) Parse(filename string, writer io.Writer) (file *ast.File, err error) {
|
||||
if filename == "" {
|
||||
if a.RelativePath == "" {
|
||||
filename = a.Path
|
||||
a.RelativePath = a.Base.RelativePath(a.Path)
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
a.Path = a.Base.AbsolutePath(a.RelativePath)
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Parse(filename, writer)
|
||||
}
|
||||
|
||||
func (a *PackageModuleEnter) Rollback(file *ast.File) error {
|
||||
for i := 0; i < len(file.Decls); i++ {
|
||||
v1, o1 := file.Decls[i].(*ast.GenDecl)
|
||||
if o1 {
|
||||
for j := 0; j < len(v1.Specs); j++ {
|
||||
v2, o2 := v1.Specs[j].(*ast.TypeSpec)
|
||||
if o2 {
|
||||
if v2.Name.Name != a.Type.Group() {
|
||||
continue
|
||||
}
|
||||
v3, o3 := v2.Type.(*ast.StructType)
|
||||
if o3 {
|
||||
for k := 0; k < len(v3.Fields.List); k++ {
|
||||
v4, o4 := v3.Fields.List[k].Type.(*ast.Ident)
|
||||
if o4 && v4.Name == a.StructName {
|
||||
v3.Fields.List = append(v3.Fields.List[:k], v3.Fields.List[k+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
if a.Type == TypePackageServiceModuleEnter {
|
||||
continue
|
||||
}
|
||||
v3, o3 := v1.Specs[j].(*ast.ValueSpec)
|
||||
if o3 {
|
||||
if len(v3.Names) == 1 && v3.Names[0].Name == a.ModuleName {
|
||||
v1.Specs = append(v1.Specs[:j], v1.Specs[j+1:]...)
|
||||
}
|
||||
}
|
||||
if v1.Tok == token.VAR && len(v1.Specs) == 0 {
|
||||
_ = NewImport(a.ImportPath).Rollback(file)
|
||||
if i == len(file.Decls) {
|
||||
file.Decls = append(file.Decls[:i-1])
|
||||
break
|
||||
} // 空的var(), 如果不删除则会影响的注入变量, 因为识别不到*ast.ValueSpec
|
||||
file.Decls = append(file.Decls[:i], file.Decls[i+1:]...)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageModuleEnter) Injection(file *ast.File) error {
|
||||
_ = NewImport(a.ImportPath).Injection(file)
|
||||
var hasValue bool
|
||||
var hasVariables bool
|
||||
for i := 0; i < len(file.Decls); i++ {
|
||||
v1, o1 := file.Decls[i].(*ast.GenDecl)
|
||||
if o1 {
|
||||
if v1.Tok == token.VAR {
|
||||
hasVariables = true
|
||||
}
|
||||
for j := 0; j < len(v1.Specs); j++ {
|
||||
if a.Type == TypePackageServiceModuleEnter {
|
||||
hasValue = true
|
||||
}
|
||||
v2, o2 := v1.Specs[j].(*ast.TypeSpec)
|
||||
if o2 {
|
||||
if v2.Name.Name != a.Type.Group() {
|
||||
continue
|
||||
}
|
||||
v3, o3 := v2.Type.(*ast.StructType)
|
||||
if o3 {
|
||||
var hasStruct bool
|
||||
for k := 0; k < len(v3.Fields.List); k++ {
|
||||
v4, o4 := v3.Fields.List[k].Type.(*ast.Ident)
|
||||
if o4 && v4.Name == a.StructName {
|
||||
hasStruct = true
|
||||
}
|
||||
}
|
||||
if !hasStruct {
|
||||
field := &ast.Field{Type: &ast.Ident{Name: a.StructName}}
|
||||
v3.Fields.List = append(v3.Fields.List, field)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
v3, o3 := v1.Specs[j].(*ast.ValueSpec)
|
||||
if o3 {
|
||||
hasVariables = true
|
||||
if len(v3.Names) == 1 && v3.Names[0].Name == a.ModuleName {
|
||||
hasValue = true
|
||||
}
|
||||
}
|
||||
if v1.Tok == token.VAR && len(v1.Specs) == 0 {
|
||||
hasVariables = false
|
||||
} // 说明是空var()
|
||||
if hasVariables && !hasValue {
|
||||
spec := &ast.ValueSpec{
|
||||
Names: []*ast.Ident{{Name: a.ModuleName}},
|
||||
Values: []ast.Expr{
|
||||
&ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: a.PackageName},
|
||||
Sel: &ast.Ident{Name: a.AppName},
|
||||
},
|
||||
Sel: &ast.Ident{Name: a.GroupName},
|
||||
},
|
||||
Sel: &ast.Ident{Name: a.ServiceName},
|
||||
},
|
||||
},
|
||||
}
|
||||
v1.Specs = append(v1.Specs, spec)
|
||||
hasValue = true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if !hasValue && !hasVariables {
|
||||
decl := &ast.GenDecl{
|
||||
Tok: token.VAR,
|
||||
Specs: []ast.Spec{
|
||||
&ast.ValueSpec{
|
||||
Names: []*ast.Ident{{Name: a.ModuleName}},
|
||||
Values: []ast.Expr{
|
||||
&ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.SelectorExpr{
|
||||
X: &ast.Ident{Name: a.PackageName},
|
||||
Sel: &ast.Ident{Name: a.AppName},
|
||||
},
|
||||
Sel: &ast.Ident{Name: a.GroupName},
|
||||
},
|
||||
Sel: &ast.Ident{Name: a.ServiceName},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
file.Decls = append(file.Decls, decl)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *PackageModuleEnter) Format(filename string, writer io.Writer, file *ast.File) error {
|
||||
if filename == "" {
|
||||
filename = a.Path
|
||||
}
|
||||
return a.Base.Format(filename, writer, file)
|
||||
}
|
||||
@@ -1,185 +0,0 @@
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPackageModuleEnter_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
AppName string
|
||||
GroupName string
|
||||
ModuleName string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadRouter 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageRouterModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "router", "example", "enter.go"),
|
||||
ImportPath: `api "git.echol.cn/loser/Go-Web-Template/server/api/v1"`,
|
||||
StructName: "FileUploadAndDownloadRouter",
|
||||
AppName: "ApiGroupApp",
|
||||
GroupName: "ExampleApiGroup",
|
||||
ModuleName: "exaFileUploadAndDownloadApi",
|
||||
PackageName: "api",
|
||||
ServiceName: "FileUploadAndDownloadApi",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadApi 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageApiModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", "example", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/service"`,
|
||||
StructName: "FileUploadAndDownloadApi",
|
||||
AppName: "ServiceGroupApp",
|
||||
GroupName: "ExampleServiceGroup",
|
||||
ModuleName: "fileUploadAndDownloadService",
|
||||
PackageName: "service",
|
||||
ServiceName: "FileUploadAndDownloadService",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadService 回滚",
|
||||
fields: fields{
|
||||
Type: TypePackageServiceModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", "example", "enter.go"),
|
||||
ImportPath: ``,
|
||||
StructName: "FileUploadAndDownloadService",
|
||||
AppName: "",
|
||||
GroupName: "",
|
||||
ModuleName: "",
|
||||
PackageName: "",
|
||||
ServiceName: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageModuleEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
ServiceName: tt.fields.ServiceName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPackageModuleEnter_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
AppName string
|
||||
GroupName string
|
||||
ModuleName string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadRouter 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageRouterModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "router", "example", "enter.go"),
|
||||
ImportPath: `api "git.echol.cn/loser/Go-Web-Template/server/api/v1"`,
|
||||
StructName: "FileUploadAndDownloadRouter",
|
||||
AppName: "ApiGroupApp",
|
||||
GroupName: "ExampleApiGroup",
|
||||
ModuleName: "exaFileUploadAndDownloadApi",
|
||||
PackageName: "api",
|
||||
ServiceName: "FileUploadAndDownloadApi",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadApi 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageApiModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "api", "v1", "example", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/service"`,
|
||||
StructName: "FileUploadAndDownloadApi",
|
||||
AppName: "ServiceGroupApp",
|
||||
GroupName: "ExampleServiceGroup",
|
||||
ModuleName: "fileUploadAndDownloadService",
|
||||
PackageName: "service",
|
||||
ServiceName: "FileUploadAndDownloadService",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 FileUploadAndDownloadService 注入",
|
||||
fields: fields{
|
||||
Type: TypePackageServiceModuleEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "service", "example", "enter.go"),
|
||||
ImportPath: ``,
|
||||
StructName: "FileUploadAndDownloadService",
|
||||
AppName: "",
|
||||
GroupName: "",
|
||||
ModuleName: "",
|
||||
PackageName: "",
|
||||
ServiceName: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PackageModuleEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
ServiceName: tt.fields.ServiceName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
//go:build legacy_plugin_ast
|
||||
// +build legacy_plugin_ast
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPluginEnter_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
StructCamelName string
|
||||
ModuleName string
|
||||
GroupName string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件UserApi 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginApiEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "api", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/service"`,
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "serviceUser",
|
||||
GroupName: "Service",
|
||||
PackageName: "service",
|
||||
ServiceName: "User",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 Gva插件UserRouter 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginRouterEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "router", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/api"`,
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "userApi",
|
||||
GroupName: "Api",
|
||||
PackageName: "api",
|
||||
ServiceName: "User",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 Gva插件UserService 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginServiceEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "service", "enter.go"),
|
||||
ImportPath: "",
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "",
|
||||
GroupName: "",
|
||||
PackageName: "",
|
||||
ServiceName: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 gva的User 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginServiceEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "service", "enter.go"),
|
||||
ImportPath: "",
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "",
|
||||
GroupName: "",
|
||||
PackageName: "",
|
||||
ServiceName: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
StructCamelName: tt.fields.StructCamelName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
ServiceName: tt.fields.ServiceName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginEnter_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
StructCamelName string
|
||||
ModuleName string
|
||||
GroupName string
|
||||
PackageName string
|
||||
ServiceName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件UserRouter 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginRouterEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "router", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/api"`,
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "userApi",
|
||||
GroupName: "Api",
|
||||
PackageName: "api",
|
||||
ServiceName: "User",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 Gva插件UserApi 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginApiEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "api", "enter.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/service"`,
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "serviceUser",
|
||||
GroupName: "Service",
|
||||
PackageName: "service",
|
||||
ServiceName: "User",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 Gva插件UserService 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginServiceEnter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "service", "enter.go"),
|
||||
ImportPath: "",
|
||||
StructName: "User",
|
||||
StructCamelName: "user",
|
||||
ModuleName: "",
|
||||
GroupName: "",
|
||||
PackageName: "",
|
||||
ServiceName: "",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginEnter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
StructCamelName: tt.fields.StructCamelName,
|
||||
ModuleName: tt.fields.ModuleName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
ServiceName: tt.fields.ServiceName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,130 +0,0 @@
|
||||
//go:build legacy_plugin_ast
|
||||
// +build legacy_plugin_ast
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPluginGenModel_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
PackageName string
|
||||
StructName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 GvaUser 结构体注入",
|
||||
fields: fields{
|
||||
Type: TypePluginGen,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "gen", "main.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
PackageName: "model",
|
||||
StructName: "User",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 GvaUser 结构体注入",
|
||||
fields: fields{
|
||||
Type: TypePluginGen,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "gen", "main.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
PackageName: "model",
|
||||
StructName: "User",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginGen{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
PackageName: tt.fields.PackageName,
|
||||
StructName: tt.fields.StructName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginGenModel_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
PackageName string
|
||||
StructName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 GvaUser 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginGen,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "gen", "main.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
PackageName: "model",
|
||||
StructName: "User",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 GvaUser 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginGen,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "gen", "main.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
PackageName: "model",
|
||||
StructName: "User",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginGen{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
PackageName: tt.fields.PackageName,
|
||||
StructName: tt.fields.StructName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,141 +0,0 @@
|
||||
//go:build legacy_plugin_ast
|
||||
// +build legacy_plugin_ast
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPluginInitializeGorm_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 &model.User{} 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "gorm.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
StructName: "User",
|
||||
PackageName: "model",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(model.ExaCustomer) 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "gorm.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
StructName: "User",
|
||||
PackageName: "model",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(model.SysUsers) 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "gorm.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
StructName: "SysUser",
|
||||
PackageName: "model",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginInitializeGorm{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginInitializeGorm_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
StructName string
|
||||
PackageName string
|
||||
IsNew bool
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 &model.User{} 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "gorm.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
StructName: "User",
|
||||
PackageName: "model",
|
||||
IsNew: false,
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "测试 new(model.ExaCustomer) 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeGorm,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "gorm.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/model"`,
|
||||
StructName: "User",
|
||||
PackageName: "model",
|
||||
IsNew: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginInitializeGorm{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: tt.fields.StructName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
IsNew: tt.fields.IsNew,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,158 +0,0 @@
|
||||
//go:build legacy_plugin_ast
|
||||
// +build legacy_plugin_ast
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPluginInitializeRouter_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
AppName string
|
||||
GroupName string
|
||||
PackageName string
|
||||
FunctionName string
|
||||
LeftRouterGroupName string
|
||||
RightRouterGroupName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件User 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "router.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/router"`,
|
||||
AppName: "Router",
|
||||
GroupName: "User",
|
||||
PackageName: "router",
|
||||
FunctionName: "Init",
|
||||
LeftRouterGroupName: "public",
|
||||
RightRouterGroupName: "private",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 中文 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "router.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/router"`,
|
||||
AppName: "Router",
|
||||
GroupName: "U中文",
|
||||
PackageName: "router",
|
||||
FunctionName: "Init",
|
||||
LeftRouterGroupName: "public",
|
||||
RightRouterGroupName: "private",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginInitializeRouter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
FunctionName: tt.fields.FunctionName,
|
||||
LeftRouterGroupName: tt.fields.LeftRouterGroupName,
|
||||
RightRouterGroupName: tt.fields.RightRouterGroupName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginInitializeRouter_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
ImportPath string
|
||||
AppName string
|
||||
GroupName string
|
||||
PackageName string
|
||||
FunctionName string
|
||||
LeftRouterGroupName string
|
||||
RightRouterGroupName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件User 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "router.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/router"`,
|
||||
AppName: "Router",
|
||||
GroupName: "User",
|
||||
PackageName: "router",
|
||||
FunctionName: "Init",
|
||||
LeftRouterGroupName: "public",
|
||||
RightRouterGroupName: "private",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "测试 中文 注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeRouter,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "initialize", "router.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva/router"`,
|
||||
AppName: "Router",
|
||||
GroupName: "U中文",
|
||||
PackageName: "router",
|
||||
FunctionName: "Init",
|
||||
LeftRouterGroupName: "public",
|
||||
RightRouterGroupName: "private",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := &PluginInitializeRouter{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
AppName: tt.fields.AppName,
|
||||
GroupName: tt.fields.GroupName,
|
||||
PackageName: tt.fields.PackageName,
|
||||
FunctionName: tt.fields.FunctionName,
|
||||
LeftRouterGroupName: tt.fields.LeftRouterGroupName,
|
||||
RightRouterGroupName: tt.fields.RightRouterGroupName,
|
||||
}
|
||||
file, err := a.Parse(a.Path, nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format(a.Path, nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -1,103 +0,0 @@
|
||||
//go:build legacy_plugin_ast
|
||||
// +build legacy_plugin_ast
|
||||
|
||||
package ast
|
||||
|
||||
import (
|
||||
"git.echol.cn/loser/Go-Web-Template/server/global"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestPluginInitialize_Injection(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
PluginPath string
|
||||
ImportPath string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件 注册注入",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeV2,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "plugin.go"),
|
||||
PluginPath: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "register.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva"`,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := PluginInitializeV2{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
PluginPath: tt.fields.PluginPath,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
}
|
||||
file, err := a.Parse("", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Injection(file)
|
||||
err = a.Format("", nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Injection() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestPluginInitialize_Rollback(t *testing.T) {
|
||||
type fields struct {
|
||||
Type Type
|
||||
Path string
|
||||
PluginPath string
|
||||
ImportPath string
|
||||
PluginName string
|
||||
StructName string
|
||||
PackageName string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
fields fields
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "测试 Gva插件 回滚",
|
||||
fields: fields{
|
||||
Type: TypePluginInitializeV2,
|
||||
Path: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "gva", "plugin.go"),
|
||||
PluginPath: filepath.Join(global.GVA_CONFIG.AutoCode.Root, global.GVA_CONFIG.AutoCode.Server, "plugin", "register.go"),
|
||||
ImportPath: `"git.echol.cn/loser/Go-Web-Template/server/plugin/gva"`,
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
a := PluginInitializeV2{
|
||||
Type: tt.fields.Type,
|
||||
Path: tt.fields.Path,
|
||||
PluginPath: tt.fields.PluginPath,
|
||||
ImportPath: tt.fields.ImportPath,
|
||||
StructName: "Plugin",
|
||||
PackageName: "gva",
|
||||
}
|
||||
file, err := a.Parse("", nil)
|
||||
if err != nil {
|
||||
t.Errorf("Parse() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
a.Rollback(file)
|
||||
err = a.Format("", nil, file)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("Rollback() error = %v, wantErr %v", err, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user