Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
76ef0ab
feat: refactor providers structure
x1unix Jul 13, 2024
e5c17a8
feat: detect if is in import block
x1unix Jul 14, 2024
dde7c15
fix: allow widgets overflow
x1unix Jul 14, 2024
bac5bec
feat: provider lifecycle hooks
x1unix Jul 14, 2024
5640429
fix: provide suggestion range
x1unix Jul 14, 2024
af94dbe
feat: add monaco Go types
x1unix Jul 14, 2024
8f25164
fix: remove original monaco comments
x1unix Jul 14, 2024
079028e
chore: add provider comment
x1unix Jul 15, 2024
682ca33
feat: add missing monaco field
x1unix Jul 15, 2024
c0fe84f
feat: add package index skeleton
x1unix Jul 15, 2024
78a94f5
feat: add pkgindexer binary
x1unix Jul 15, 2024
5ec50cf
feat: finish pkgindexer
x1unix Jul 15, 2024
da7180d
fix: fix write bugs in pkgindexer
x1unix Jul 15, 2024
3bfe27a
fix: remove redundant file
x1unix Jul 15, 2024
c6b6702
chore: move indexer into tools
x1unix Jul 15, 2024
fb7be37
chore: bump 'dexie'
x1unix Jul 15, 2024
8a9c496
feat: add simple key-value storage
x1unix Jul 15, 2024
3db260c
feat: add completion service
x1unix Jul 15, 2024
b353964
feat: use cache
x1unix Jul 15, 2024
03cb038
feat: implement cache TTL
x1unix Jul 15, 2024
921e7ae
feat: update build script
x1unix Jul 15, 2024
cb72af2
feat: build imports index
x1unix Jul 15, 2024
41df435
fix: copy tools to Docker
x1unix Jul 15, 2024
c6c815d
fix: fix dockerignore
x1unix Jul 15, 2024
056fe28
Merge branch 'master' into feat/import-autocomplete
x1unix Jul 15, 2024
228f42b
fix: fix error handling in pkgindexer
x1unix Jul 15, 2024
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
1 change: 0 additions & 1 deletion .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,4 @@
.idea
.vscode
web/node_modules
tools/
target/
2 changes: 0 additions & 2 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ on:
release:
types:
- created
repository_dispatch:
types: manual-deploy

env:
GO_VERSION: 1.21
Expand Down
7 changes: 6 additions & 1 deletion build.mk
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@ check-go:
exit 1; \
fi

.PHONY: pkg-index
pkg-index:
@echo ":: Generating Go packages index..." && \
$(GO) run ./tools/pkgindexer -o $(UI)/public/data/imports.json

.PHONY:check-yarn
check-yarn:
$(call check_tool,$(YARN),'YARN')
Expand Down Expand Up @@ -73,7 +78,7 @@ go-repl.wasm:
wasm: wasm_exec.js analyzer.wasm go-repl.wasm

.PHONY: build
build: check-go check-yarn clean preinstall gen collect-meta build-server wasm build-ui
build: check-go check-yarn clean preinstall gen collect-meta build-server wasm pkg-index build-ui
@echo ":: Copying assets..." && \
cp -rfv ./data $(TARGET)/data && \
mv -v $(UI)/build $(TARGET)/public && \
Expand Down
5 changes: 4 additions & 1 deletion build/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ WORKDIR /tmp/playground
COPY cmd ./cmd
COPY pkg ./pkg
COPY internal ./internal
COPY tools ./tools
COPY go.mod .
COPY go.sum .

Expand All @@ -49,7 +50,8 @@ RUN echo "Building server with version $APP_VERSION" && \
-trimpath \
-o ./analyzer@$WASM_API_VER.wasm ./cmd/wasm/analyzer && \
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./[email protected] && \
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./wasm_exec.js
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./wasm_exec.js && \
go run ./tools/pkgindexer -o ./data/imports.json

FROM golang:${GO_VERSION}-alpine AS production
ARG GO_VERSION
Expand All @@ -66,6 +68,7 @@ COPY --from=ui-build /tmp/web/build ./public
COPY --from=build /tmp/playground/server .
COPY --from=build /tmp/playground/*.wasm ./public/wasm/
COPY --from=build /tmp/playground/*.js ./public/wasm/
COPY --from=build /tmp/playground/data ./public/data
EXPOSE 8000
ENTRYPOINT /opt/playground/server \
-f='/opt/playground/data/packages.json' \
Expand Down
5 changes: 4 additions & 1 deletion build/release.dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ WORKDIR /tmp/playground
COPY cmd ./cmd
COPY pkg ./pkg
COPY internal ./internal
COPY tools ./tools
COPY go.mod .
COPY go.sum .

Expand All @@ -36,7 +37,8 @@ RUN echo "Building server with version $APP_VERSION" && \
-trimpath \
-o ./analyzer@$WASM_API_VER.wasm ./cmd/wasm/analyzer && \
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./[email protected] && \
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./wasm_exec.js
cp $(go env GOROOT)/misc/wasm/wasm_exec.js ./wasm_exec.js && \
go run ./tools/pkgindexer -o ./data/imports.json

FROM golang:${GO_VERSION}-alpine AS production
ARG GO_VERSION
Expand All @@ -52,6 +54,7 @@ COPY web/build ./public
COPY --from=build /tmp/playground/server .
COPY --from=build /tmp/playground/*.wasm ./public/wasm/
COPY --from=build /tmp/playground/*.js ./public/wasm/
COPY --from=build /tmp/playground/data ./public/data
EXPOSE 8000
ENTRYPOINT /opt/playground/server \
-f='/opt/playground/data/packages.json' \
Expand Down
5 changes: 4 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -17,15 +17,18 @@ require (
go.uber.org/zap v1.21.0
golang.org/x/exp v0.0.0-20230321023759-10a507213a29
golang.org/x/mod v0.14.0
golang.org/x/sync v0.2.0
golang.org/x/sync v0.7.0
golang.org/x/time v0.0.0-20201208040808-7e3f01d25324
)

require (
github.com/benbjohnson/clock v1.1.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/getsentry/sentry-go v0.13.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/cobra v1.8.1 // indirect
github.com/spf13/pflag v1.0.5 // indirect
go.uber.org/atomic v1.9.0 // indirect
go.uber.org/multierr v1.8.0 // indirect
golang.org/x/sys v0.3.0 // indirect
Expand Down
10 changes: 10 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ github.com/avast/retry-go v3.0.0+incompatible h1:4SOWQ7Qs+oroOTQOYnAHqelpCO0biHS
github.com/avast/retry-go v3.0.0+incompatible/go.mod h1:XtSnn+n/sHqQIpZ10K1qAevBhOOCWBLXXy3hyiqqBrY=
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
Expand All @@ -13,6 +14,8 @@ github.com/go-errors/errors v1.0.1 h1:LUHzmkK3GUKUrL/1gfBUxAHzcev3apQlezX/+O7ma6
github.com/google/go-cmp v0.5.8 h1:e6P7q2lk1O+qJJb4BtCQXlK8vWEO8V1ZeuEdJNOqZyg=
github.com/gorilla/mux v1.7.3 h1:gnP5JzjVOuiZD07fKKToCAOjS0yOpj/qPETTXCCS6hw=
github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/kelseyhightower/envconfig v1.4.0 h1:Im6hONhd3pLkfDFsbRgu68RDNkGF1r3dvMUtDTo2cv8=
github.com/kelseyhightower/envconfig v1.4.0/go.mod h1:cccZRl6mQpaq41TPp5QxidR+Sa3axMbJDNb//FQX6Gg=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
Expand All @@ -25,8 +28,13 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
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/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
Expand Down Expand Up @@ -71,6 +79,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.2.0 h1:PUR+T4wwASmuSTYdKjYHI5TD22Wy5ogLU5qZCOLxBrI=
golang.org/x/sync v0.2.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
2 changes: 1 addition & 1 deletion internal/analyzer/decl.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func funcToItem(fn *ast.FuncDecl) *CompletionItem {
Label: fn.Name.String(),
Kind: Function,
Detail: funcToString(fn.Type),
Documentation: formatDoc(fn.Doc.Text()),
Documentation: FormatDocString(fn.Doc.Text()),
InsertText: formatFuncInsertText(fn),
InsertTextRules: InsertAsSnippet,
}
Expand Down
3 changes: 2 additions & 1 deletion internal/analyzer/docfmt.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ func isDocLine(line string) bool {
return false
}

func formatDoc(str string) MarkdownString {
// FormatDocString parses Go comment and returns a markdown-formatted string.
func FormatDocString(str string) MarkdownString {
if str == "" {
return MarkdownString{Value: str}
}
Expand Down
73 changes: 73 additions & 0 deletions internal/pkgindex/parser.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package pkgindex

import (
"context"
"fmt"
"go/parser"
"go/token"
"path/filepath"
"strings"

"github.com/x1unix/go-playground/internal/analyzer"
"github.com/x1unix/go-playground/pkg/monaco"
)

const goDocDomain = "pkg.go.dev"

type PackageParseParams struct {
RootDir string
ImportPath string
Files []string
}

func (params PackageParseParams) PackagePath() string {
return filepath.Join(params.RootDir, params.ImportPath)
}

func formatGoDocLink(importPath string) string {
return fmt.Sprintf("[%[2]s on %[1]s](https://%[1]s/%[2]s)", goDocDomain, importPath)
}

// ParseImportCompletionItem parses a Go package at a given GOROOT and constructs monaco CompletionItem from it.
func ParseImportCompletionItem(ctx context.Context, params PackageParseParams) (result monaco.CompletionItem, error error) {
pkgPath := params.PackagePath()

result = monaco.CompletionItem{
Kind: monaco.Module,
Detail: params.ImportPath,
InsertText: params.ImportPath,
}

docString := formatGoDocLink(params.ImportPath)

fset := token.NewFileSet()
for _, fname := range params.Files {
if err := ctx.Err(); err != nil {
return result, err
}

fpath := filepath.Join(pkgPath, fname)
src, err := parser.ParseFile(fset, fpath, nil, parser.ParseComments)
if err != nil {
return result, fmt.Errorf("failed to parse Go file %q: %s", fpath, err)
}

doc := src.Doc
if doc == nil {
continue
}

// Found a doc string, exit.
result.Detail = src.Name.String()
docComment := strings.TrimSpace(analyzer.FormatDocString(doc.Text()).Value)
docString = docComment + "\n\n" + docString
break
}

result.Label.SetString(params.ImportPath)
result.Documentation.SetValue(&monaco.IMarkdownString{
Value: docString,
IsTrusted: true,
})
return result, nil
}
113 changes: 113 additions & 0 deletions internal/pkgindex/parser_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
package pkgindex

import (
"context"
"fmt"
"os"
"path/filepath"
"testing"

"github.com/stretchr/testify/require"
"github.com/x1unix/go-playground/pkg/monaco"
)

func TestParseImportCompletionItem(t *testing.T) {
cases := map[string]struct {
pkgName string
expectErr string
getContext func() context.Context
expect func(importPath string) monaco.CompletionItem
}{
"package with documentation": {
pkgName: "foopkg/pkgbar",
expect: func(importPath string) monaco.CompletionItem {
ret := monaco.CompletionItem{
InsertText: importPath,
Kind: monaco.Module,
Detail: "pkgbar",
}

ret.Label.SetString(importPath)
ret.Documentation.SetValue(&monaco.IMarkdownString{
IsTrusted: true,
Value: "Package pkgbar is a stub package for a test.\n\n" +
fmt.Sprintf("[%[2]s on %[1]s](https://%[1]s/%[2]s)", goDocDomain, importPath),
})
return ret
},
},
"package without any documentation": {
pkgName: "foopkg/emptypkg",
expect: func(importPath string) monaco.CompletionItem {
ret := monaco.CompletionItem{
InsertText: importPath,
Kind: monaco.Module,
Detail: importPath,
}

ret.Label.SetString(importPath)
ret.Documentation.SetValue(&monaco.IMarkdownString{
IsTrusted: true,
Value: fmt.Sprintf("[%[2]s on %[1]s](https://%[1]s/%[2]s)", goDocDomain, importPath),
})
return ret
},
},
"package with bad files": {
pkgName: "badpkg",
expectErr: "failed to parse Go file",
},
"canceled context": {
pkgName: "foopkg/pkgbar",
expectErr: context.Canceled.Error(),
getContext: func() context.Context {
ctx, cancelFn := context.WithCancel(context.TODO())
cancelFn()

return ctx
},
},
}

const rootDir = "testdata"
for n, c := range cases {
t.Run(n, func(t *testing.T) {
ctx := context.TODO()
if c.getContext != nil {
ctx = c.getContext()
}

result, err := ParseImportCompletionItem(ctx, PackageParseParams{
RootDir: rootDir,
ImportPath: c.pkgName,
Files: findDirFiles(t, rootDir, c.pkgName),
})
if c.expectErr != "" {
require.Error(t, err)
require.Contains(t, err.Error(), c.expectErr)
return
}

expect := c.expect(c.pkgName)
require.NoError(t, err)
require.Equal(t, expect, result)
})
}
}

func findDirFiles(t *testing.T, dir, pkgName string) []string {
t.Helper()
entries, err := os.ReadDir(filepath.Join(dir, pkgName))
require.NoError(t, err)

files := make([]string, 0, len(entries))
for _, entry := range entries {
if entry.IsDir() {
continue
}

files = append(files, entry.Name())
}

return files
}
8 changes: 8 additions & 0 deletions internal/pkgindex/result.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package pkgindex

import "github.com/x1unix/go-playground/pkg/monaco"

type GoRootSummary struct {
Version string `json:"version"`
Packages []monaco.CompletionItem `json:"packages"`
}
Loading