Skip to content

Commit c90efee

Browse files
author
Bryan C. Mills
committed
modfile: prefer to add a new 'go' directive after the 'module' directive
The previous behavior put the new 'go' directive at the end of the file, which is not where anybody actually puts it, and that in turn complicates the regression tests for golang/go#34822. Updates golang/go#34822 Change-Id: Ic275eb6999fc0db7e72e2d9636b77c9e3d919539 Reviewed-on: https://go-review.googlesource.com/c/mod/+/205497 Run-TryBot: Bryan C. Mills <[email protected]> TryBot-Result: Gobot Gobot <[email protected]> Reviewed-by: Jay Conrod <[email protected]>
1 parent e1e0e08 commit c90efee

File tree

3 files changed

+116
-2
lines changed

3 files changed

+116
-2
lines changed

modfile/read.go

+40-1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,19 @@ func (x *FileSyntax) Span() (start, end Position) {
9090
return start, end
9191
}
9292

93+
// addLine adds a line containing the given tokens to the file.
94+
//
95+
// If the first token of the hint matches the first token of the
96+
// line, the new line is added at the end of the block containing hint,
97+
// extracting hint into a new block if it is not yet in one.
98+
//
99+
// If the hint is non-nil buts its first token does not match,
100+
// the new line is added after the block containing hint
101+
// (or hint itself, if not in a block).
102+
//
103+
// If no hint is provided, addLine appends the line to the end of
104+
// the last block with a matching first token,
105+
// or to the end of the file if no such block exists.
93106
func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line {
94107
if hint == nil {
95108
// If no hint given, add to the last statement of the given type.
@@ -111,11 +124,27 @@ func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line {
111124
}
112125
}
113126

127+
newLineAfter := func(i int) *Line {
128+
new := &Line{Token: tokens}
129+
if i == len(x.Stmt) {
130+
x.Stmt = append(x.Stmt, new)
131+
} else {
132+
x.Stmt = append(x.Stmt, nil)
133+
copy(x.Stmt[i+2:], x.Stmt[i+1:])
134+
x.Stmt[i+1] = new
135+
}
136+
return new
137+
}
138+
114139
if hint != nil {
115140
for i, stmt := range x.Stmt {
116141
switch stmt := stmt.(type) {
117142
case *Line:
118143
if stmt == hint {
144+
if stmt.Token == nil || stmt.Token[0] != tokens[0] {
145+
return newLineAfter(i)
146+
}
147+
119148
// Convert line to line block.
120149
stmt.InBlock = true
121150
block := &LineBlock{Token: stmt.Token[:1], Line: []*Line{stmt}}
@@ -125,15 +154,25 @@ func (x *FileSyntax) addLine(hint Expr, tokens ...string) *Line {
125154
block.Line = append(block.Line, new)
126155
return new
127156
}
157+
128158
case *LineBlock:
129159
if stmt == hint {
160+
if stmt.Token[0] != tokens[0] {
161+
return newLineAfter(i)
162+
}
163+
130164
new := &Line{Token: tokens[1:], InBlock: true}
131165
stmt.Line = append(stmt.Line, new)
132166
return new
133167
}
168+
134169
for j, line := range stmt.Line {
135170
if line == hint {
136-
// Add new line after hint.
171+
if stmt.Token[0] != tokens[0] {
172+
return newLineAfter(i)
173+
}
174+
175+
// Add new line after hint within the block.
137176
stmt.Line = append(stmt.Line, nil)
138177
copy(stmt.Line[j+2:], stmt.Line[j+1:])
139178
new := &Line{Token: tokens[1:], InBlock: true}

modfile/rule.go

+5-1
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,13 @@ func (f *File) AddGoStmt(version string) error {
505505
return fmt.Errorf("invalid language version string %q", version)
506506
}
507507
if f.Go == nil {
508+
var hint Expr
509+
if f.Module != nil && f.Module.Syntax != nil {
510+
hint = f.Module.Syntax
511+
}
508512
f.Go = &Go{
509513
Version: version,
510-
Syntax: f.Syntax.addLine(nil, "go", version),
514+
Syntax: f.Syntax.addLine(hint, "go", version),
511515
}
512516
} else {
513517
f.Go.Version = version

modfile/rule_test.go

+71
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,47 @@ var setRequireTests = []struct {
9696
},
9797
}
9898

99+
var addGoTests = []struct {
100+
in string
101+
version string
102+
out string
103+
}{
104+
{`module m
105+
`,
106+
`1.14`,
107+
`module m
108+
go 1.14
109+
`,
110+
},
111+
{`module m
112+
require x.y/a v1.2.3
113+
`,
114+
`1.14`,
115+
`module m
116+
go 1.14
117+
require x.y/a v1.2.3
118+
`,
119+
},
120+
{
121+
`require x.y/a v1.2.3
122+
module example.com/inverted
123+
`,
124+
`1.14`,
125+
`require x.y/a v1.2.3
126+
module example.com/inverted
127+
go 1.14
128+
`,
129+
},
130+
{
131+
`require x.y/a v1.2.3
132+
`,
133+
`1.14`,
134+
`require x.y/a v1.2.3
135+
go 1.14
136+
`,
137+
},
138+
}
139+
99140
func TestAddRequire(t *testing.T) {
100141
for i, tt := range addRequireTests {
101142
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
@@ -167,3 +208,33 @@ func TestSetRequire(t *testing.T) {
167208
})
168209
}
169210
}
211+
212+
func TestAddGo(t *testing.T) {
213+
for i, tt := range addGoTests {
214+
t.Run(fmt.Sprintf("#%d", i), func(t *testing.T) {
215+
f, err := Parse("in", []byte(tt.in), nil)
216+
if err != nil {
217+
t.Fatal(err)
218+
}
219+
g, err := Parse("out", []byte(tt.out), nil)
220+
if err != nil {
221+
t.Fatal(err)
222+
}
223+
golden, err := g.Format()
224+
if err != nil {
225+
t.Fatal(err)
226+
}
227+
228+
if err := f.AddGoStmt(tt.version); err != nil {
229+
t.Fatal(err)
230+
}
231+
out, err := f.Format()
232+
if err != nil {
233+
t.Fatal(err)
234+
}
235+
if !bytes.Equal(out, golden) {
236+
t.Errorf("have:\n%s\nwant:\n%s", out, golden)
237+
}
238+
})
239+
}
240+
}

0 commit comments

Comments
 (0)