github.com/unionj-cloud/go-doudou/v2@v2.3.5/toolkit/gormgen/internal/parser/export.go (about) 1 package parser 2 3 import ( 4 "fmt" 5 "go/build" 6 "os" 7 "path/filepath" 8 "reflect" 9 "runtime" 10 "strings" 11 ) 12 13 // InterfacePath interface path 14 type InterfacePath struct { 15 Name string 16 FullName string 17 Files []string 18 Package string 19 } 20 21 // GetInterfacePath get interface's directory path and all files it contains 22 func GetInterfacePath(v interface{}) (paths []*InterfacePath, err error) { 23 value := reflect.ValueOf(v) 24 if value.Kind() != reflect.Func { 25 err = fmt.Errorf("model param is not function:%s", value.String()) 26 return 27 } 28 29 for i := 0; i < value.Type().NumIn(); i++ { 30 var path InterfacePath 31 arg := value.Type().In(i) 32 path.FullName = arg.String() 33 34 // keep the last model 35 for _, n := range strings.Split(arg.String(), ".") { 36 path.Name = n 37 } 38 39 ctx := build.Default 40 var p *build.Package 41 42 if strings.Split(arg.String(), ".")[0] == "main" { 43 _, file, _, _ := runtime.Caller(3) 44 p, err = ctx.ImportDir(filepath.Dir(file), build.ImportComment) 45 } else { 46 p, err = ctx.Import(arg.PkgPath(), "", build.ImportComment) 47 } 48 49 if err != nil { 50 return 51 } 52 53 for _, file := range p.GoFiles { 54 goFile := fmt.Sprintf("%s/%s", p.Dir, file) 55 if fileExists(goFile) { 56 path.Files = append(path.Files, goFile) 57 } 58 } 59 60 if len(path.Files) == 0 { 61 err = fmt.Errorf("interface file not found:%s", value.String()) 62 return 63 } 64 65 paths = append(paths, &path) 66 } 67 68 return 69 } 70 71 func fileExists(path string) bool { 72 _, err := os.Stat(path) 73 return err == nil 74 } 75 76 // GetModelMethod get diy methods 77 func GetModelMethod(v interface{}, skip int) (method *DIYMethods, err error) { 78 method = new(DIYMethods) 79 80 // get diy method info by input value, must input a function or a struct 81 value := reflect.ValueOf(v) 82 switch value.Kind() { 83 case reflect.Func: 84 fullPath := runtime.FuncForPC(value.Pointer()).Name() 85 err = method.parserPath(fullPath) 86 if err != nil { 87 return nil, err 88 } 89 case reflect.Struct: 90 method.pkgPath = value.Type().PkgPath() 91 method.BaseStructType = value.Type().Name() 92 default: 93 return nil, fmt.Errorf("method param must be a function or struct") 94 } 95 96 var p *build.Package 97 98 // if struct in main file 99 ctx := build.Default 100 if method.pkgPath == "main" { 101 _, file, _, _ := runtime.Caller(skip) 102 p, err = ctx.ImportDir(filepath.Dir(file), build.ImportComment) 103 } else { 104 p, err = ctx.Import(method.pkgPath, "", build.ImportComment) 105 } 106 if err != nil { 107 return nil, fmt.Errorf("diy method dir not found:%s.%s %w", method.pkgPath, method.MethodName, err) 108 } 109 110 for _, file := range p.GoFiles { 111 goFile := p.Dir + "/" + file 112 if fileExists(goFile) { 113 method.pkgFiles = append(method.pkgFiles, goFile) 114 } 115 } 116 if len(method.pkgFiles) == 0 { 117 return nil, fmt.Errorf("diy method file not found:%s.%s", method.pkgPath, method.MethodName) 118 } 119 120 // read files got methods 121 return method, method.LoadMethods() 122 }