Skip to content

Commit

Permalink
Merge pull request #19 from xushiwei/q
Browse files Browse the repository at this point in the history
gopls.proxy & lsview
  • Loading branch information
xushiwei authored Oct 16, 2023
2 parents 7310f48 + 0133794 commit 7f87bea
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 41 deletions.
4 changes: 3 additions & 1 deletion gopls/goxls/cmd/gopls.proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package main

import (
"os"

"golang.org/x/tools/gopls/goxls/proxy"
)

Expand All @@ -14,5 +16,5 @@ const (
)

func main() {
proxy.Main(gopls, goxls)
proxy.Main(gopls, goxls, os.Args[1:]...)
}
4 changes: 3 additions & 1 deletion gopls/goxls/cmd/lsview/lsview_app.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
package main

import (
"os"

"golang.org/x/tools/gopls/goxls/lsview"
)

Expand All @@ -14,5 +16,5 @@ const (
)

func main() {
lsview.Main(gopls, goxls)
lsview.Main(gopls, goxls, os.Args[1:]...)
}
107 changes: 81 additions & 26 deletions gopls/goxls/lsview/lsview.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"context"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"log"
Expand All @@ -21,16 +22,24 @@ import (
"golang.org/x/tools/internal/jsonrpc2"
)

func Main(app, goxls string) {
fin, err := os.Open(app + ".in")
func Main(app, goxls string, args ...string) {
flag := flag.NewFlagSet("lsview", flag.ExitOnError)
var (
fSummary = flag.Bool("s", false, "show summary information for jsonrpc")
fSel = flag.String("sel", "", "select a method to print")
)
flag.Parse(args)
sel := *fSel

fin, err := os.Open("gopls.in")
check(err)
defer fin.Close()

fview, err := os.Create(app + ".view")
fview, err := os.Create("gopls.view")
check(err)
defer fview.Close()

fdiff, err := os.Create(app + ".diff")
fdiff, err := os.Create("gopls.diff")
check(err)
defer fdiff.Close()

Expand All @@ -55,48 +64,52 @@ func Main(app, goxls string) {
}
switch req := msg.(type) {
case *jsonrpc2.Call:
id := req.ID()
log.Printf("[%v] %s:\n%s", id, req.Method(), params(req.Params()))
id, method := req.ID(), req.Method()
summary := *fSummary && method != sel
log.Printf("[%v] %s\n%s", id, method, params(req.Params(), summary))
reqChan <- id
resp, ret := respFetch(respChan)
resp, ret := respFetch(respChan, summary)
if resp != nil {
log.Printf("[%v] %s ret:\n%s", id, app, resp)
log.Printf("[%v] %s ret\n%s", id, app, resp)
}
if goxls != "" {
var resp2, ret2 any
select { // allow send request failed
case <-time.After(time.Second):
case reqChan2 <- id:
if resp2, ret2 := respFetch(respChan2); resp2 != nil {
log.Printf("[%v] %s ret:\n%s", id, goxls, resp2)
if !reflect.DeepEqual(ret, ret2) {
logd.Printf("[%v] %s:\n%s", id, req.Method(), params(req.Params()))
logd.Printf("[%v] %s ret:\n%s", id, app, resp)
logd.Printf("[%v] %s ret:\n%s", id, goxls, resp2)
}
if resp2, ret2 = respFetch(respChan2, summary); resp2 != nil {
log.Printf("[%v] %s ret\n%s", id, goxls, resp2)
}
}
if eq, resp, resp2 := checkEqual(id, ret, ret2, resp, resp2); !eq {
logd.Printf("[%v] %s\n%s", id, method, params(req.Params(), summary))
logd.Printf("[%v] %s ret\n%s", id, app, resp)
logd.Printf("[%v] %s ret\n%s", id, goxls, resp2)
}
}
case *jsonrpc2.Notification:
log.Printf("[] %s:\n%s", req.Method(), params(req.Params()))
method := req.Method()
summary := *fSummary && method != sel
log.Printf("[] %s:\n%s", method, params(req.Params(), summary))
}
}
}()
go respLoop(app, respChan, reqChan)
if goxls != "" {
go respLoop(app, respChan2, reqChan2)
go respLoop(goxls, respChan2, reqChan2)
}
select {}
}

func respFetch(respChan chan *jsonrpc2.Response) (any, any) {
func respFetch(respChan chan *jsonrpc2.Response, summary bool) (any, any) {
select {
case <-time.After(time.Second):
case resp := <-respChan:
ret := any(resp.Err())
if ret == nil {
return paramsEx(resp.Result())
return paramsEx(resp.Result(), summary)
}
return fmt.Sprintf("%serror: %v\n", indent, ret), nil
return fmt.Sprintf("%serror: %v\n", indent, ret), ret
}
return nil, nil
}
Expand Down Expand Up @@ -147,33 +160,39 @@ type slice = []any

const indent = " "

func params(raw json.RawMessage) []byte {
func params(raw json.RawMessage, summary bool) []byte {
if summary {
return nil
}
var ret any
err := json.Unmarshal(raw, &ret)
if err != nil {
return raw
}
return paramsFmt(ret, indent)
return paramsFmt(ret, indent, false)
}

func paramsEx(raw json.RawMessage) ([]byte, any) {
func paramsEx(raw json.RawMessage, summary bool) ([]byte, any) {
var ret any
err := json.Unmarshal(raw, &ret)
if err != nil {
return raw, ret
}
return paramsFmt(ret, indent), ret
return paramsFmt(ret, indent, summary), ret
}

func paramsFmt(ret any, prefix string) []byte {
func paramsFmt(ret any, prefix string, summary bool) []byte {
if summary {
return nil
}
var b bytes.Buffer
switch val := ret.(type) {
case mapt:
keys := keys(val)
for _, k := range keys {
v := val[k]
if isComplex(v) {
fmt.Fprintf(&b, "%s%s:\n%s", prefix, k, paramsFmt(v, prefix+indent))
fmt.Fprintf(&b, "%s%s:\n%s", prefix, k, paramsFmt(v, prefix+indent, false))
} else {
fmt.Fprintf(&b, "%s%s: %v\n", prefix, k, v)
}
Expand Down Expand Up @@ -208,6 +227,42 @@ func isComplex(v any) bool {
return ok
}

func checkEqual(id jsonrpc2.ID, a, b, resp, resp2 any) (eq bool, fmta, fmtb any) {
ma, oka := a.(mapt)
mb, okb := b.(mapt)
if oka && okb {
if id == jsonrpc2.NewIntID(0) {
delete(ma, "serverInfo")
delete(mb, "serverInfo")
}
if eq = mapEqual(ma, mb); !eq {
fmta, fmtb = paramsFmt(a, indent, false), paramsFmt(b, indent, false)
}
return
}
return reflect.DeepEqual(a, b), resp, resp2
}

func mapEqual(ma, mb mapt) bool {
for k, va := range ma {
if vb, ok := mb[k]; ok {
mva, oka := va.(mapt)
mvb, okb := vb.(mapt)
eq := false
if oka && okb {
eq = mapEqual(mva, mvb)
} else {
eq = reflect.DeepEqual(va, vb)
}
if eq {
delete(ma, k)
delete(mb, k)
}
}
}
return len(ma) == 0 && len(mb) == 0
}

func keys(v mapt) []string {
ret := make([]string, 0, len(v))
for key := range v {
Expand Down
35 changes: 22 additions & 13 deletions gopls/goxls/proxy/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,21 @@ import (
"time"
)

func Main(gopls, goxls string) {
func Main(gopls, goxls string, args ...string) {
if len(args) > 0 && args[0] == "version" {
version(gopls, args)
return
}

home, err := os.UserHomeDir()
check(err)

goplsDir := home + "/.gopls/"
rotateDir := goplsDir + strconv.FormatInt(time.Now().UnixMicro(), 36)
err = os.MkdirAll(rotateDir, 0755)
check(err)
if _, e := os.Lstat(goplsDir + gopls + ".in"); e == nil {
err = os.MkdirAll(rotateDir, 0755)
check(err)
}

rotateDir += "/"
createFile := func(name string) (f *os.File, err error) {
Expand All @@ -29,21 +36,14 @@ func Main(gopls, goxls string) {
return os.Create(normal)
}

logf, err := createFile(gopls + ".log")
check(err)
defer logf.Close()

stdinf, err := createFile(gopls + ".in")
stdinf, err := createFile("gopls.in")
check(err)
defer stdinf.Close()

stdoutf, err := createFile(gopls + ".out")
check(err)
defer stdoutf.Close()

log.SetOutput(logf)
log.Println("[INFO] app start:", os.Args)

var pwGox io.WriteCloser
if goxls != "" {
goxoutf, err := createFile(goxls + ".out")
Expand All @@ -55,7 +55,7 @@ func Main(gopls, goxls string) {
pwGox = pw

go func() {
cmd := exec.Command(goxls, os.Args[1:]...)
cmd := exec.Command(goxls, args...)
cmd.Stdin = pr
cmd.Stdout = goxoutf
cmd.Stderr = os.Stderr
Expand All @@ -78,14 +78,23 @@ func Main(gopls, goxls string) {
}
}()

cmd := exec.Command(gopls, os.Args[1:]...)
cmd := exec.Command(gopls, args...)
cmd.Stdin = pr
cmd.Stdout = io.MultiWriter(os.Stdout, stdoutf)
cmd.Stderr = os.Stderr
err = cmd.Run()
check(err)
}

func version(gopls string, args []string) {
cmd := exec.Command(gopls, args...)
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err := cmd.Run()
check(err)
}

func check(err error) {
if err != nil {
log.Panicln(err)
Expand Down

0 comments on commit 7f87bea

Please sign in to comment.