internal/lsp: stop making background contexts everywhere
For all uses inside the lsp we use the detatch logic instead For tests we build it in the test harness instead This is in preparation for things on the context becomming important Change-Id: I7e6910e0d3581b82abbeeb09f9c22a99efb73142 Reviewed-on: https://go-review.googlesource.com/c/tools/+/185677 Run-TryBot: Ian Cottrell <iancottrell@google.com> Reviewed-by: Rebecca Stambler <rstambler@golang.org>
This commit is contained in:
parent
2868181328
commit
5f9351755f
|
@ -18,6 +18,7 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/lsp/xlog"
|
||||
"golang.org/x/tools/internal/span"
|
||||
"golang.org/x/tools/internal/xcontext"
|
||||
)
|
||||
|
||||
type session struct {
|
||||
|
@ -64,11 +65,11 @@ func (s *session) Cache() source.Cache {
|
|||
return s.cache
|
||||
}
|
||||
|
||||
func (s *session) NewView(name string, folder span.URI) source.View {
|
||||
func (s *session) NewView(ctx context.Context, name string, folder span.URI) source.View {
|
||||
index := atomic.AddInt64(&viewIndex, 1)
|
||||
s.viewMu.Lock()
|
||||
defer s.viewMu.Unlock()
|
||||
ctx := context.Background()
|
||||
ctx = xcontext.Detach(ctx)
|
||||
backgroundCtx, cancel := context.WithCancel(ctx)
|
||||
v := &view{
|
||||
session: s,
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package cmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
|
@ -23,7 +22,7 @@ func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) {
|
|||
fname := uri.Filename()
|
||||
args := []string{"-remote=internal", "check", fname}
|
||||
out := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), r.app, args)
|
||||
tool.Main(r.ctx, r.app, args)
|
||||
})
|
||||
// parse got into a collection of reports
|
||||
got := map[string]struct{}{}
|
||||
|
|
|
@ -26,6 +26,7 @@ import (
|
|||
"golang.org/x/tools/internal/lsp/source"
|
||||
"golang.org/x/tools/internal/span"
|
||||
"golang.org/x/tools/internal/tool"
|
||||
"golang.org/x/tools/internal/xcontext"
|
||||
)
|
||||
|
||||
// Application is the main application as passed to tool.Main
|
||||
|
@ -148,7 +149,7 @@ func (app *Application) connect(ctx context.Context) (*connection, error) {
|
|||
return c, nil
|
||||
}
|
||||
connection := newConnection(app)
|
||||
ctx := context.Background() //TODO:a way of shutting down the internal server
|
||||
ctx := xcontext.Detach(ctx) //TODO:a way of shutting down the internal server
|
||||
cr, sw, _ := os.Pipe()
|
||||
sr, cw, _ := os.Pipe()
|
||||
var jc *jsonrpc2.Conn
|
||||
|
|
|
@ -6,6 +6,7 @@ package cmd_test
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -24,6 +25,7 @@ type runner struct {
|
|||
exporter packagestest.Exporter
|
||||
data *tests.Data
|
||||
app *cmd.Application
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func TestCommandLine(t *testing.T) {
|
||||
|
@ -38,6 +40,7 @@ func testCommandLine(t *testing.T, exporter packagestest.Exporter) {
|
|||
exporter: exporter,
|
||||
data: data,
|
||||
app: cmd.New(data.Config.Dir, data.Exported.Config.Env),
|
||||
ctx: tests.Context(t),
|
||||
}
|
||||
tests.Run(t, r, data)
|
||||
}
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package cmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -56,7 +55,7 @@ func TestDefinitionHelpExample(t *testing.T) {
|
|||
fmt.Sprintf("%v:#%v", thisFile, cmd.ExampleOffset)} {
|
||||
args := append(baseArgs, query)
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), cmd.New("", nil), args)
|
||||
tool.Main(tests.Context(t), cmd.New("", nil), args)
|
||||
})
|
||||
if !expect.MatchString(got) {
|
||||
t.Errorf("test with %v\nexpected:\n%s\ngot:\n%s", args, expect, got)
|
||||
|
@ -84,7 +83,7 @@ func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
|||
uri := d.Src.URI()
|
||||
args = append(args, fmt.Sprint(d.Src))
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), r.app, args)
|
||||
tool.Main(r.ctx, r.app, args)
|
||||
})
|
||||
got = normalizePaths(r.data, got)
|
||||
if mode&jsonGoDef != 0 && runtime.GOOS == "windows" {
|
||||
|
|
|
@ -5,7 +5,6 @@
|
|||
package cmd_test
|
||||
|
||||
import (
|
||||
"context"
|
||||
"os/exec"
|
||||
"regexp"
|
||||
"strings"
|
||||
|
@ -40,7 +39,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
|||
}
|
||||
app := cmd.New(r.data.Config.Dir, r.data.Config.Env)
|
||||
got := captureStdOut(t, func() {
|
||||
tool.Main(context.Background(), app, append([]string{"-remote=internal", "format"}, args...))
|
||||
tool.Main(r.ctx, app, append([]string{"-remote=internal", "format"}, args...))
|
||||
})
|
||||
got = normalizePaths(r.data, got)
|
||||
// check the first two lines are the expected file header
|
||||
|
|
|
@ -32,18 +32,20 @@ func TestLSP(t *testing.T) {
|
|||
type runner struct {
|
||||
server *Server
|
||||
data *tests.Data
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
const viewName = "lsp_test"
|
||||
|
||||
func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
||||
ctx := tests.Context(t)
|
||||
data := tests.Load(t, exporter, "testdata")
|
||||
defer data.Exported.Cleanup()
|
||||
|
||||
log := xlog.New(xlog.StdSink{})
|
||||
cache := cache.New()
|
||||
session := cache.NewSession(log)
|
||||
view := session.NewView(viewName, span.FileURI(data.Config.Dir))
|
||||
view := session.NewView(ctx, viewName, span.FileURI(data.Config.Dir))
|
||||
view.SetEnv(data.Config.Env)
|
||||
for filename, content := range data.Config.Overlay {
|
||||
session.SetOverlay(span.FileURI(filename), content)
|
||||
|
@ -59,6 +61,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
|||
hoverKind: source.SynopsisDocumentation,
|
||||
},
|
||||
data: data,
|
||||
ctx: ctx,
|
||||
}
|
||||
tests.Run(t, r, data)
|
||||
}
|
||||
|
@ -67,7 +70,7 @@ func testLSP(t *testing.T, exporter packagestest.Exporter) {
|
|||
func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) {
|
||||
v := r.server.session.View(viewName)
|
||||
for uri, want := range data {
|
||||
f, err := v.GetFile(context.Background(), uri)
|
||||
f, err := v.GetFile(r.ctx, uri)
|
||||
if err != nil {
|
||||
t.Fatalf("no file for %s: %v", f, err)
|
||||
}
|
||||
|
@ -75,7 +78,7 @@ func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) {
|
|||
if !ok {
|
||||
t.Fatalf("%s is not a Go file: %v", uri, err)
|
||||
}
|
||||
results, err := source.Diagnostics(context.Background(), v, gof, nil)
|
||||
results, err := source.Diagnostics(r.ctx, v, gof, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -218,7 +221,7 @@ func (r *runner) Completion(t *testing.T, data tests.Completions, snippets tests
|
|||
|
||||
func (r *runner) runCompletion(t *testing.T, src span.Span) *protocol.CompletionList {
|
||||
t.Helper()
|
||||
list, err := r.server.Completion(context.Background(), &protocol.CompletionParams{
|
||||
list, err := r.server.Completion(r.ctx, &protocol.CompletionParams{
|
||||
TextDocumentPositionParams: protocol.TextDocumentPositionParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(src.URI()),
|
||||
|
@ -295,7 +298,6 @@ func summarizeCompletionItems(i int, want []source.CompletionItem, got []protoco
|
|||
}
|
||||
|
||||
func (r *runner) Format(t *testing.T, data tests.Formats) {
|
||||
ctx := context.Background()
|
||||
for _, spn := range data {
|
||||
uri := spn.URI()
|
||||
filename := uri.Filename()
|
||||
|
@ -305,7 +307,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
|||
return out, nil
|
||||
}))
|
||||
|
||||
edits, err := r.server.Formatting(context.Background(), &protocol.DocumentFormattingParams{
|
||||
edits, err := r.server.Formatting(r.ctx, &protocol.DocumentFormattingParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(uri),
|
||||
},
|
||||
|
@ -316,7 +318,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
|||
}
|
||||
continue
|
||||
}
|
||||
_, m, err := getSourceFile(ctx, r.server.session.ViewOf(uri), uri)
|
||||
_, m, err := getSourceFile(r.ctx, r.server.session.ViewOf(uri), uri)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -333,7 +335,6 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
|||
}
|
||||
|
||||
func (r *runner) Import(t *testing.T, data tests.Imports) {
|
||||
ctx := context.Background()
|
||||
for _, spn := range data {
|
||||
uri := spn.URI()
|
||||
filename := uri.Filename()
|
||||
|
@ -343,7 +344,7 @@ func (r *runner) Import(t *testing.T, data tests.Imports) {
|
|||
return out, nil
|
||||
}))
|
||||
|
||||
actions, err := r.server.CodeAction(context.Background(), &protocol.CodeActionParams{
|
||||
actions, err := r.server.CodeAction(r.ctx, &protocol.CodeActionParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(uri),
|
||||
},
|
||||
|
@ -354,7 +355,7 @@ func (r *runner) Import(t *testing.T, data tests.Imports) {
|
|||
}
|
||||
continue
|
||||
}
|
||||
_, m, err := getSourceFile(ctx, r.server.session.ViewOf(uri), uri)
|
||||
_, m, err := getSourceFile(r.ctx, r.server.session.ViewOf(uri), uri)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -393,13 +394,13 @@ func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
|||
var locs []protocol.Location
|
||||
var hover *protocol.Hover
|
||||
if d.IsType {
|
||||
locs, err = r.server.TypeDefinition(context.Background(), params)
|
||||
locs, err = r.server.TypeDefinition(r.ctx, params)
|
||||
} else {
|
||||
locs, err = r.server.Definition(context.Background(), params)
|
||||
locs, err = r.server.Definition(r.ctx, params)
|
||||
if err != nil {
|
||||
t.Fatalf("failed for %v: %v", d.Src, err)
|
||||
}
|
||||
hover, err = r.server.Hover(context.Background(), params)
|
||||
hover, err = r.server.Hover(r.ctx, params)
|
||||
}
|
||||
if err != nil {
|
||||
t.Fatalf("failed for %v: %v", d.Src, err)
|
||||
|
@ -446,7 +447,7 @@ func (r *runner) Highlight(t *testing.T, data tests.Highlights) {
|
|||
TextDocument: protocol.TextDocumentIdentifier{URI: loc.URI},
|
||||
Position: loc.Range.Start,
|
||||
}
|
||||
highlights, err := r.server.DocumentHighlight(context.Background(), params)
|
||||
highlights, err := r.server.DocumentHighlight(r.ctx, params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -492,7 +493,7 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
|||
Position: loc.Range.Start,
|
||||
},
|
||||
}
|
||||
got, err := r.server.References(context.Background(), params)
|
||||
got, err := r.server.References(r.ctx, params)
|
||||
if err != nil {
|
||||
t.Fatalf("failed for %v: %v", src, err)
|
||||
}
|
||||
|
@ -509,7 +510,6 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
|||
}
|
||||
|
||||
func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
||||
ctx := context.Background()
|
||||
for spn, newText := range data {
|
||||
tag := fmt.Sprintf("%s-rename", newText)
|
||||
|
||||
|
@ -524,7 +524,7 @@ func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
|||
t.Fatalf("failed for %v: %v", spn, err)
|
||||
}
|
||||
|
||||
workspaceEdits, err := r.server.Rename(ctx, &protocol.RenameParams{
|
||||
workspaceEdits, err := r.server.Rename(r.ctx, &protocol.RenameParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(uri),
|
||||
},
|
||||
|
@ -544,7 +544,7 @@ func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
|||
var res []string
|
||||
for uri, edits := range *workspaceEdits.Changes {
|
||||
spnURI := span.URI(uri)
|
||||
_, m, err := getSourceFile(ctx, r.server.session.ViewOf(span.URI(spnURI)), spnURI)
|
||||
_, m, err := getSourceFile(r.ctx, r.server.session.ViewOf(span.URI(spnURI)), spnURI)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
|
@ -612,7 +612,7 @@ func (r *runner) Symbol(t *testing.T, data tests.Symbols) {
|
|||
URI: string(uri),
|
||||
},
|
||||
}
|
||||
symbols, err := r.server.DocumentSymbol(context.Background(), params)
|
||||
symbols, err := r.server.DocumentSymbol(r.ctx, params)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -688,7 +688,7 @@ func (r *runner) SignatureHelp(t *testing.T, data tests.Signatures) {
|
|||
if err != nil {
|
||||
t.Fatalf("failed for %v: %v", loc, err)
|
||||
}
|
||||
gotSignatures, err := r.server.SignatureHelp(context.Background(), &protocol.TextDocumentPositionParams{
|
||||
gotSignatures, err := r.server.SignatureHelp(r.ctx, &protocol.TextDocumentPositionParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(spn.URI()),
|
||||
},
|
||||
|
@ -754,7 +754,7 @@ func (r *runner) Link(t *testing.T, data tests.Links) {
|
|||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
gotLinks, err := r.server.DocumentLink(context.Background(), &protocol.DocumentLinkParams{
|
||||
gotLinks, err := r.server.DocumentLink(r.ctx, &protocol.DocumentLinkParams{
|
||||
TextDocument: protocol.TextDocumentIdentifier{
|
||||
URI: protocol.NewURI(uri),
|
||||
},
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package protocol
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// detatch returns a context that keeps all the values of its parent context
|
||||
// but detatches from the cancellation and error handling.
|
||||
func detatchContext(ctx context.Context) context.Context { return detatchedContext{ctx} }
|
||||
|
||||
type detatchedContext struct{ parent context.Context }
|
||||
|
||||
func (v detatchedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||
func (v detatchedContext) Done() <-chan struct{} { return nil }
|
||||
func (v detatchedContext) Err() error { return nil }
|
||||
func (v detatchedContext) Value(key interface{}) interface{} { return v.parent.Value(key) }
|
|
@ -10,13 +10,14 @@ import (
|
|||
"golang.org/x/tools/internal/jsonrpc2"
|
||||
"golang.org/x/tools/internal/lsp/telemetry/trace"
|
||||
"golang.org/x/tools/internal/lsp/xlog"
|
||||
"golang.org/x/tools/internal/xcontext"
|
||||
)
|
||||
|
||||
const defaultMessageBufferSize = 20
|
||||
const defaultRejectIfOverloaded = false
|
||||
|
||||
func canceller(ctx context.Context, conn *jsonrpc2.Conn, id jsonrpc2.ID) {
|
||||
ctx = detatchContext(ctx)
|
||||
ctx = xcontext.Detach(ctx)
|
||||
ctx, span := trace.StartSpan(ctx, "protocol.canceller")
|
||||
defer span.End()
|
||||
conn.Notify(ctx, "$/cancelRequest", &CancelParams{ID: id})
|
||||
|
|
|
@ -30,9 +30,11 @@ func TestSource(t *testing.T) {
|
|||
type runner struct {
|
||||
view source.View
|
||||
data *tests.Data
|
||||
ctx context.Context
|
||||
}
|
||||
|
||||
func testSource(t *testing.T, exporter packagestest.Exporter) {
|
||||
ctx := tests.Context(t)
|
||||
data := tests.Load(t, exporter, "../testdata")
|
||||
defer data.Exported.Cleanup()
|
||||
|
||||
|
@ -40,8 +42,9 @@ func testSource(t *testing.T, exporter packagestest.Exporter) {
|
|||
cache := cache.New()
|
||||
session := cache.NewSession(log)
|
||||
r := &runner{
|
||||
view: session.NewView("source_test", span.FileURI(data.Config.Dir)),
|
||||
view: session.NewView(ctx, "source_test", span.FileURI(data.Config.Dir)),
|
||||
data: data,
|
||||
ctx: ctx,
|
||||
}
|
||||
r.view.SetEnv(data.Config.Env)
|
||||
for filename, content := range data.Config.Overlay {
|
||||
|
@ -52,11 +55,11 @@ func testSource(t *testing.T, exporter packagestest.Exporter) {
|
|||
|
||||
func (r *runner) Diagnostics(t *testing.T, data tests.Diagnostics) {
|
||||
for uri, want := range data {
|
||||
f, err := r.view.GetFile(context.Background(), uri)
|
||||
f, err := r.view.GetFile(r.ctx, uri)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
results, err := source.Diagnostics(context.Background(), r.view, f.(source.GoFile), nil)
|
||||
results, err := source.Diagnostics(r.ctx, r.view, f.(source.GoFile), nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
@ -132,7 +135,7 @@ func summarizeDiagnostics(i int, want []source.Diagnostic, got []source.Diagnost
|
|||
}
|
||||
|
||||
func (r *runner) Completion(t *testing.T, data tests.Completions, snippets tests.CompletionSnippets, items tests.CompletionItems) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for src, itemList := range data {
|
||||
var want []source.CompletionItem
|
||||
for _, pos := range itemList {
|
||||
|
@ -289,7 +292,7 @@ func summarizeCompletionItems(i int, want []source.CompletionItem, got []source.
|
|||
}
|
||||
|
||||
func (r *runner) Format(t *testing.T, data tests.Formats) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for _, spn := range data {
|
||||
uri := spn.URI()
|
||||
filename := uri.Filename()
|
||||
|
@ -327,7 +330,7 @@ func (r *runner) Format(t *testing.T, data tests.Formats) {
|
|||
}
|
||||
|
||||
func (r *runner) Import(t *testing.T, data tests.Imports) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for _, spn := range data {
|
||||
uri := spn.URI()
|
||||
filename := uri.Filename()
|
||||
|
@ -365,7 +368,7 @@ func (r *runner) Import(t *testing.T, data tests.Imports) {
|
|||
}
|
||||
|
||||
func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for _, d := range data {
|
||||
f, err := r.view.GetFile(ctx, d.Src.URI())
|
||||
if err != nil {
|
||||
|
@ -407,7 +410,7 @@ func (r *runner) Definition(t *testing.T, data tests.Definitions) {
|
|||
}
|
||||
|
||||
func (r *runner) Highlight(t *testing.T, data tests.Highlights) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for name, locations := range data {
|
||||
src := locations[0]
|
||||
f, err := r.view.GetFile(ctx, src.URI())
|
||||
|
@ -432,7 +435,7 @@ func (r *runner) Highlight(t *testing.T, data tests.Highlights) {
|
|||
}
|
||||
|
||||
func (r *runner) Reference(t *testing.T, data tests.References) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for src, itemList := range data {
|
||||
f, err := r.view.GetFile(ctx, src.URI())
|
||||
if err != nil {
|
||||
|
@ -478,7 +481,7 @@ func (r *runner) Reference(t *testing.T, data tests.References) {
|
|||
}
|
||||
|
||||
func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for spn, newText := range data {
|
||||
tag := fmt.Sprintf("%s-rename", newText)
|
||||
|
||||
|
@ -489,11 +492,11 @@ func (r *runner) Rename(t *testing.T, data tests.Renames) {
|
|||
tok := f.GetToken(ctx)
|
||||
pos := tok.Pos(spn.Start().Offset())
|
||||
|
||||
ident, err := source.Identifier(context.Background(), r.view, f.(source.GoFile), pos)
|
||||
ident, err := source.Identifier(r.ctx, r.view, f.(source.GoFile), pos)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
changes, err := ident.Rename(context.Background(), newText)
|
||||
changes, err := ident.Rename(r.ctx, newText)
|
||||
if err != nil {
|
||||
renamed := string(r.data.Golden(tag, spn.URI().Filename(), func() ([]byte, error) {
|
||||
return []byte(err.Error()), nil
|
||||
|
@ -568,7 +571,7 @@ func sortSourceTextEdits(d []source.TextEdit) {
|
|||
}
|
||||
|
||||
func (r *runner) Symbol(t *testing.T, data tests.Symbols) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for uri, expectedSymbols := range data {
|
||||
f, err := r.view.GetFile(ctx, uri)
|
||||
if err != nil {
|
||||
|
@ -632,7 +635,7 @@ func summarizeSymbols(i int, want []source.Symbol, got []source.Symbol, reason s
|
|||
}
|
||||
|
||||
func (r *runner) SignatureHelp(t *testing.T, data tests.Signatures) {
|
||||
ctx := context.Background()
|
||||
ctx := r.ctx
|
||||
for spn, expectedSignature := range data {
|
||||
f, err := r.view.GetFile(ctx, spn.URI())
|
||||
if err != nil {
|
||||
|
|
|
@ -129,7 +129,7 @@ type Cache interface {
|
|||
// A session may have many active views at any given time.
|
||||
type Session interface {
|
||||
// NewView creates a new View and returns it.
|
||||
NewView(name string, folder span.URI) View
|
||||
NewView(ctx context.Context, name string, folder span.URI) View
|
||||
|
||||
// Cache returns the cache that created this session.
|
||||
Cache() Cache
|
||||
|
|
|
@ -127,6 +127,10 @@ type Golden struct {
|
|||
Modified bool
|
||||
}
|
||||
|
||||
func Context(t testing.TB) context.Context {
|
||||
return context.Background()
|
||||
}
|
||||
|
||||
func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
||||
t.Helper()
|
||||
|
||||
|
@ -193,7 +197,7 @@ func Load(t testing.TB, exporter packagestest.Exporter, dir string) *Data {
|
|||
// Merge the exported.Config with the view.Config.
|
||||
data.Config = *data.Exported.Config
|
||||
data.Config.Fset = token.NewFileSet()
|
||||
data.Config.Context = context.Background()
|
||||
data.Config.Context = Context(nil)
|
||||
data.Config.ParseFile = func(fset *token.FileSet, filename string, src []byte) (*ast.File, error) {
|
||||
panic("ParseFile should not be called")
|
||||
}
|
||||
|
|
|
@ -31,6 +31,6 @@ func (s *Server) changeFolders(ctx context.Context, event protocol.WorkspaceFold
|
|||
}
|
||||
|
||||
func (s *Server) addView(ctx context.Context, name string, uri span.URI) error {
|
||||
s.session.NewView(name, uri)
|
||||
s.session.NewView(ctx, name, uri)
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -1,21 +0,0 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package memoize
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// detatch returns a context that keeps all the values of its parent context
|
||||
// but detatches from the cancellation and error handling.
|
||||
func detatchContext(ctx context.Context) context.Context { return detatchedContext{ctx} }
|
||||
|
||||
type detatchedContext struct{ parent context.Context }
|
||||
|
||||
func (v detatchedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||
func (v detatchedContext) Done() <-chan struct{} { return nil }
|
||||
func (v detatchedContext) Err() error { return nil }
|
||||
func (v detatchedContext) Value(key interface{}) interface{} { return v.parent.Value(key) }
|
|
@ -19,6 +19,8 @@ import (
|
|||
"runtime"
|
||||
"sync"
|
||||
"unsafe"
|
||||
|
||||
"golang.org/x/tools/internal/xcontext"
|
||||
)
|
||||
|
||||
// Store binds keys to functions, returning handles that can be used to access
|
||||
|
@ -180,7 +182,7 @@ func (e *entry) get(ctx context.Context, f Function) (interface{}, bool) {
|
|||
// Use the background context to avoid canceling the function.
|
||||
// The function cannot be canceled even if the context is canceled
|
||||
// because multiple goroutines may depend on it.
|
||||
value = f(detatchContext(ctx))
|
||||
value = f(xcontext.Detach(ctx))
|
||||
|
||||
// The function has completed. Update the value in the entry.
|
||||
e.mu.Lock()
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
// Copyright 2019 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
// Package xcontext is a package to offer the extra functionality we need
|
||||
// from contexts that is not available from the standard context package.
|
||||
package xcontext
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Detach returns a context that keeps all the values of its parent context
|
||||
// but detaches from the cancellation and error handling.
|
||||
func Detach(ctx context.Context) context.Context { return detachedContext{ctx} }
|
||||
|
||||
type detachedContext struct{ parent context.Context }
|
||||
|
||||
func (v detachedContext) Deadline() (time.Time, bool) { return time.Time{}, false }
|
||||
func (v detachedContext) Done() <-chan struct{} { return nil }
|
||||
func (v detachedContext) Err() error { return nil }
|
||||
func (v detachedContext) Value(key interface{}) interface{} { return v.parent.Value(key) }
|
Loading…
Reference in New Issue