1

given this code, how do i print it with the extra import spec without breaking comments nodes.

In below code I load a package from a string using the package loader API. I try to consume the resulting AST to insert a new node, an import spec.

Unfortunately when I try to print the modified AST the comments are scrambled around.

https://play.golang.org/p/N6_y1ehM1Qc

package main

import (
    "go/ast"
    "go/parser"
    "go/printer"
    "go/token"
    "log"
    "os"

    "golang.org/x/tools/go/loader"
)

func main() {

    var conf loader.Config
    conf.ParserMode = parser.ParseComments

    f, err := conf.ParseFile("main.go", `// some comment goes here 
package main

// some comment here.

// main comment here.
func main(){
}
`)
    if err != nil {
        log.Fatal(err)
    }
    conf.CreateFromFiles("main", f)
    prog, err := conf.Load()
    if err != nil {
        log.Println(err)
    }

    g := &ast.GenDecl{}
    g.Tok = token.IMPORT
    spec := &ast.ImportSpec{
        Path: &ast.BasicLit{Value: "package/path"},
    }
    g.Specs = append(g.Specs, spec)
    f.Decls = append([]ast.Decl{g}, f.Decls...)
    _ = prog
    printer.Fprint(os.Stdout, token.NewFileSet(), f)
    //printer.Fprint(os.Stdout, prog.Fset, f)
}

This program outputs

package main // some comment goes here
// some comment here.
// main comment here.
import package/path

func main() {
}

I expected to get this result instead:

// some comment goes here
package main

// some comment here.
import package/path

// main comment here.
func main() {
}

This is problematic because in a more complex program, the output is broken:

// some comment goes here
package main

import // some comment here.
package/path

// main comment here.
func main() {
}
  • 1
    You can use the existing `FileSet` to avoid having everything misplaced, and then set the desired `token.Pos` for the import declaration. https://play.golang.org/p/hCLQB3daxOF – mkopriva Nov 20 '19 at 14:59
  • do you any suggestion about descending the tree to adjust the pos of every element following the newly inserted node ? I did some more testing and it seems to me it is risky to only use a reference and add/remove an offset. –  Nov 20 '19 at 17:22
  • 1
    Maybe try using `golang.org/x/tools/go/ast/astutil` and also take a look at its source to see how it calculates the position. Can't say more than that as I've never used it myself. – mkopriva Nov 20 '19 at 17:39
  • thank you, i have forgotten about astutil. should help indeed. –  Nov 20 '19 at 17:42
  • 1
    We got caught by this same problem. I think the ast package documentation should be updated a bit. (We ended up going a different way entirely) – torek Nov 20 '19 at 23:43

0 Answers0