interal/lsp: add context based version of xlog

this is a temporary migration solution

Change-Id: Idb6542298dff85a0926aae761f6317ea155293db
Reviewed-on: https://go-review.googlesource.com/c/tools/+/185987
Run-TryBot: Ian Cottrell <iancottrell@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Rebecca Stambler <rstambler@golang.org>
diff --git a/internal/jsonrpc2/jsonrpc2_test.go b/internal/jsonrpc2/jsonrpc2_test.go
index 53affac..89252fd 100644
--- a/internal/jsonrpc2/jsonrpc2_test.go
+++ b/internal/jsonrpc2/jsonrpc2_test.go
@@ -167,9 +167,9 @@
 func (h *handle) Request(ctx context.Context, direction jsonrpc2.Direction, r *jsonrpc2.WireRequest) context.Context {
 	if h.log {
 		if r.ID != nil {
-			log.Printf("%v call [%v] %s %s", direction, r.ID, r.Method, r.Params)
+			log.Printf("%v call [%v] %s %v", direction, r.ID, r.Method, r.Params)
 		} else {
-			log.Printf("%v notification %s %s", direction, r.Method, r.Params)
+			log.Printf("%v notification %s %v", direction, r.Method, r.Params)
 		}
 		ctx = context.WithValue(ctx, "method", r.Method)
 		ctx = context.WithValue(ctx, "start", time.Now())
@@ -181,7 +181,7 @@
 	if h.log {
 		method := ctx.Value("method")
 		elapsed := time.Since(ctx.Value("start").(time.Time))
-		log.Printf("%v response in %v [%v] %s %s", direction, elapsed, r.ID, method, r.Result)
+		log.Printf("%v response in %v [%v] %s %v", direction, elapsed, r.ID, method, r.Result)
 	}
 	return ctx
 }
diff --git a/internal/lsp/cache/cache.go b/internal/lsp/cache/cache.go
index 713e5e7..ed2468f 100644
--- a/internal/lsp/cache/cache.go
+++ b/internal/lsp/cache/cache.go
@@ -72,12 +72,12 @@
 	}
 }
 
-func (c *cache) NewSession(log xlog.Logger) source.Session {
+func (c *cache) NewSession(ctx context.Context) source.Session {
 	index := atomic.AddInt64(&sessionIndex, 1)
 	s := &session{
 		cache:         c,
 		id:            strconv.FormatInt(index, 10),
-		log:           log,
+		log:           xlog.From(ctx),
 		overlays:      make(map[span.URI]*overlay),
 		filesWatchMap: NewWatchMap(),
 	}
diff --git a/internal/lsp/cmd/cmd.go b/internal/lsp/cmd/cmd.go
index 03aa3d2..c459037 100644
--- a/internal/lsp/cmd/cmd.go
+++ b/internal/lsp/cmd/cmd.go
@@ -140,7 +140,7 @@
 	switch app.Remote {
 	case "":
 		connection := newConnection(app)
-		connection.Server = lsp.NewClientServer(app.cache, connection.Client)
+		ctx, connection.Server = lsp.NewClientServer(ctx, app.cache, connection.Client)
 		return connection, connection.initialize(ctx)
 	case "internal":
 		internalMu.Lock()
@@ -153,9 +153,12 @@
 		cr, sw, _ := os.Pipe()
 		sr, cw, _ := os.Pipe()
 		var jc *jsonrpc2.Conn
-		jc, connection.Server, _ = protocol.NewClient(jsonrpc2.NewHeaderStream(cr, cw), connection.Client)
+		ctx, jc, connection.Server = protocol.NewClient(ctx, jsonrpc2.NewHeaderStream(cr, cw), connection.Client)
 		go jc.Run(ctx)
-		go lsp.NewServer(app.cache, jsonrpc2.NewHeaderStream(sr, sw)).Run(ctx)
+		go func() {
+			ctx, srv := lsp.NewServer(ctx, app.cache, jsonrpc2.NewHeaderStream(sr, sw))
+			srv.Run(ctx)
+		}()
 		if err := connection.initialize(ctx); err != nil {
 			return nil, err
 		}
@@ -169,7 +172,7 @@
 		}
 		stream := jsonrpc2.NewHeaderStream(conn, conn)
 		var jc *jsonrpc2.Conn
-		jc, connection.Server, _ = protocol.NewClient(stream, connection.Client)
+		ctx, jc, connection.Server = protocol.NewClient(ctx, stream, connection.Client)
 		go jc.Run(ctx)
 		return connection, connection.initialize(ctx)
 	}
diff --git a/internal/lsp/cmd/serve.go b/internal/lsp/cmd/serve.go
index ac02312..9b45f9f 100644
--- a/internal/lsp/cmd/serve.go
+++ b/internal/lsp/cmd/serve.go
@@ -79,7 +79,7 @@
 	}
 
 	// For debugging purposes only.
-	run := func(srv *lsp.Server) {
+	run := func(ctx context.Context, srv *lsp.Server) {
 		srv.Conn.AddHandler(&handler{trace: s.Trace, out: out})
 		go srv.Run(ctx)
 	}
@@ -90,7 +90,7 @@
 		return lsp.RunServerOnPort(ctx, s.app.cache, s.Port, run)
 	}
 	stream := jsonrpc2.NewHeaderStream(os.Stdin, os.Stdout)
-	srv := lsp.NewServer(s.app.cache, stream)
+	ctx, srv := lsp.NewServer(ctx, s.app.cache, stream)
 	srv.Conn.AddHandler(&handler{trace: s.Trace, out: out})
 	return srv.Run(ctx)
 }
diff --git a/internal/lsp/lsp_test.go b/internal/lsp/lsp_test.go
index f448059..7c8fdf8 100644
--- a/internal/lsp/lsp_test.go
+++ b/internal/lsp/lsp_test.go
@@ -42,9 +42,9 @@
 	data := tests.Load(t, exporter, "testdata")
 	defer data.Exported.Cleanup()
 
-	log := xlog.New(xlog.StdSink{})
+	ctx = xlog.With(ctx, xlog.StdSink{})
 	cache := cache.New()
-	session := cache.NewSession(log)
+	session := cache.NewSession(ctx)
 	view := session.NewView(ctx, viewName, span.FileURI(data.Config.Dir))
 	view.SetEnv(data.Config.Env)
 	for filename, content := range data.Config.Overlay {
diff --git a/internal/lsp/protocol/protocol.go b/internal/lsp/protocol/protocol.go
index c1bbb76..254b2f9 100644
--- a/internal/lsp/protocol/protocol.go
+++ b/internal/lsp/protocol/protocol.go
@@ -40,19 +40,19 @@
 	return true
 }
 
-func NewClient(stream jsonrpc2.Stream, client Client) (*jsonrpc2.Conn, Server, xlog.Logger) {
-	log := xlog.New(NewLogger(client))
+func NewClient(ctx context.Context, stream jsonrpc2.Stream, client Client) (context.Context, *jsonrpc2.Conn, Server) {
+	ctx = xlog.With(ctx, NewLogger(client))
 	conn := jsonrpc2.NewConn(stream)
-	conn.AddHandler(&clientHandler{log: log, client: client})
-	return conn, &serverDispatcher{Conn: conn}, log
+	conn.AddHandler(&clientHandler{log: xlog.From(ctx), client: client})
+	return ctx, conn, &serverDispatcher{Conn: conn}
 }
 
-func NewServer(stream jsonrpc2.Stream, server Server) (*jsonrpc2.Conn, Client, xlog.Logger) {
+func NewServer(ctx context.Context, stream jsonrpc2.Stream, server Server) (context.Context, *jsonrpc2.Conn, Client) {
 	conn := jsonrpc2.NewConn(stream)
 	client := &clientDispatcher{Conn: conn}
-	log := xlog.New(NewLogger(client))
-	conn.AddHandler(&serverHandler{log: log, server: server})
-	return conn, client, log
+	ctx = xlog.With(ctx, NewLogger(client))
+	conn.AddHandler(&serverHandler{log: xlog.From(ctx), server: server})
+	return ctx, conn, client
 }
 
 func sendParseError(ctx context.Context, log xlog.Logger, req *jsonrpc2.Request, err error) {
diff --git a/internal/lsp/server.go b/internal/lsp/server.go
index a75821e..8d38423 100644
--- a/internal/lsp/server.go
+++ b/internal/lsp/server.go
@@ -18,32 +18,32 @@
 )
 
 // NewClientServer
-func NewClientServer(cache source.Cache, client protocol.Client) *Server {
-	return &Server{
+func NewClientServer(ctx context.Context, cache source.Cache, client protocol.Client) (context.Context, *Server) {
+	ctx = xlog.With(ctx, protocol.NewLogger(client))
+	return ctx, &Server{
 		client:  client,
-		session: cache.NewSession(xlog.New(protocol.NewLogger(client))),
+		session: cache.NewSession(ctx),
 	}
 }
 
 // NewServer starts an LSP server on the supplied stream, and waits until the
 // stream is closed.
-func NewServer(cache source.Cache, stream jsonrpc2.Stream) *Server {
+func NewServer(ctx context.Context, cache source.Cache, stream jsonrpc2.Stream) (context.Context, *Server) {
 	s := &Server{}
-	var log xlog.Logger
-	s.Conn, s.client, log = protocol.NewServer(stream, s)
-	s.session = cache.NewSession(log)
-	return s
+	ctx, s.Conn, s.client = protocol.NewServer(ctx, stream, s)
+	s.session = cache.NewSession(ctx)
+	return ctx, s
 }
 
 // RunServerOnPort starts an LSP server on the given port and does not exit.
 // This function exists for debugging purposes.
-func RunServerOnPort(ctx context.Context, cache source.Cache, port int, h func(s *Server)) error {
+func RunServerOnPort(ctx context.Context, cache source.Cache, port int, h func(ctx context.Context, s *Server)) error {
 	return RunServerOnAddress(ctx, cache, fmt.Sprintf(":%v", port), h)
 }
 
 // RunServerOnPort starts an LSP server on the given port and does not exit.
 // This function exists for debugging purposes.
-func RunServerOnAddress(ctx context.Context, cache source.Cache, addr string, h func(s *Server)) error {
+func RunServerOnAddress(ctx context.Context, cache source.Cache, addr string, h func(ctx context.Context, s *Server)) error {
 	ln, err := net.Listen("tcp", addr)
 	if err != nil {
 		return err
@@ -53,7 +53,7 @@
 		if err != nil {
 			return err
 		}
-		h(NewServer(cache, jsonrpc2.NewHeaderStream(conn, conn)))
+		h(NewServer(ctx, cache, jsonrpc2.NewHeaderStream(conn, conn)))
 	}
 }
 
diff --git a/internal/lsp/source/source_test.go b/internal/lsp/source/source_test.go
index c38e38c..7bd469e 100644
--- a/internal/lsp/source/source_test.go
+++ b/internal/lsp/source/source_test.go
@@ -38,9 +38,9 @@
 	data := tests.Load(t, exporter, "../testdata")
 	defer data.Exported.Cleanup()
 
-	log := xlog.New(xlog.StdSink{})
+	ctx = xlog.With(ctx, xlog.StdSink{})
 	cache := cache.New()
-	session := cache.NewSession(log)
+	session := cache.NewSession(ctx)
 	r := &runner{
 		view: session.NewView(ctx, "source_test", span.FileURI(data.Config.Dir)),
 		data: data,
diff --git a/internal/lsp/source/view.go b/internal/lsp/source/view.go
index 996d659..f40553d 100644
--- a/internal/lsp/source/view.go
+++ b/internal/lsp/source/view.go
@@ -111,7 +111,7 @@
 	FileSystem
 
 	// NewSession creates a new Session manager and returns it.
-	NewSession(log xlog.Logger) Session
+	NewSession(ctx context.Context) Session
 
 	// FileSet returns the shared fileset used by all files in the system.
 	FileSet() *token.FileSet
diff --git a/internal/lsp/xlog/xlog.go b/internal/lsp/xlog/xlog.go
index a8d5bda..6d9fc36 100644
--- a/internal/lsp/xlog/xlog.go
+++ b/internal/lsp/xlog/xlog.go
@@ -35,11 +35,6 @@
 // StdSink is a Sink that writes to the standard log package.
 type StdSink struct{}
 
-// New returns a logger for the provided sink.
-func New(sink Sink) Logger {
-	return Logger{sink: sink}
-}
-
 // Errorf is intended for the logging of errors that we could not easily return
 // to the client but that caused problems internally.
 func (l Logger) Errorf(ctx context.Context, format string, args ...interface{}) {
@@ -69,3 +64,27 @@
 		log.Print("Debug: ", message)
 	}
 }
+
+type contextKeyType int
+
+const contextKey = contextKeyType(0)
+
+func With(ctx context.Context, sink Sink) context.Context {
+	return context.WithValue(ctx, contextKey, sink)
+}
+
+func From(ctx context.Context) Logger {
+	return Logger{sink: ctx.Value(contextKey).(Sink)}
+}
+
+func Errorf(ctx context.Context, format string, args ...interface{}) {
+	From(ctx).Errorf(ctx, format, args...)
+}
+
+func Infof(ctx context.Context, format string, args ...interface{}) {
+	From(ctx).Infof(ctx, format, args...)
+}
+
+func Debugf(ctx context.Context, format string, args ...interface{}) {
+	From(ctx).Debugf(ctx, format, args...)
+}