Skip to content

Commit ab2804f

Browse files
committed
internal/lsp: don't offer suggested fixes for generated files
As suggested on Slack, a better fix for golang/go#38467 would be to hide suggested fixes on generated files. This way, the diagnostics are still visible but files are not unintentionally modified. Also, deleted the SuggestedFixes field on source.Diagnostic, since it's entirely unused. Change-Id: I10756471e0f913465b1cccd7f222eea0f4de77fe Reviewed-on: https://go-review.googlesource.com/c/tools/+/230999 Run-TryBot: Rebecca Stambler <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Heschi Kreinick <[email protected]>
1 parent d351ea0 commit ab2804f

File tree

5 files changed

+74
-28
lines changed

5 files changed

+74
-28
lines changed

internal/lsp/code_action.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ func (s *Server) codeAction(ctx context.Context, params *protocol.CodeActionPara
6767
})
6868
}
6969
case source.Go:
70+
// Don't suggest fixes for generated files, since they are generally
71+
// not useful and some editors may apply them automatically on save.
72+
if source.IsGenerated(ctx, snapshot, uri) {
73+
return nil, nil
74+
}
7075
diagnostics := params.Context.Diagnostics
7176

7277
// First, process any missing imports and pair them with the

internal/lsp/fake/editor.go

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -502,16 +502,16 @@ func (e *Editor) OrganizeImports(ctx context.Context, path string) error {
502502

503503
// ApplyQuickFixes requests and performs the quickfix codeAction.
504504
func (e *Editor) ApplyQuickFixes(ctx context.Context, path string, diagnostics []protocol.Diagnostic) error {
505-
return e.codeAction(ctx, path, diagnostics, protocol.QuickFix)
505+
return e.codeAction(ctx, path, diagnostics, protocol.QuickFix, protocol.SourceFixAll)
506506
}
507507

508-
func (e *Editor) codeAction(ctx context.Context, path string, diagnostics []protocol.Diagnostic, only protocol.CodeActionKind) error {
508+
func (e *Editor) codeAction(ctx context.Context, path string, diagnostics []protocol.Diagnostic, only ...protocol.CodeActionKind) error {
509509
if e.server == nil {
510510
return nil
511511
}
512512
params := &protocol.CodeActionParams{}
513513
params.TextDocument.URI = e.ws.URI(path)
514-
params.Context.Only = []protocol.CodeActionKind{only}
514+
params.Context.Only = only
515515
if diagnostics != nil {
516516
params.Context.Diagnostics = diagnostics
517517
}
@@ -522,17 +522,25 @@ func (e *Editor) codeAction(ctx context.Context, path string, diagnostics []prot
522522
e.mu.Lock()
523523
defer e.mu.Unlock()
524524
for _, action := range actions {
525-
if action.Kind == only {
526-
for _, change := range action.Edit.DocumentChanges {
527-
path := e.ws.URIToPath(change.TextDocument.URI)
528-
if float64(e.buffers[path].version) != change.TextDocument.Version {
529-
// Skip edits for old versions.
530-
continue
531-
}
532-
edits := convertEdits(change.Edits)
533-
if err := e.editBufferLocked(ctx, path, edits); err != nil {
534-
return fmt.Errorf("editing buffer %q: %v", path, err)
535-
}
525+
var match bool
526+
for _, o := range only {
527+
if action.Kind == o {
528+
match = true
529+
break
530+
}
531+
}
532+
if !match {
533+
continue
534+
}
535+
for _, change := range action.Edit.DocumentChanges {
536+
path := e.ws.URIToPath(change.TextDocument.URI)
537+
if float64(e.buffers[path].version) != change.TextDocument.Version {
538+
// Skip edits for old versions.
539+
continue
540+
}
541+
edits := convertEdits(change.Edits)
542+
if err := e.editBufferLocked(ctx, path, edits); err != nil {
543+
return fmt.Errorf("editing buffer %q: %v", path, err)
536544
}
537545
}
538546
}

internal/lsp/mod/diagnostics.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,9 @@ func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[source.File
4444
}
4545
for _, e := range parseErrors {
4646
diag := &source.Diagnostic{
47-
Message: e.Message,
48-
Range: e.Range,
49-
SuggestedFixes: e.SuggestedFixes,
50-
Source: e.Category,
47+
Message: e.Message,
48+
Range: e.Range,
49+
Source: e.Category,
5150
}
5251
if e.Category == "syntax" {
5352
diag.Severity = protocol.SeverityError

internal/lsp/regtest/diagnostics_test.go

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"golang.org/x/tools/internal/lsp"
1111
"golang.org/x/tools/internal/lsp/fake"
1212
"golang.org/x/tools/internal/lsp/protocol"
13+
"golang.org/x/tools/internal/lsp/tests"
1314
)
1415

1516
// Use mod.com for all go.mod files due to golang/go#35230.
@@ -403,3 +404,39 @@ var X = 0
403404
env.Await(EmptyDiagnostics("main.go"))
404405
}, WithEnv("GOFLAGS=-tags=foo"))
405406
}
407+
408+
func TestNoSuggestedFixesForGeneratedFiles_Issue38467(t *testing.T) {
409+
const generated = `
410+
-- go.mod --
411+
module mod.com
412+
413+
-- main.go --
414+
package main
415+
416+
// Code generated by generator.go. DO NOT EDIT.
417+
418+
func _() {
419+
for i, _ := range []string{} {
420+
_ = i
421+
}
422+
}
423+
`
424+
runner.Run(t, generated, func(t *testing.T, env *Env) {
425+
env.OpenFile("main.go")
426+
original := env.ReadWorkspaceFile("main.go")
427+
metBy := env.Await(
428+
DiagnosticAt("main.go", 5, 8),
429+
)
430+
d, ok := metBy[0].(*protocol.PublishDiagnosticsParams)
431+
if !ok {
432+
t.Fatalf("unexpected met by result %v (%T)", metBy, metBy)
433+
}
434+
// Apply fixes and save the buffer.
435+
env.ApplyQuickFixes("main.go", d.Diagnostics)
436+
env.SaveBuffer("main.go")
437+
fixed := env.ReadWorkspaceFile("main.go")
438+
if original != fixed {
439+
t.Fatalf("generated file was changed by quick fixes:\n%s", tests.Diff(original, fixed))
440+
}
441+
})
442+
}

internal/lsp/source/diagnostics.go

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ type Diagnostic struct {
2727
Severity protocol.DiagnosticSeverity
2828
Tags []protocol.DiagnosticTag
2929

30-
SuggestedFixes []SuggestedFix
31-
Related []RelatedInformation
30+
Related []RelatedInformation
3231
}
3332

3433
type SuggestedFix struct {
@@ -295,13 +294,12 @@ func analyses(ctx context.Context, snapshot Snapshot, reports map[FileIdentity][
295294
tags = append(tags, protocol.Unnecessary)
296295
}
297296
if err := addReports(snapshot, reports, e.URI, &Diagnostic{
298-
Range: e.Range,
299-
Message: e.Message,
300-
Source: e.Category,
301-
Severity: protocol.SeverityWarning,
302-
Tags: tags,
303-
SuggestedFixes: e.SuggestedFixes,
304-
Related: e.Related,
297+
Range: e.Range,
298+
Message: e.Message,
299+
Source: e.Category,
300+
Severity: protocol.SeverityWarning,
301+
Tags: tags,
302+
Related: e.Related,
305303
}); err != nil {
306304
return err
307305
}
@@ -344,7 +342,6 @@ func addReports(snapshot Snapshot, reports map[FileIdentity][]*Diagnostic, uri s
344342
if d1.Message != d2.Message {
345343
continue
346344
}
347-
reports[identity][i].SuggestedFixes = append(reports[identity][i].SuggestedFixes, d1.SuggestedFixes...)
348345
reports[identity][i].Tags = append(reports[identity][i].Tags, d1.Tags...)
349346
}
350347
return nil

0 commit comments

Comments
 (0)