Skip to content

Commit 6e1b77e

Browse files
committed
[gopls-release-branch.0.4] all: merge master in for gopls/v0.4.1
Change-Id: Icac9c3c2ee24e194b0f5e6e6f08a5b087e03268e
2 parents 5fc56a9 + 625332f commit 6e1b77e

File tree

248 files changed

+8545
-7216
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

248 files changed

+8545
-7216
lines changed

cmd/goimports/goimports.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,12 @@ func processFile(filename string, in io.Reader, out io.Writer, argType argumentT
160160
// filename is "<standard input>"
161161
return errors.New("can't use -w on stdin")
162162
}
163-
err = ioutil.WriteFile(filename, res, 0)
163+
// On Windows, we need to re-set the permissions from the file. See golang/go#38225.
164+
var perms os.FileMode
165+
if fi, err := os.Stat(filename); err == nil {
166+
perms = fi.Mode() & os.ModePerm
167+
}
168+
err = ioutil.WriteFile(filename, res, perms)
164169
if err != nil {
165170
return err
166171
}

go/analysis/analysistest/analysistest.go

Lines changed: 97 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
package analysistest
33

44
import (
5+
"bytes"
56
"fmt"
67
"go/format"
78
"go/token"
@@ -20,8 +21,10 @@ import (
2021
"golang.org/x/tools/go/analysis/internal/checker"
2122
"golang.org/x/tools/go/packages"
2223
"golang.org/x/tools/internal/lsp/diff"
24+
"golang.org/x/tools/internal/lsp/diff/myers"
2325
"golang.org/x/tools/internal/span"
2426
"golang.org/x/tools/internal/testenv"
27+
"golang.org/x/tools/txtar"
2528
)
2629

2730
// WriteFiles is a helper function that creates a temporary directory
@@ -64,10 +67,38 @@ type Testing interface {
6467
Errorf(format string, args ...interface{})
6568
}
6669

70+
// RunWithSuggestedFixes behaves like Run, but additionally verifies suggested fixes.
71+
// It uses golden files placed alongside the source code under analysis:
72+
// suggested fixes for code in example.go will be compared against example.go.golden.
73+
//
74+
// Golden files can be formatted in one of two ways: as plain Go source code, or as txtar archives.
75+
// In the first case, all suggested fixes will be applied to the original source, which will then be compared against the golden file.
76+
// In the second case, suggested fixes will be grouped by their messages, and each set of fixes will be applied and tested separately.
77+
// Each section in the archive corresponds to a single message.
78+
//
79+
// A golden file using txtar may look like this:
80+
// -- turn into single negation --
81+
// package pkg
82+
//
83+
// func fn(b1, b2 bool) {
84+
// if !b1 { // want `negating a boolean twice`
85+
// println()
86+
// }
87+
// }
88+
//
89+
// -- remove double negation --
90+
// package pkg
91+
//
92+
// func fn(b1, b2 bool) {
93+
// if b1 { // want `negating a boolean twice`
94+
// println()
95+
// }
96+
// }
6797
func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns ...string) []*Result {
6898
r := Run(t, dir, a, patterns...)
6999

70-
fileEdits := make(map[*token.File][]diff.TextEdit)
100+
// file -> message -> edits
101+
fileEdits := make(map[*token.File]map[string][]diff.TextEdit)
71102
fileContents := make(map[*token.File][]byte)
72103

73104
// Validate edits, prepare the fileEdits map and read the file contents.
@@ -100,7 +131,11 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
100131
if err != nil {
101132
t.Errorf("error converting edit to span %s: %v", file.Name(), err)
102133
}
103-
fileEdits[file] = append(fileEdits[file], diff.TextEdit{
134+
135+
if _, ok := fileEdits[file]; !ok {
136+
fileEdits[file] = make(map[string][]diff.TextEdit)
137+
}
138+
fileEdits[file][sf.Message] = append(fileEdits[file][sf.Message], diff.TextEdit{
104139
Span: spn,
105140
NewText: string(edit.NewText),
106141
})
@@ -109,25 +144,77 @@ func RunWithSuggestedFixes(t Testing, dir string, a *analysis.Analyzer, patterns
109144
}
110145
}
111146

112-
for file, edits := range fileEdits {
147+
for file, fixes := range fileEdits {
113148
// Get the original file contents.
114149
orig, ok := fileContents[file]
115150
if !ok {
116151
t.Errorf("could not find file contents for %s", file.Name())
117152
continue
118153
}
119-
out := diff.ApplyEdits(string(orig), edits)
154+
120155
// Get the golden file and read the contents.
121-
want, err := ioutil.ReadFile(file.Name() + ".golden")
156+
ar, err := txtar.ParseFile(file.Name() + ".golden")
122157
if err != nil {
123158
t.Errorf("error reading %s.golden: %v", file.Name(), err)
124-
}
125-
formatted, err := format.Source([]byte(out))
126-
if err != nil {
127159
continue
128160
}
129-
if string(want) != string(formatted) {
130-
t.Errorf("suggested fixes failed for %s, expected:\n%#v\ngot:\n%#v", file.Name(), string(want), string(formatted))
161+
162+
if len(ar.Files) > 0 {
163+
// one virtual file per kind of suggested fix
164+
165+
if len(ar.Comment) != 0 {
166+
// we allow either just the comment, or just virtual
167+
// files, not both. it is not clear how "both" should
168+
// behave.
169+
t.Errorf("%s.golden has leading comment; we don't know what to do with it", file.Name())
170+
continue
171+
}
172+
173+
for sf, edits := range fixes {
174+
found := false
175+
for _, vf := range ar.Files {
176+
if vf.Name == sf {
177+
found = true
178+
out := diff.ApplyEdits(string(orig), edits)
179+
// the file may contain multiple trailing
180+
// newlines if the user places empty lines
181+
// between files in the archive. normalize
182+
// this to a single newline.
183+
want := string(bytes.TrimRight(vf.Data, "\n")) + "\n"
184+
formatted, err := format.Source([]byte(out))
185+
if err != nil {
186+
continue
187+
}
188+
if want != string(formatted) {
189+
d := myers.ComputeEdits("", want, string(formatted))
190+
t.Errorf("suggested fixes failed for %s:\n%s", file.Name(), diff.ToUnified(fmt.Sprintf("%s.golden [%s]", file.Name(), sf), "actual", want, d))
191+
}
192+
break
193+
}
194+
}
195+
if !found {
196+
t.Errorf("no section for suggested fix %q in %s.golden", sf, file.Name())
197+
}
198+
}
199+
} else {
200+
// all suggested fixes are represented by a single file
201+
202+
var catchallEdits []diff.TextEdit
203+
for _, edits := range fixes {
204+
catchallEdits = append(catchallEdits, edits...)
205+
}
206+
207+
out := diff.ApplyEdits(string(orig), catchallEdits)
208+
want := string(ar.Comment)
209+
210+
formatted, err := format.Source([]byte(out))
211+
if err != nil {
212+
continue
213+
}
214+
if want != string(formatted) {
215+
d := myers.ComputeEdits("", want, string(formatted))
216+
t.Errorf("suggested fixes failed for %s:\n%s", file.Name(), diff.ToUnified(file.Name()+".golden", "actual", want, d))
217+
}
131218
}
132219
}
133220
return r

go/analysis/internal/analysisflags/flags.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ func (tree JSONTree) Add(fset *token.FileSet, id, name string, diags []analysis.
382382
func (tree JSONTree) Print() {
383383
data, err := json.MarshalIndent(tree, "", "\t")
384384
if err != nil {
385-
log.Panicf("internal error: JSON marshalling failed: %v", err)
385+
log.Panicf("internal error: JSON marshaling failed: %v", err)
386386
}
387387
fmt.Printf("%s\n", data)
388388
}

go/ast/inspector/inspector.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,11 @@ func traverse(files []*ast.File) []event {
150150
extent += int(f.End() - f.Pos())
151151
}
152152
// This estimate is based on the net/http package.
153-
events := make([]event, 0, extent*33/100)
153+
capacity := extent * 33 / 100
154+
if capacity > 1e6 {
155+
capacity = 1e6 // impose some reasonable maximum
156+
}
157+
events := make([]event, 0, capacity)
154158

155159
var stack []event
156160
for _, f := range files {

go/gcexportdata/gcexportdata.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,15 +85,11 @@ func Read(in io.Reader, fset *token.FileSet, imports map[string]*types.Package,
8585
return gcimporter.ImportData(imports, path, path, bytes.NewReader(data))
8686
}
8787

88-
// The indexed export format starts with an 'i'; the older
89-
// binary export format starts with a 'c', 'd', or 'v'
90-
// (from "version"). Select appropriate importer.
91-
if len(data) > 0 && data[0] == 'i' {
92-
_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)
93-
return pkg, err
88+
// The indexed export format starts with an 'i'.
89+
if len(data) == 0 || data[0] != 'i' {
90+
return nil, fmt.Errorf("unknown export data format")
9491
}
95-
96-
_, pkg, err := gcimporter.BImportData(fset, imports, data, path)
92+
_, pkg, err := gcimporter.IImportData(fset, imports, data[1:], path)
9793
return pkg, err
9894
}
9995

0 commit comments

Comments
 (0)