diff --git a/extract/extract.go b/extract/extract.go index 85f2e0422..63ebcb121 100644 --- a/extract/extract.go +++ b/extract/extract.go @@ -23,6 +23,8 @@ import ( "strconv" "strings" "text/template" + + "golang.org/x/tools/go/packages" ) const model = `// Code generated by 'yaegi extract {{.ImportPath}}'. DO NOT EDIT. @@ -447,16 +449,44 @@ func (e *Extractor) Extract(pkgIdent, importPath string, rw io.Writer) (string, return "", err } - pkg, err := importer.ForCompiler(token.NewFileSet(), "source", nil).Import(pkgIdent) - if err != nil { - return "", err + var pkg *types.Package + isRelative := strings.HasPrefix(pkgIdent, ".") + // If we are relative with a manual import path, we cannot use modules + // and must fall back on the standard go/importer loader. + if isRelative && importPath != "" { + pkg, err = importer.ForCompiler(token.NewFileSet(), "source", nil).Import(pkgIdent) + if err != nil { + return "", err + } + } else { + // Otherwise, we can use the much faster x/tools/go/packages loader. + if isRelative { + // We must be in the location of the module for the loader to work correctly. + err := os.Chdir(pkgIdent) + if err != nil { + return "", err + } + // Our path must point back to ourself here. + pkgIdent = filepath.Join("..", filepath.Base(pkgIdent)) + } + pkgs, err := packages.Load(&packages.Config{Mode: packages.NeedTypes}, pkgIdent) + if err != nil { + return "", err + } + if len(pkgs) != 1 { + return "", fmt.Errorf("expected one package, got %d", len(pkgs)) + } + ppkg := pkgs[0] + if len(ppkg.Errors) > 0 { + return "", ppkg.Errors[0] + } + pkg = ppkg.Types } content, err := e.genContent(ipp, pkg) if err != nil { return "", err } - if _, err := rw.Write(content); err != nil { return "", err } diff --git a/go.mod b/go.mod index e8cc07765..c093c494f 100644 --- a/go.mod +++ b/go.mod @@ -1,3 +1,10 @@ module github.com/traefik/yaegi go 1.21 + +require golang.org/x/tools v0.22.0 + +require ( + golang.org/x/mod v0.18.0 // indirect + golang.org/x/sync v0.7.0 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 000000000..16f2f692e --- /dev/null +++ b/go.sum @@ -0,0 +1,6 @@ +golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0= +golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA= +golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=