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  }