go/ast and *token.FileSet

371 views
Skip to first unread message

Dmitri Shuralyov

unread,
May 2, 2014, 1:33:04 AM5/2/14
to golan...@googlegroups.com
Hello. First off, I'm a big fan of the go/ast package. I've been playing with it for a year and its existence got me to try Go in the first place.

Now, I've been trying to do something very simple with it and it seems to me that it is *impossible* (I could be wrong). I want to ask/confirm if that's indeed the case, and what can be done.

Suppose I have the AST and a *token.FileSet of the following short Go program (acquired via go/parser.ParseFile):

package main

func main() {
println("ASTs")
println("are awesome")
}

I want to make a small modification to it (insert a newline), so that when printed with go/printer it looks like this:

package main

func main() {
println("ASTs")

println("are awesome")
}

The *ast.File is actually identical, the only difference is inside the *token.FileSet. However, I see no public API that would allow me to insert a newline. There's one API http://godoc.org/go/token#File.MergeLine that lets you merge two lines.

Am I missing anything? Is the only way to make such a modification to the AST/FileSet pair by _printing_ it into text, changing the text, and then parsing it again?

Assuming that's correct, it seems the current go/ast and related things are absolutely fantastic for/at:

- parsing .go files into ast.File and token.FileSet.
- printing ast.File and token.FileSet into Go code (including formatting ala gofmt)
- doing amazing things with code.google.com/p/go.tools/go/types, code.google.com/p/go.tools/imports, astutil, oracle, etc. etc. packages

And not really good at:

- modifying ASTs (while preserving formatting and comments)

What can be done to address that last point, without losing the existing benefits outlined above?

Josh Bleecher Snyder

unread,
May 2, 2014, 12:24:21 PM5/2/14
to Dmitri Shuralyov, golang-nuts
In general, modifying the AST while preserving formatting and comments
is surprisingly hard.

The MergeLine method was added because it was needed for gofmt. I
(personally) think that an AddLine method or some such would be
reasonable to add. I recommend filing an issue asking for it, giving a
real-world use case.

Note that it is also pretty trivial to implement, so in a real pinch,
you could fork the package and add it. Or if it's just for your
experimentation or a one-off run, you could just modify your stdlib in
place.

-josh
Reply all
Reply to author
Forward
0 new messages