go/format:在源代码中包含//go:build指令时,格式化节点可能存在内部错误,

mrphzbgm  于 4个月前  发布在  Go
关注(0)|答案(2)|浏览(58)

复现者:

func TestBuildDirectiveFormat(t *testing.T) {
	const src = "package A\nimport()\nfunc A(){0//go:build\n0}"

	fs := token.NewFileSet()
	f, err := parser.ParseFile(fs, "test.go", src, parser.ParseComments|parser.SkipObjectResolution)
	if err != nil {
		t.Fatal(err)
	}

	if err := printer.Fprint(io.Discard, fs, f); err != nil {
		t.Fatal(err) // no error
	}

	if err := format.Node(io.Discard, fs, f); err != nil {
		t.Fatal(err) // format.Node internal error (8:5: expected ';', found 0 (and 1 more errors))
	}
}

printer.Fprint 对于相同的源文件没有返回错误,只返回了 format.Node 的错误。这种情况发生在:
go/src/go/format/format.go
第76行到第80行
| | file, err=parser.ParseFile(fset, "", buf.Bytes(), parserMode) |
| | iferr!=nil { |
| | // 我们不应该在这里。如果我们在这里,请提供良好的诊断信息。 |
| | returnfmt.Errorf("format.Node内部错误 (%s)", err) |
| | } |
CC @griesemer

nc1teljy

nc1teljy1#

这种情况发生是因为,在以下文件中:
go/src/go/format/format.go
第71行到第81行
| | varbuf bytes.Buffer |
| | err:=config.Fprint(&buf, fset, file) |
| | iferr!=nil { |
| | returnerr |
| | } |
| | file, err=parser.ParseFile(fset, "", buf.Bytes(), parserMode) |
| | iferr!=nil { |
| | // We should never get here. If we do, provide good diagnostic. |
| | returnfmt.Errorf("format.Node internal error (%s)", err) |
| | } |
| | ast.SortImports(fset, file) |
格式化后的源代码为:

"//go:build\n\npackage A\n\nimport ()\n\nfunc A() {\n\t0  0\n}\n"

这里的错误格式化发生在以下文件中:
go/src/go/printer/printer.go
第1371行到第1373行
| | // output is buffered in p.output now. |
| | // fix //go:build and // +build comments if needed. |
| | p.fixGoBuildLines() |

sbtkgmzw

sbtkgmzw2#

https://go.dev/cl/609055提到了这个问题:go/printer: correctly print trailing //go:build and //+build

相关问题