Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,43 @@ require (
github.com/BurntSushi/toml v1.2.1 // indirect
github.com/btcsuite/btcd/btcec/v2 v2.3.4 // indirect
github.com/btcsuite/btcd/btcutil v1.1.6 // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/cockroachdb/apd/v3 v3.2.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/gofrs/flock v0.12.1 // indirect
github.com/google/safehtml v0.1.0 // indirect
github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.25.1 // indirect
github.com/libp2p/go-buffer-pool v0.1.0 // indirect
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/xid v1.6.0 // indirect
github.com/sig-0/insertion-queue v0.0.0-20241004125609-6b3ca841346b // indirect
github.com/stretchr/testify v1.10.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
go.opentelemetry.io/otel v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v1.34.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v1.34.0 // indirect
go.opentelemetry.io/otel/metric v1.34.0 // indirect
go.opentelemetry.io/otel/sdk v1.34.0 // indirect
go.opentelemetry.io/otel/sdk/metric v1.34.0 // indirect
go.opentelemetry.io/otel/trace v1.34.0 // indirect
go.opentelemetry.io/proto/otlp v1.5.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/crypto v0.40.0 // indirect
golang.org/x/exp v0.0.0-20240613232115-7f521ea00fb8 // indirect
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 // indirect
golang.org/x/net v0.42.0 // indirect
golang.org/x/tools/go/packages/packagestest v0.1.1-deprecated // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20250115164207-1a7da9e5054f // indirect
google.golang.org/grpc v1.69.4 // indirect
google.golang.org/protobuf v1.36.3 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
)

replace github.com/gnolang/gno => github.com/n0izn0iz/gno v0.1.2-0.20250920103332-3549e304804d
12 changes: 7 additions & 5 deletions go.sum
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s=
dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk=
github.com/BurntSushi/toml v1.2.1 h1:9F2/+DoOYIOksmaJFPw1tGFy1eDnIJXg+UHjuD8lTak=
github.com/BurntSushi/toml v1.2.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
github.com/DataDog/zstd v1.4.5 h1:EndNeuB0l9syBZhut0wns3gV1hL8zX8LIu6ZiVHWLIQ=
Expand Down Expand Up @@ -61,12 +63,13 @@ github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1/go.mod h1:hyedUtir6IdtD/7lIxGeC
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
github.com/decred/dcrd/lru v1.0.0/go.mod h1:mxKOwFd7lFjN2GZYsiz/ecgqR6kkYAl+0pz0tEMk218=
github.com/fortytw2/leaktest v1.3.0 h1:u8491cBMTQ8ft8aeV+adlcytMZylmA5nnwwkRZjI8vw=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/getsentry/sentry-go v0.27.0 h1:Pv98CIbtB3LkMWmXi4Joa5OOcwbmnX88sF5qbK3r3Ps=
github.com/getsentry/sentry-go v0.27.0/go.mod h1:lc76E2QywIyW8WuBnwl8Lc4bkmQH4+w1gwTf25trprY=
github.com/gnolang/gno v0.0.0-20250911110843-956c0ddde9af h1:kJqIlHX1gdSwa6cT4Hm24+tAv5RTI/j/Gc9sxEeFxns=
github.com/gnolang/gno v0.0.0-20250911110843-956c0ddde9af/go.mod h1:j9wKq29meqwktEj2ReqPbSkeYUwoisfxHHVeV20lhtw=
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
Expand Down Expand Up @@ -113,11 +116,8 @@ github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlT
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/klauspost/compress v1.16.0 h1:iULayQNOReoYUe+1qtKOqw9CwJv3aNQu8ivo7lw1HU4=
github.com/klauspost/compress v1.16.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lib/pq v1.10.7 h1:p7ZhMD+KsSRozJr34udlUrhboJwWAgCg34+/ZZNvZZw=
Expand All @@ -126,6 +126,8 @@ github.com/libp2p/go-buffer-pool v0.1.0 h1:oK4mSFcQz7cTQIfqbe4MIj9gLW+mnanjyFtc6
github.com/libp2p/go-buffer-pool v0.1.0/go.mod h1:N+vh8gMqimBzdKkSMVuydVDq+UV5QTWy5HSiZacSbPg=
github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo=
github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/n0izn0iz/gno v0.1.2-0.20250920103332-3549e304804d h1:L9rznI/rbHWmMMKem+Yz+okxmq2HSu++c/8Ec/csKo0=
github.com/n0izn0iz/gno v0.1.2-0.20250920103332-3549e304804d/go.mod h1:j9wKq29meqwktEj2ReqPbSkeYUwoisfxHHVeV20lhtw=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
Expand Down
169 changes: 107 additions & 62 deletions pkg/resolver/driver.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"strings"

"github.com/gnolang/gno/gnovm/pkg/gnoenv"
"github.com/gnolang/gno/gnovm/pkg/gnolang"
gnopackages "github.com/gnolang/gno/gnovm/pkg/packages"
"github.com/gnoverse/gnopls/internal/packages"
"github.com/gnoverse/gnopls/pkg/eventlogger"
)
Expand All @@ -21,29 +23,51 @@ func Resolve(req *packages.DriverRequest, patterns ...string) (*packages.DriverR
"tests", req.Tests,
"build-flags", req.BuildFlags,
"overlay", req.Overlay,
"patterns", patterns,
)

// Inject examples
requireBuiltin := false
loaderPatterns := []string{}
for _, pattern := range patterns {
// XXX: better support file pattern
if strings.HasPrefix(pattern, "file=") {
dir, _ := filepath.Split(pattern)
dir = strings.TrimPrefix(dir, "file=")
gnomodsRes, err := listPackagesPath(dir)
if err != nil {
logger.Error("failed to get pkg", slog.String("error", err.Error()))
return nil, err
}
if len(gnomodsRes) != 1 {
logger.Warn("unexpected number of packages",
slog.String("arg", pattern),
slog.Int("count", len(gnomodsRes)),
)
}
loaderPatterns = append(loaderPatterns, gnomodsRes...)
continue
} else if pattern == "builtin" {
requireBuiltin = true
continue
}

gnoRoot, err := gnoenv.GuessRootDir()
if err != nil {
logger.Warn("can't find gno root, examples and std packages are ignored", slog.String("error", err.Error()))
loaderPatterns = append(loaderPatterns, pattern)
}

targets := patterns
res := packages.DriverResponse{}

if gnoRoot != "" {
targets = append(targets, filepath.Join(gnoRoot, "examples", "..."))
findGoPkg := func(pkgpath string) *packages.Package {
for _, pkg := range res.Packages {
if pkg != nil && pkg.PkgPath == pkgpath {
return pkg
}
}
return nil
}

pkgsCache := map[string]*packages.Package{}
res := packages.DriverResponse{}

// Inject gnobuiltin
if pkg, err := getBuiltinPkg(); err == nil {
pkgsCache[pkg.Name] = pkg
res.Packages = append(res.Packages, pkg)
res.Roots = append(res.Roots, pkg.ID)
gnoRoot, err := gnoenv.GuessRootDir()
if err != nil {
logger.Warn("can't find gno root, examples and std packages are ignored", slog.String("error", err.Error()))
}

// Inject stdlibs
Expand All @@ -59,6 +83,10 @@ func Resolve(req *packages.DriverRequest, patterns ...string) (*packages.DriverR
return nil
}

if path == "." {
return nil
}

pkgDir := filepath.Join(libsRoot, path)

pkgs := readPkg(req, pkgDir, path, logger)
Expand All @@ -68,9 +96,6 @@ func Resolve(req *packages.DriverRequest, patterns ...string) (*packages.DriverR
}

res.Packages = append(res.Packages, pkg)
if !strings.HasSuffix(pkg.Name, "_test") {
pkgsCache[path] = pkg
}

testLibDir := filepath.Join(testLibsRoot, path)
testsDir, err := os.ReadDir(testLibDir)
Expand Down Expand Up @@ -106,62 +131,82 @@ func Resolve(req *packages.DriverRequest, patterns ...string) (*packages.DriverR
}); err != nil {
logger.Warn("failed to inject all stdlibs", slog.String("error", err.Error()))
}
}

// Discover packages

pkgpaths := []string{}
for _, target := range targets {
dir, file := filepath.Split(target)
if file == "..." {
gnomodsRes, err := listPackagesPath(dir)
// inject tests libs
if err := fs.WalkDir(os.DirFS(testLibsRoot), ".", func(path string, d fs.DirEntry, err error) error {
if err != nil {
logger.Error("failed to get pkg list", slog.String("error", err.Error()))
return nil, err
}
pkgpaths = append(pkgpaths, gnomodsRes...)
} else if strings.HasPrefix(target, "file=") {
dir = strings.TrimPrefix(dir, "file=")
gnomodsRes, err := listPackagesPath(dir)
if err != nil {
logger.Error("failed to get pkg", slog.String("error", err.Error()))
return nil, err
return nil
}
if len(gnomodsRes) != 1 {
logger.Warn("unexpected number of packages",
slog.String("arg", target),
slog.Int("count", len(gnomodsRes)),
)

if !d.IsDir() {
return nil
}
pkgpaths = append(pkgpaths, gnomodsRes...)
} else {
logger.Warn("unknown arg shape", slog.String("value", target))
}
}
logger.Info("discovered packages", slog.Int("count", len(pkgpaths)+len(res.Packages)))

// Convert packages
if path == "." {
return nil
}

for _, gnomodPath := range pkgpaths {
pkgs := gnoPkgToGo(req, gnomodPath, logger)
for _, pkg := range pkgs {
if pkg == nil {
logger.Error("failed to convert gno pkg to go pkg", slog.String("gnomod", gnomodPath))
continue
if slices.ContainsFunc(res.Packages, func(p *packages.Package) bool { return p.PkgPath == path }) {
return nil
}
if _, ok := pkgsCache[pkg.PkgPath]; ok {
// ignore duplicates in later targets, mostly useful to ignore examples present in explicit targets
logger.Debug("ignored duplicate", slog.String("pkg-path", pkg.PkgPath), slog.String("new", gnomodPath))
continue

pkgDir := filepath.Join(testLibsRoot, path)

pkgs := readPkg(req, pkgDir, path, logger)
for _, pkg := range pkgs {
if len(pkg.GoFiles) == 0 {
continue
}

res.Packages = append(res.Packages, pkg)

}

// logger.Info("injected stdlib", slog.String("path", pkg.PkgPath), slog.String("name", pkg.Name))

return nil
}); err != nil {
logger.Warn("failed to inject all tests stdlibs", slog.String("error", err.Error()))
}
}

if requireBuiltin {
// Inject gnobuiltin
if pkg, err := getBuiltinPkg(); err == nil {
res.Packages = append(res.Packages, pkg)
res.Roots = append(res.Roots, pkg.ID)
if !strings.HasSuffix(pkg.Name, "_test") {
pkgsCache[pkg.PkgPath] = pkg
}
}

loadCfg := gnopackages.LoadConfig{
Test: req.Tests,
Out: os.Stderr,
Deps: true,
GnoRoot: gnoRoot,
// Overlay: req.Overlay,
}
loadedPkgs, err := gnopackages.Load(loadCfg, loaderPatterns...)
if err != nil {
return nil, err
}

// Convert packages

for _, gnopkg := range loadedPkgs {
if gnolang.IsStdlib(gnopkg.ImportPath) {
continue
}
pkgs := gnoPkgToGo(req, gnopkg, logger)
res.Packages = append(res.Packages, pkgs...)
if len(gnopkg.Match) != 0 {
for _, pkg := range pkgs {
res.Roots = append(res.Roots, pkg.ID)
}
}
}

logger.Info("discovered packages", slog.Int("count", len(res.Packages)))

// Resolve imports

for _, pkg := range res.Packages {
Expand All @@ -171,8 +216,8 @@ func Resolve(req *packages.DriverRequest, patterns ...string) (*packages.DriverR

toDelete := []string{}
for importPath := range pkg.Imports {
imp, ok := pkgsCache[importPath]
if ok {
imp := findGoPkg(importPath)
if imp != nil {
pkg.Imports[importPath] = imp
// logger.Info("found import", slog.String("path", importPath))
continue
Expand Down
10 changes: 5 additions & 5 deletions pkg/resolver/resolver.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,20 +13,20 @@ import (

"github.com/gnolang/gno/gnovm/pkg/gnolang"
"github.com/gnolang/gno/gnovm/pkg/gnomod"
gnopackages "github.com/gnolang/gno/gnovm/pkg/packages"
"github.com/gnoverse/gnopls/internal/packages"
"github.com/gnoverse/gnopls/pkg/gnotypes"
)

func gnoPkgToGo(req *packages.DriverRequest, path string, logger *slog.Logger) []*packages.Package {
mod, err := gnomod.ParseDir(path)
func gnoPkgToGo(req *packages.DriverRequest, pkg *gnopackages.Package, logger *slog.Logger) []*packages.Package {
mod, err := gnomod.ParseDir(pkg.Dir)
if err != nil {
logger.Error("failed to read mod file", "path", path, "err", err)
logger.Error("failed to read mod file", "path", pkg.Dir, "err", err)
return nil
}

// TODO: support subpkgs
module := mod.Module
return readPkg(req, path, module, logger)
return readPkg(req, pkg.Dir, module, logger)
}

// listPackagesPath recursively finds all gnomods at root
Expand Down