diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml new file mode 100644 index 0000000..ce4281b --- /dev/null +++ b/.github/workflows/go.yml @@ -0,0 +1,25 @@ +name: Go + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + + build: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - name: Set up Go + uses: actions/setup-go@v4 + with: + go-version: 1.21 + + - name: Build + run: go build -v ./... + + - name: Test + run: go test -v ./... diff --git a/README.md b/README.md index 4201673..570dfac 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ +*Note: `harry-hov/gnopls` is now [`gnolang/gnopls`](https://github.com/gnolang/gnopls) + # `gnopls`, the Gno language server +![Build & Test](https://github.com/harry-hov/gnopls/actions/workflows/go.yml/badge.svg) + `gnopls` (pronounced "Gno please") is the unofficial Gno [language server]. It provides IDE features to any [LSP]-compatible editor. ## Installation diff --git a/internal/lsp/completion.go b/internal/lsp/completion.go index f40bc7b..c1f0ff0 100644 --- a/internal/lsp/completion.go +++ b/internal/lsp/completion.go @@ -164,7 +164,7 @@ func (s *server) Completion(ctx context.Context, reply jsonrpc2.Replier, req jso return reply(ctx, nil, errors.New("snapshot not found")) } // Try parsing current file - pgf, err := file.ParseGno(ctx) + pgf, err := file.ParseGno2(ctx) if err != nil { return reply(ctx, nil, errors.New("cannot parse gno file")) } @@ -180,12 +180,6 @@ func (s *server) Completion(ctx context.Context, reply jsonrpc2.Replier, req jso } } - // Load pkg from cache - pkg, ok := s.cache.pkgs.Get(filepath.Dir(string(uri.Filename()))) - if !ok { - return reply(ctx, nil, nil) - } - // Completion is based on what precedes the cursor. // Find the path to the position before pos. paths, _ := astutil.PathEnclosingInterval(pgf.File, token.Pos(offset-1), token.Pos(offset-1)) @@ -193,6 +187,15 @@ func (s *server) Completion(ctx context.Context, reply jsonrpc2.Replier, req jso return reply(ctx, nil, nil) } + // Debug + // slog.Info("COMPLETION", "token", fmt.Sprintf("%s", paths[0])) + + // Load pkg from cache + pkg, ok := s.cache.pkgs.Get(filepath.Dir(string(uri.Filename()))) + if !ok { + return reply(ctx, nil, nil) + } + switch n := paths[0].(type) { case *ast.Ident: _, tv := getTypeAndValue( @@ -244,7 +247,6 @@ func (s *server) Completion(ctx context.Context, reply jsonrpc2.Replier, req jso break } t := parseType(typeStr, path) - slog.Info(t) methods, ok := pkg.Methods.Get(t) if !ok { break @@ -304,7 +306,6 @@ func (s *server) Completion(ctx context.Context, reply jsonrpc2.Replier, req jso break } t := parseType(typeStr, path) - slog.Info(t) methods, ok := pkg.Methods.Get(t) if !ok { break diff --git a/internal/lsp/hover.go b/internal/lsp/hover.go index bc49f2b..e9726a1 100644 --- a/internal/lsp/hover.go +++ b/internal/lsp/hover.go @@ -85,7 +85,16 @@ func (s *server) Hover(ctx context.Context, reply jsonrpc2.Replier, req jsonrpc2 case *ast.SelectorExpr: return hoverSelectorExpr(ctx, s, reply, params, pgf, pkg, paths, n, t, int(line)) default: - return reply(ctx, nil, nil) + return reply(ctx, protocol.Hover{ + Contents: protocol.MarkupContent{ + Kind: protocol.Markdown, + Value: FormatHoverContent(n.Name, ""), + }, + Range: posToRange( + int(params.Position.Line), + []int{int(n.Pos()), int(n.End())}, + ), + }, nil) } } typeStr := tv.Type.String() diff --git a/internal/lsp/snapshot.go b/internal/lsp/snapshot.go index b867a7a..f197e13 100644 --- a/internal/lsp/snapshot.go +++ b/internal/lsp/snapshot.go @@ -46,6 +46,7 @@ type ParsedGnoFile struct { Src []byte } +// ParseGno reads src from disk and parse it func (f *GnoFile) ParseGno(ctx context.Context) (*ParsedGnoFile, error) { fset := token.NewFileSet() ast, err := parser.ParseFile(fset, f.URI.Filename(), nil, parser.ParseComments) @@ -64,6 +65,27 @@ func (f *GnoFile) ParseGno(ctx context.Context) (*ParsedGnoFile, error) { return pgf, nil } +// ParseGno2 parses src from GnoFile instead of reading from disk +// Right now it's only used in `completion.go` +// TODO: Replace content of `ParseGno` with `ParseGno2` +func (f *GnoFile) ParseGno2(ctx context.Context) (*ParsedGnoFile, error) { + fset := token.NewFileSet() + ast, err := parser.ParseFile(fset, f.URI.Filename(), f.Src, parser.ParseComments) + if err != nil { + return nil, err + } + + pgf := &ParsedGnoFile{ + URI: f.URI, + + File: ast, + Fset: fset, + Src: f.Src, + } + + return pgf, nil +} + // contains parsed gno.mod file. type ParsedGnoMod struct { URI string