Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use x/tools/go/packages to significantly improve speed of extract code generation #1642

Open
wants to merge 10 commits into
base: master
Choose a base branch
from
38 changes: 34 additions & 4 deletions extract/extract.go
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
Expand Down
7 changes: 7 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
@@ -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
)
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
@@ -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=
Loading