0

使用 gofmt 格式化 go 源代码时,它会保留换行符,以便您可以将项目组合在一起。我对这实际上是如何实现的很感兴趣。我尝试查看 github repo 中的源代码golang/go,但无法立即找到。如果您查看https://github.com/golang/go/blob/master/src/go/printer/printer.go#L979

// intersperse extra newlines if present in the source

打印机如何知道源中存在这些额外的换行符?有人可以指出我正确的方向吗?

4

3 回答 3

2

与大多数词法分析器不同,go 词法分析器包含经常被编译器的词法分析器删除或省略的标记。词法分析器发出的标记流包括注释标记、隐含分号、换行符、换页符 (FF) 和其他空格。这允许使用相同的令牌流来重新生成源代码,并创建编译器所需的结构,例如 AST。

于 2017-08-12T16:13:01.743 回答
1

gofmt 适用于 AST。当您查看https://golang.org/pkg/go/ast时,您会看到每个节点都有函数 Pos() 和 End() 分别返回开头和结尾的 token.Pos。这些本质上是源文件中的偏移量,因此对行号/中断一无所知。

但是当与 token.Fileset 结合时,这样的 token.Pos 可以转换为包含行号的 token.Position。gofmt 在函数 printer.go:lineFor() 中执行此操作。

换行符的实际插入是在nodes.go:linebreak() 中完成的。linebreak() 的第一个参数是通过在相应的 token.Pos 上调用上述 lineFor() 获得的行号。该函数计算此行号与打印的最后一个标记的行号之间的差异(在结构打印机的 pos 字段中跟踪)。这告诉它现在要打印的标记是否与前一个标记在输入文件中的同一行。如果不是,则意味着程序员在原始源代码中包含一个或多个换行符,并且 linebreak() 将最多输出 1 个空行。虽然它可以保留所有输入换行符,但 gofmt 的策略是将一系列空行压缩到仅 1 个空行。

如果您问这个问题的原因是您想自定义 gofmt,请查看https://github.com/mbenkmann/goformat

于 2018-04-27T13:34:55.967 回答
0

internal.go `line 40-41有这个:

// 使用 ; 插入,而不是换行符,以便行号

// 在 psrc 中匹配 src 中的。

然后这个:

psrc := append([]byte("package p;"), src...)
file, err = parser.ParseFile(fset, filename, psrc, parserMode)

那是你要找的吗?如果我的问题是正确的。

于 2017-08-11T09:44:05.713 回答