Skip to content

Commit

Permalink
feat: support GNOSRCPATHS
Browse files Browse the repository at this point in the history
Signed-off-by: Norman Meier <[email protected]>
  • Loading branch information
n0izn0iz committed Jun 29, 2024
1 parent 02bac5b commit c8c1d49
Show file tree
Hide file tree
Showing 11 changed files with 109 additions and 4 deletions.
3 changes: 3 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ require (
github.com/gnolang/gno v0.0.0-20240118150545-7aa81d138701
github.com/google/go-github v17.0.0+incompatible
github.com/orcaman/concurrent-map/v2 v2.0.1
github.com/samber/slog-multi v1.1.0
github.com/spf13/cobra v1.5.0
go.lsp.dev/jsonrpc2 v0.10.0
go.lsp.dev/pkg v0.0.0-20210717090340-384b27a52fb2
Expand Down Expand Up @@ -47,6 +48,7 @@ require (
github.com/pelletier/go-toml v1.9.5 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/rs/cors v1.10.1 // indirect
github.com/samber/lo v1.38.1 // indirect
github.com/segmentio/asm v1.1.3 // indirect
github.com/segmentio/encoding v0.3.4 // indirect
github.com/spf13/pflag v1.0.5 // indirect
Expand All @@ -56,6 +58,7 @@ require (
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/zap v1.24.0 // indirect
golang.org/x/crypto v0.15.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/net v0.17.0 // indirect
golang.org/x/sys v0.14.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
Expand Down
6 changes: 6 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,10 @@ github.com/rs/cors v1.10.1 h1:L0uuZVXIKlI1SShY2nhFfo44TYvDPQ1w4oFkUJNfhyo=
github.com/rs/cors v1.10.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/samber/slog-multi v1.1.0 h1:m5wfpXE8Qu2gCiR/JnhFGsLcWDOmTxnso32EMffVAY0=
github.com/samber/slog-multi v1.1.0/go.mod h1:uLAvHpGqbYgX4FSL0p1ZwoLuveIAJvBECtE07XmYvFo=
github.com/segmentio/asm v1.1.3 h1:WM03sfUOENvvKexOLp+pCqgb/WDjsi7EK8gIsICtzhc=
github.com/segmentio/asm v1.1.3/go.mod h1:Ld3L4ZXGNcSLRg4JBsZ3//1+f/TjYl0Mzen/DQy1EJg=
github.com/segmentio/encoding v0.3.4 h1:WM4IBnxH8B9TakiM2QD5LyNl9JSndh88QbHqVC+Pauc=
Expand Down Expand Up @@ -239,6 +243,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
Expand Down
1 change: 1 addition & 0 deletions internal/lsp/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ func (s *server) TranspileAndBuild(file *GnoFile) ([]ErrorInfo, error) {
return nil, err
}

slog.Info("transpiling", slog.String("dir", tmpDir))
preOut, _ := tools.Transpile(tmpDir)
slog.Info(string(preOut))
if len(preOut) > 0 {
Expand Down
45 changes: 44 additions & 1 deletion internal/lsp/check.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ import (
"go/parser"
"go/token"
"go/types"
"io/fs"
"log/slog"
"math"
"os"
"path/filepath"
"regexp"
"sort"
"strconv"
"strings"
Expand Down Expand Up @@ -38,14 +40,55 @@ type PackageGetter interface {
// PackageInfo if found.
// Note: it doesn't work for relative path
func GetPackageInfo(path string) (*PackageInfo, error) {
//slog.Info("getting package info for", slog.String("path", path))
// if not absolute, assume its import path
if !filepath.IsAbs(path) {
if env.GlobalEnv.GNOROOT == "" {
// if GNOROOT is unknown, we can't locate the
// `examples` and `stdlibs`
return nil, errors.New("GNOROOT not set")
}
if strings.HasPrefix(path, "gno.land/") { // look in `examples`
if strings.HasPrefix(path, "gno.land/") { // look in gno `examples` and extra dirs
// find in extra dirs
srcPathsStr, ok := os.LookupEnv("GNOSRCPATHS")
//slog.Info("extra source paths", slog.String("env", srcPathsStr))
if ok {
srcPaths := strings.Split(srcPathsStr, ",")
for _, srcPath := range srcPaths {
modFiles := []string{}
if err := filepath.Walk(srcPath, func(path string, info fs.FileInfo, err error) error {
if !strings.HasSuffix(path, "/gno.mod") {
return nil
}
//slog.Info("found mod file", slog.String("path", path))
modFiles = append(modFiles, path)
return nil
}); err != nil {
return nil, err
}

for _, modFile := range modFiles {
modData, err := os.ReadFile(modFile)
if err != nil {
continue
}
re := regexp.MustCompile(`^module (.+)`)
res := re.FindSubmatch(modData)
if len(res) != 2 {
continue
}
pkgDir := strings.TrimSuffix(modFile, "/gno.mod")
pkgPath := string(res[1])
//slog.Info("found package", slog.String("path", pkgPath), slog.String("dir", pkgDir))
if pkgPath != path {
continue
}
//slog.Info("found correct package")
return getPackageInfo(pkgDir)
}
}
}

path = filepath.Join(env.GlobalEnv.GNOROOT, "examples", path)
} else { // look into `stdlibs`
path = filepath.Join(env.GlobalEnv.GNOROOT, "gnovm", "stdlibs", path)
Expand Down
3 changes: 3 additions & 0 deletions internal/lsp/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ func (cs *CompletionStore) lookupPkg(pkg string) *Package {
}

func (cs *CompletionStore) lookupSymbol(pkg, symbol string) *Symbol {
pnames := []string{}
for _, p := range cs.pkgs {
if p.Name == pkg {
for _, s := range p.Symbols {
Expand All @@ -49,7 +50,9 @@ func (cs *CompletionStore) lookupSymbol(pkg, symbol string) *Symbol {
}
}
}
pnames = append(pnames, p.Name)
}
slog.Info("pkg not found", "pkg", pkg, "symbol", symbol, "pkgs", pnames)
return nil
}

Expand Down
4 changes: 4 additions & 0 deletions internal/lsp/definition.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,17 @@ func (s *server) Definition(ctx context.Context, reply jsonrpc2.Replier, req jso
int(line),
offset,
)
slog.Info("node", "str", n.String(), "tv", tv)
if tv == nil || tv.Type == nil {
switch t := paths[1].(type) {
case *ast.FuncDecl:
slog.Info("func decl", "t", t)
if t.Recv != nil {
return definitionMethodDecl(ctx, reply, params, pkg, n, t)
}
return definitionFuncDecl(ctx, reply, params, pkg, n)
case *ast.SelectorExpr:
slog.Info("selector expr", "t", t)
return definitionSelectorExpr(ctx, s, reply, params, pgf, pkg, paths, n, t, int(line))
default:
return reply(ctx, nil, nil)
Expand Down Expand Up @@ -170,6 +173,7 @@ func definitionSelectorExpr(ctx context.Context, s *server, reply jsonrpc2.Repli
} else if last == parentStr { // on package symbol
symbol := s.completionStore.lookupSymbol(parentStr, i.Name)
if symbol == nil {
slog.Info("symbol not found", "parent", parentStr, "symbol", i.Name)
break
}

Expand Down
5 changes: 5 additions & 0 deletions internal/lsp/hover.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,17 +64,21 @@ func (s *server) Hover(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2
// Get path enclosing
paths := pathEnclosingObjNode(pgf.File, token.Pos(offset))
if len(paths) < 2 {
slog.Info("path not found", "pos", token.Pos(offset))
return reply(ctx, nil, nil)
}

switch n := paths[0].(type) {
case *ast.Ident:
slog.Info("ident type")

_, tv := getTypeAndValue(
*pkg.TypeCheckResult.fset,
info, n.Name,
int(line),
offset,
)
slog.Info("got tv", "tv", tv)
if tv == nil || tv.Type == nil {
switch t := paths[1].(type) {
case *ast.FuncDecl:
Expand Down Expand Up @@ -153,6 +157,7 @@ func (s *server) Hover(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2
),
}, nil)
default:
slog.Info("unknown type")
return reply(ctx, nil, nil)
}
}
Expand Down
1 change: 1 addition & 0 deletions internal/lsp/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func BuildServerHandler(conn jsonrpc2.Conn, e *env.Env) jsonrpc2.Handler {
if e.GNOROOT != "" {
dirs = append(dirs, filepath.Join(e.GNOROOT, "examples"))
dirs = append(dirs, filepath.Join(e.GNOROOT, "gnovm/stdlibs"))
dirs = append(dirs, os.Getenv("GNOSRCPATHS"))
}
server := &server{
conn: conn,
Expand Down
11 changes: 10 additions & 1 deletion internal/tools/build.go
Original file line number Diff line number Diff line change
@@ -1,12 +1,21 @@
package tools

import (
"log/slog"
"os"
"os/exec"
"path/filepath"
"strings"
)

// Build a Gno package: gno transpile -gobuild <dir>.
// TODO: Remove this in the favour of directly using tools/transpile.go
func Build(rootDir string) ([]byte, error) {
return exec.Command("gno", "transpile", "-skip-imports", "-gobuild", filepath.Join(rootDir)).CombinedOutput()
args := []string{"transpile", "-skip-imports", "-gobuild", filepath.Join(rootDir)}
srcPathsStr := os.Getenv("GNOSRCPATHS")
if srcPathsStr != "" {
args = append(args, "-extra-dirs", srcPathsStr)
}
slog.Info("will run", slog.String("cmd", strings.Join(append([]string{"gno"}, args...), " ")))
return exec.Command("gno", args...).CombinedOutput()
}
8 changes: 7 additions & 1 deletion internal/tools/transpile.go
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
package tools

import (
"os"
"os/exec"
"path/filepath"
)

// Transpile a Gno package: gno transpile <dir>.
func Transpile(rootDir string) ([]byte, error) {
return exec.Command("gno", "transpile", "-skip-imports", filepath.Join(rootDir)).CombinedOutput()
args := []string{"transpile", "-skip-imports", filepath.Join(rootDir)}
srcPathsStr := os.Getenv("GNOSRCPATHS")
if srcPathsStr != "" {
args = append(args, "-extra-dirs", srcPathsStr)
}
return exec.Command("gno", args...).CombinedOutput()
}
26 changes: 25 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,31 @@
package main

import "github.com/gnolang/gnopls/cmd"
import (
"log/slog"
"os"
"path/filepath"

"github.com/gnolang/gnopls/cmd"
slogmulti "github.com/samber/slog-multi"
)

func main() {
userHomeDir, err := os.UserHomeDir()
if err != nil {
panic(err)
}
logFilePath := filepath.Join(userHomeDir, "gnopls.log")
logFile, err := os.OpenFile(logFilePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0755)
if err != nil {
panic(err)
}
defer logFile.Close()
logger := slog.New(
slogmulti.Fanout(
slog.NewTextHandler(logFile, &slog.HandlerOptions{}), // pass to first handler: logstash over tcp
slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{}), // then to second handler: stderr
),
)
slog.SetDefault(logger)
cmd.Execute()
}

0 comments on commit c8c1d49

Please sign in to comment.