1
0
mirror of https://github.com/golang/go synced 2024-10-01 05:18:33 -06:00
go/internal/lsp/regtest/wrappers.go
Rob Findley 4c83a7e07a internal/lsp/fake: add regexp search and replace
Expressing regtests in terms of textual coordinates is hard to read: the
reader ends up counting lines and characters to understand the text edit
or assertion.

To address, this, add two new functions for fake.Editor: RegexpSearch
and RegexpReplace, as well as a symmetric RegexpSearch function for
workspace files and wrappers for regtext.Env.

This allows expressing edits as well as buffer locations in terms of
easily scannable regexps.

An alternative solution to this problem is to integrate markers ala
packagestest. I tried this, but it ended up being cumbersome to
implement and less usable than regexps, due to the static nature of
markers: after the buffer has been edited all markers must be
updated.

Updates golang/go#36879

Change-Id: Iad087cf0d529737034197beef7b729816a159c69
Reviewed-on: https://go-review.googlesource.com/c/tools/+/224757
Run-TryBot: Robert Findley <rfindley@google.com>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Heschi Kreinick <heschi@google.com>
2020-03-24 20:17:55 +00:00

134 lines
3.5 KiB
Go

// Copyright 2020 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 regtest
import (
"golang.org/x/tools/internal/lsp/fake"
)
// RemoveFileFromWorkspace deletes a file on disk but does nothing in the
// editor. It calls t.Fatal on any error.
func (e *Env) RemoveFileFromWorkspace(name string) {
e.t.Helper()
if err := e.W.RemoveFile(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// ReadWorkspaceFile reads a file from the workspace, calling t.Fatal on any
// error.
func (e *Env) ReadWorkspaceFile(name string) string {
e.t.Helper()
content, err := e.W.ReadFile(name)
if err != nil {
e.t.Fatal(err)
}
return content
}
// OpenFile opens a file in the editor, calling t.Fatal on any error.
func (e *Env) OpenFile(name string) {
e.t.Helper()
if err := e.E.OpenFile(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// CreateBuffer creates a buffer in the editor, calling t.Fatal on any error.
func (e *Env) CreateBuffer(name string, content string) {
e.t.Helper()
if err := e.E.CreateBuffer(e.ctx, name, content); err != nil {
e.t.Fatal(err)
}
}
// CloseBuffer closes an editor buffer without saving, calling t.Fatal on any
// error.
func (e *Env) CloseBuffer(name string) {
e.t.Helper()
if err := e.E.CloseBuffer(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// EditBuffer applies edits to an editor buffer, calling t.Fatal on any error.
func (e *Env) EditBuffer(name string, edits ...fake.Edit) {
e.t.Helper()
if err := e.E.EditBuffer(e.ctx, name, edits); err != nil {
e.t.Fatal(err)
}
}
// RegexpSearch returns the starting position of the first match for re in the
// buffer specified by name, calling t.Fatal on any error. It first searches
// for the position in open buffers, then in workspace files.
func (e *Env) RegexpSearch(name, re string) fake.Pos {
e.t.Helper()
pos, err := e.E.RegexpSearch(name, re)
if err == fake.ErrUnknownBuffer {
pos, err = e.W.RegexpSearch(name, re)
}
if err != nil {
e.t.Fatalf("RegexpSearch: %v", err)
}
return pos
}
// RegexpReplace replaces the first group in the first match of regexpStr with
// the replace text, calling t.Fatal on any error.
func (e *Env) RegexpReplace(name, regexpStr, replace string) {
e.t.Helper()
if err := e.E.RegexpReplace(e.ctx, name, regexpStr, replace); err != nil {
e.t.Fatalf("RegexpReplace: %v", err)
}
}
// SaveBuffer saves an editor buffer, calling t.Fatal on any error.
func (e *Env) SaveBuffer(name string) {
e.t.Helper()
if err := e.E.SaveBuffer(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// GoToDefinition goes to definition in the editor, calling t.Fatal on any
// error.
func (e *Env) GoToDefinition(name string, pos fake.Pos) (string, fake.Pos) {
e.t.Helper()
n, p, err := e.E.GoToDefinition(e.ctx, name, pos)
if err != nil {
e.t.Fatal(err)
}
return n, p
}
// FormatBuffer formats the editor buffer, calling t.Fatal on any error.
func (e *Env) FormatBuffer(name string) {
e.t.Helper()
if err := e.E.FormatBuffer(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// OrganizeImports processes the source.organizeImports codeAction, calling
// t.Fatal on any error.
func (e *Env) OrganizeImports(name string) {
e.t.Helper()
if err := e.E.OrganizeImports(e.ctx, name); err != nil {
e.t.Fatal(err)
}
}
// CloseEditor shuts down the editor, calling t.Fatal on any error.
func (e *Env) CloseEditor() {
e.t.Helper()
if err := e.E.Shutdown(e.ctx); err != nil {
e.t.Fatal(err)
}
if err := e.E.Exit(e.ctx); err != nil {
e.t.Fatal(err)
}
}