Skip to content

Commit 936a401

Browse files
h9jianggopherbot
authored andcommitted
gopls/internal/golang: preserve copyright and build constraint
- This commit updates addTest and extractToFile to preserve copyright and build constraint comments when creating new files. - The change introduces utility functions to extract these comments from an ast.File. For golang/vscode-go#1594 Change-Id: I2b2f70d6d4de662c8357bca8558c094496c8b2e9 Reviewed-on: https://go-review.googlesource.com/c/tools/+/629756 Reviewed-by: Alan Donovan <[email protected]> Auto-Submit: Hongxiang Jiang <[email protected]> Reviewed-by: Robert Findley <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 1ffc3a1 commit 936a401

File tree

5 files changed

+170
-25
lines changed

5 files changed

+170
-25
lines changed

gopls/internal/golang/addtest.go

+20-14
Original file line numberDiff line numberDiff line change
@@ -330,22 +330,28 @@ func AddTestForFunc(ctx context.Context, snapshot *cache.Snapshot, loc protocol.
330330
// package decl based on the originating file.
331331
// Search for something that looks like a copyright header, to replicate
332332
// in the new file.
333-
if groups := pgf.File.Comments; len(groups) > 0 {
334-
// Copyright should appear before package decl and must be the first
335-
// comment group.
336-
// Avoid copying any other comment like package doc or directive comment.
337-
if c := groups[0]; c.Pos() < pgf.File.Package && c != pgf.File.Doc &&
338-
!isDirective(c.List[0].Text) &&
339-
strings.Contains(strings.ToLower(c.List[0].Text), "copyright") {
340-
start, end, err := pgf.NodeOffsets(c)
341-
if err != nil {
342-
return nil, err
343-
}
344-
header.Write(pgf.Src[start:end])
345-
// One empty line between copyright header and package decl.
346-
header.WriteString("\n\n")
333+
if c := copyrightComment(pgf.File); c != nil {
334+
start, end, err := pgf.NodeOffsets(c)
335+
if err != nil {
336+
return nil, err
347337
}
338+
header.Write(pgf.Src[start:end])
339+
// One empty line between copyright header and following.
340+
header.WriteString("\n\n")
348341
}
342+
343+
// If this test file was created by gopls, add build constraints
344+
// matching the non-test file.
345+
if c := buildConstraintComment(pgf.File); c != nil {
346+
start, end, err := pgf.NodeOffsets(c)
347+
if err != nil {
348+
return nil, err
349+
}
350+
header.Write(pgf.Src[start:end])
351+
// One empty line between build constraint and following.
352+
header.WriteString("\n\n")
353+
}
354+
349355
fmt.Fprintf(&header, "package %s_test\n", pkg.Types().Name())
350356

351357
// Write the copyright and package decl to the beginning of the file.

gopls/internal/golang/extracttofile.go

+20-1
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,26 @@ func ExtractToNewFile(ctx context.Context, snapshot *cache.Snapshot, fh file.Han
133133
}
134134

135135
var buf bytes.Buffer
136+
if c := copyrightComment(pgf.File); c != nil {
137+
start, end, err := pgf.NodeOffsets(c)
138+
if err != nil {
139+
return nil, err
140+
}
141+
buf.Write(pgf.Src[start:end])
142+
// One empty line between copyright header and following.
143+
buf.WriteString("\n\n")
144+
}
145+
146+
if c := buildConstraintComment(pgf.File); c != nil {
147+
start, end, err := pgf.NodeOffsets(c)
148+
if err != nil {
149+
return nil, err
150+
}
151+
buf.Write(pgf.Src[start:end])
152+
// One empty line between build constraint and following.
153+
buf.WriteString("\n\n")
154+
}
155+
136156
fmt.Fprintf(&buf, "package %s\n", pgf.File.Name.Name)
137157
if len(adds) > 0 {
138158
buf.WriteString("import (")
@@ -154,7 +174,6 @@ func ExtractToNewFile(ctx context.Context, snapshot *cache.Snapshot, fh file.Han
154174
fileStart := pgf.File.FileStart
155175
buf.Write(pgf.Src[start-fileStart : end-fileStart])
156176

157-
// TODO: attempt to duplicate the copyright header, if any.
158177
newFileContent, err := format.Source(buf.Bytes())
159178
if err != nil {
160179
return nil, err

gopls/internal/golang/util.go

+42
Original file line numberDiff line numberDiff line change
@@ -397,3 +397,45 @@ func AbbreviateVarName(s string) string {
397397
}
398398
return b.String()
399399
}
400+
401+
// copyrightComment returns the copyright comment group from the input file, or
402+
// nil if not found.
403+
func copyrightComment(file *ast.File) *ast.CommentGroup {
404+
if len(file.Comments) == 0 {
405+
return nil
406+
}
407+
408+
// Copyright should appear before package decl and must be the first
409+
// comment group.
410+
if c := file.Comments[0]; c.Pos() < file.Package && c != file.Doc &&
411+
!isDirective(c.List[0].Text) &&
412+
strings.Contains(strings.ToLower(c.List[0].Text), "copyright") {
413+
return c
414+
}
415+
416+
return nil
417+
}
418+
419+
var buildConstraintRe = regexp.MustCompile(`^//(go:build|\s*\+build).*`)
420+
421+
// buildConstraintComment returns the build constraint comment from the input
422+
// file.
423+
// Returns nil if not found.
424+
func buildConstraintComment(file *ast.File) *ast.Comment {
425+
for _, cg := range file.Comments {
426+
// In Go files a build constraint must appear before the package clause.
427+
// See https://pkg.go.dev/cmd/go#hdr-Build_constraints
428+
if cg.Pos() > file.Package {
429+
return nil
430+
}
431+
432+
for _, c := range cg.List {
433+
// TODO: use ast.ParseDirective when available (#68021).
434+
if buildConstraintRe.MatchString(c.Text) {
435+
return c
436+
}
437+
}
438+
}
439+
440+
return nil
441+
}

gopls/internal/test/marker/testdata/codeaction/addtest.txt

+14-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ go 1.18
1313
"addTestSourceCodeAction": true
1414
}
1515

16-
-- withcopyright/copyright.go --
16+
-- copyrightandbuildconstraint/copyrightandbuildconstraint.go --
1717
// Copyright 2020 The Go Authors. All rights reserved.
1818
// Use of this source code is governed by a BSD-style
1919
// license that can be found in the LICENSE file.
@@ -23,18 +23,20 @@ go 1.18
2323
// Package main is for lsp test.
2424
package main
2525

26-
func Foo(in string) string {return in} //@codeaction("Foo", "source.addTest", edit=with_copyright)
26+
func Foo(in string) string {return in} //@codeaction("Foo", "source.addTest", edit=with_copyright_build_constraint)
2727

28-
-- @with_copyright/withcopyright/copyright_test.go --
29-
@@ -0,0 +1,30 @@
28+
-- @with_copyright_build_constraint/copyrightandbuildconstraint/copyrightandbuildconstraint_test.go --
29+
@@ -0,0 +1,32 @@
3030
+// Copyright 2020 The Go Authors. All rights reserved.
3131
+// Use of this source code is governed by a BSD-style
3232
+// license that can be found in the LICENSE file.
3333
+
34+
+//go:build go1.18
35+
+
3436
+package main_test
3537
+
3638
+import(
37-
+ "golang.org/lsptests/addtest/withcopyright"
39+
+ "golang.org/lsptests/addtest/copyrightandbuildconstraint"
3840
+ "testing"
3941
+)
4042
+
@@ -57,20 +59,22 @@ func Foo(in string) string {return in} //@codeaction("Foo", "source.addTest", ed
5759
+ })
5860
+ }
5961
+}
60-
-- withoutcopyright/copyright.go --
62+
-- buildconstraint/buildconstraint.go --
6163
//go:build go1.18
6264

6365
// Package copyright is for lsp test.
6466
package copyright
6567

66-
func Foo(in string) string {return in} //@codeaction("Foo", "source.addTest", edit=without_copyright)
68+
func Foo(in string) string {return in} //@codeaction("Foo", "source.addTest", edit=with_build_constraint)
6769

68-
-- @without_copyright/withoutcopyright/copyright_test.go --
69-
@@ -0,0 +1,26 @@
70+
-- @with_build_constraint/buildconstraint/buildconstraint_test.go --
71+
@@ -0,0 +1,28 @@
72+
+//go:build go1.18
73+
+
7074
+package copyright_test
7175
+
7276
+import(
73-
+ "golang.org/lsptests/addtest/withoutcopyright"
77+
+ "golang.org/lsptests/addtest/buildconstraint"
7478
+ "testing"
7579
+)
7680
+

gopls/internal/test/marker/testdata/codeaction/extracttofile.txt

+74
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,77 @@ func F() {} //@codeaction("func", "refactor.extract.toNewFile", edit=blank_impor
275275
- return time1.Now().string()
276276
-}
277277
-
278+
-- copyright.go --
279+
// Copyright 2020 The Go Authors. All rights reserved.
280+
// Use of this source code is governed by a BSD-style
281+
// license that can be found in the LICENSE file.
282+
283+
package main
284+
285+
// docs
286+
const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=copyright)
287+
288+
-- @copyright/c.go --
289+
@@ -0,0 +1,8 @@
290+
+// Copyright 2020 The Go Authors. All rights reserved.
291+
+// Use of this source code is governed by a BSD-style
292+
+// license that can be found in the LICENSE file.
293+
+
294+
+package main
295+
+
296+
+// docs
297+
+const C = ""
298+
-- @copyright/copyright.go --
299+
@@ -7,2 +7 @@
300+
-// docs
301+
-const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=copyright)
302+
+//@codeaction("const", "refactor.extract.toNewFile", edit=copyright)
303+
-- buildconstraint.go --
304+
//go:build go1.18
305+
306+
package main
307+
308+
// docs
309+
const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=buildconstraint)
310+
311+
-- @buildconstraint/buildconstraint.go --
312+
@@ -5,2 +5 @@
313+
-// docs
314+
-const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=buildconstraint)
315+
+//@codeaction("const", "refactor.extract.toNewFile", edit=buildconstraint)
316+
-- @buildconstraint/c.go --
317+
@@ -0,0 +1,6 @@
318+
+//go:build go1.18
319+
+
320+
+package main
321+
+
322+
+// docs
323+
+const C = ""
324+
-- copyrightandbuildconstraint.go --
325+
// Copyright 2020 The Go Authors. All rights reserved.
326+
// Use of this source code is governed by a BSD-style
327+
// license that can be found in the LICENSE file.
328+
329+
//go:build go1.18
330+
331+
package main
332+
333+
// docs
334+
const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=copyrightandbuildconstraint)
335+
-- @copyrightandbuildconstraint/c.go --
336+
@@ -0,0 +1,10 @@
337+
+// Copyright 2020 The Go Authors. All rights reserved.
338+
+// Use of this source code is governed by a BSD-style
339+
+// license that can be found in the LICENSE file.
340+
+
341+
+//go:build go1.18
342+
+
343+
+package main
344+
+
345+
+// docs
346+
+const C = ""
347+
-- @copyrightandbuildconstraint/copyrightandbuildconstraint.go --
348+
@@ -9,2 +9 @@
349+
-// docs
350+
-const C = "" //@codeaction("const", "refactor.extract.toNewFile", edit=copyrightandbuildconstraint)
351+
+//@codeaction("const", "refactor.extract.toNewFile", edit=copyrightandbuildconstraint)

0 commit comments

Comments
 (0)