Skip to content

Commit 34db5bc

Browse files
committed
gopls: initial support for godebug directive in go.mod and go.work
For now, incorporate godebug support by just updating x/mod and write some tests. Diagnostics are mispositioned due to golang/go#67623. While writing tests, I realized that the expect package still did not support go.work files. Add this missing support. Also, remove a stale comment from go.mod comment extraction, and simplify. Fixes golang/go#67583 Change-Id: I9d9bb53824b8c817ee18f51a0cfca63842565513 Reviewed-on: https://go-review.googlesource.com/c/tools/+/588055 Reviewed-by: Alan Donovan <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 56f50e3 commit 34db5bc

File tree

10 files changed

+187
-23
lines changed

10 files changed

+187
-23
lines changed

go/expect/expect.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
/*
66
Package expect provides support for interpreting structured comments in Go
7-
source code as test expectations.
7+
source code (including go.mod and go.work files) as test expectations.
88
99
This is primarily intended for writing tests of things that process Go source
1010
files, although it does not directly depend on the testing package.

go/expect/expect_test.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,14 @@ func TestMarker(t *testing.T) {
5050
"βMarker": "require golang.org/modfile v0.0.0",
5151
},
5252
},
53+
{
54+
filename: "testdata/go.fake.work",
55+
expectNotes: 2,
56+
expectMarkers: map[string]string{
57+
"αMarker": "1.23.0",
58+
"βMarker": "αβ",
59+
},
60+
},
5361
} {
5462
t.Run(tt.filename, func(t *testing.T) {
5563
content, err := os.ReadFile(tt.filename)

go/expect/extract.go

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func Parse(fset *token.FileSet, filename string, content []byte) ([]*Note, error
5454
}
5555
f := fset.AddFile(filename, -1, len(content))
5656
f.SetLinesForContent(content)
57-
notes, err := extractMod(fset, file)
57+
notes, err := extractModWork(fset, file.Syntax.Stmt)
5858
if err != nil {
5959
return nil, err
6060
}
@@ -64,39 +64,45 @@ func Parse(fset *token.FileSet, filename string, content []byte) ([]*Note, error
6464
note.Pos += token.Pos(f.Base())
6565
}
6666
return notes, nil
67+
case ".work":
68+
file, err := modfile.ParseWork(filename, content, nil)
69+
if err != nil {
70+
return nil, err
71+
}
72+
f := fset.AddFile(filename, -1, len(content))
73+
f.SetLinesForContent(content)
74+
notes, err := extractModWork(fset, file.Syntax.Stmt)
75+
if err != nil {
76+
return nil, err
77+
}
78+
// As with go.mod files, we need to compute a synthetic token.Pos.
79+
for _, note := range notes {
80+
note.Pos += token.Pos(f.Base())
81+
}
82+
return notes, nil
6783
}
6884
return nil, nil
6985
}
7086

71-
// extractMod collects all the notes present in a go.mod file.
87+
// extractModWork collects all the notes present in a go.mod file or go.work
88+
// file, by way of the shared modfile.Expr statement node.
89+
//
7290
// Each comment whose text starts with @ is parsed as a comma-separated
7391
// sequence of notes.
7492
// See the package documentation for details about the syntax of those
7593
// notes.
7694
// Only allow notes to appear with the following format: "//@mark()" or // @mark()
77-
func extractMod(fset *token.FileSet, file *modfile.File) ([]*Note, error) {
95+
func extractModWork(fset *token.FileSet, exprs []modfile.Expr) ([]*Note, error) {
7896
var notes []*Note
79-
for _, stmt := range file.Syntax.Stmt {
97+
for _, stmt := range exprs {
8098
comment := stmt.Comment()
8199
if comment == nil {
82100
continue
83101
}
84-
// Handle the case for markers of `// indirect` to be on the line before
85-
// the require statement.
86-
// TODO(golang/go#36894): have a more intuitive approach for // indirect
87-
for _, cmt := range comment.Before {
88-
text, adjust := getAdjustedNote(cmt.Token)
89-
if text == "" {
90-
continue
91-
}
92-
parsed, err := parse(fset, token.Pos(int(cmt.Start.Byte)+adjust), text)
93-
if err != nil {
94-
return nil, err
95-
}
96-
notes = append(notes, parsed...)
97-
}
98-
// Handle the normal case for markers on the same line.
99-
for _, cmt := range comment.Suffix {
102+
var allComments []modfile.Comment
103+
allComments = append(allComments, comment.Before...)
104+
allComments = append(allComments, comment.Suffix...)
105+
for _, cmt := range allComments {
100106
text, adjust := getAdjustedNote(cmt.Token)
101107
if text == "" {
102108
continue

go/expect/testdata/go.fake.work

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// This file is named go.fake.mod so it does not define a real module, which
2+
// would make the contents of this directory unavailable to the test when run
3+
// from outside the repository.
4+
5+
go 1.23.0 //@mark(αMarker, "1.23.0")
6+
7+
use ./αβ //@mark(βMarker, "αβ")

gopls/go.mod

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ go 1.19 // => default GODEBUG has gotypesalias=0
55
require (
66
github.com/google/go-cmp v0.6.0
77
github.com/jba/templatecheck v0.7.0
8-
golang.org/x/mod v0.17.0
8+
golang.org/x/mod v0.17.1-0.20240514174713-c0bdc7bd01c9
99
golang.org/x/sync v0.7.0
1010
golang.org/x/telemetry v0.0.0-20240521205824-bda55230c457
1111
golang.org/x/text v0.15.0

gopls/go.sum

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,9 @@ golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v
1616
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338 h1:2O2DON6y3XMJiQRAS1UWU+54aec2uopH3x7MAiqGW6Y=
1717
golang.org/x/exp/typeparams v0.0.0-20221212164502-fae10dda9338/go.mod h1:AbB0pIl9nAr9wVwH+Z2ZpaocVmF5I4GyWCDIsVjR0bk=
1818
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
19-
golang.org/x/mod v0.17.0 h1:zY54UmvipHiNd+pm+m0x9KhZ9hl1/7QNMyxXbc6ICqA=
2019
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
20+
golang.org/x/mod v0.17.1-0.20240514174713-c0bdc7bd01c9 h1:EfMABMgrJ8+hRjLvhUzJkLKgFv3lYAglGXczg5ggNyk=
21+
golang.org/x/mod v0.17.1-0.20240514174713-c0bdc7bd01c9/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
2122
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
2223
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
2324
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
This test basic gopls functionality in a workspace with a godebug
2+
directive in its modfile.
3+
4+
-- flags --
5+
-min_go=go1.23
6+
7+
-- go.mod --
8+
module example.com/m
9+
10+
go 1.23
11+
12+
godebug (
13+
gotypesalias=0
14+
)
15+
godebug gotypesalias=1
16+
17+
-- a/a.go --
18+
package a
19+
20+
import "example.com/m/b"
21+
22+
const A = b.B //@def("B", B)
23+
24+
-- b/b.go --
25+
package b
26+
27+
const B = 42 //@loc(B, "B")
28+
29+
-- format/go.mod --
30+
module example.com/m/format //@format(formatted)
31+
32+
godebug (
33+
gotypesalias=0
34+
)
35+
godebug gotypesalias=1
36+
-- @formatted --
37+
module example.com/m/format //@format(formatted)
38+
39+
godebug (
40+
gotypesalias=0
41+
)
42+
43+
godebug gotypesalias=1
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
This test checks that we surface the error for unexpected godebug values.
2+
3+
TODO(golang/go#67623): the diagnostic should be on the bad godebug value.
4+
5+
-- flags --
6+
-min_go=go1.23
7+
-errors_ok
8+
9+
-- go.mod --
10+
module example.com/m //@diag("module", re`unknown godebug "gotypealias"`)
11+
12+
go 1.23
13+
14+
godebug (
15+
gotypealias=0 // misspelled
16+
)
17+
godebug gotypesalias=1
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
This test basic gopls functionality in a workspace with a godebug
2+
directive in its modfile.
3+
4+
-- flags --
5+
-min_go=go1.23
6+
7+
-- a/go.work --
8+
go 1.23
9+
10+
use .
11+
12+
godebug (
13+
gotypesalias=0
14+
)
15+
godebug gotypesalias=1
16+
17+
-- a/go.mod --
18+
module example.com/a
19+
20+
go 1.23
21+
22+
-- a/a.go --
23+
package a
24+
25+
import "example.com/a/b"
26+
27+
const A = b.B //@def("B", B)
28+
29+
-- a/b/b.go --
30+
package b
31+
32+
const B = 42 //@loc(B, "B")
33+
34+
-- format/go.work --
35+
go 1.23 //@format(formatted)
36+
37+
use .
38+
39+
godebug (
40+
gotypesalias=0
41+
)
42+
godebug gotypesalias=1
43+
44+
-- @formatted --
45+
go 1.23 //@format(formatted)
46+
47+
use .
48+
49+
godebug (
50+
gotypesalias=0
51+
)
52+
53+
godebug gotypesalias=1
54+
-- format/go.mod --
55+
module example.com/format
56+
57+
go 1.23
58+
59+
-- format/p.go --
60+
package format
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
This test checks that we surface the error for unexpected godebug values.
2+
3+
TODO(golang/go#67623): the diagnostic should be on the bad godebug value.
4+
5+
-- flags --
6+
-min_go=go1.23
7+
-errors_ok
8+
9+
-- go.work --
10+
go 1.23
11+
12+
use .
13+
14+
godebug (
15+
gotypealias=0 // misspelled
16+
)
17+
godebug gotypesalias=1
18+
19+
-- go.mod --
20+
module example.com/m //@diag("module", re`unknown godebug "gotypealias"`)
21+
22+
go 1.23

0 commit comments

Comments
 (0)