LoginSignup
1
1

More than 5 years have passed since last update.

Go のソースコードからコメントを消す

Posted at

go の parser.ParseFile で AST を取得して、この情報からコメントの情報を消して format.Node を使って再度コードに戻すことでコメントだけが消えたソースを生成することが出来ます。

package main

import (
    "go/ast"
    "go/format"
    "go/parser"
    "go/token"
    "os"
)

var src = `
package p; // p package

/*
 * sample
 */
func main() {
    a := 1
    a++ // increment
}
`

func main() {
    fset := token.NewFileSet()
    f, _ := parser.ParseFile(fset, "example.go", src, 0)

    f.Comments = make([]*ast.CommentGroup, 0)

    format.Node(os.Stdout, fset, f)
}

実行結果

package p

func main() {
        a := 1
        a++
}

コメントが消えたソースが出力されていることを確認出来ました。

仕組み

parser.ParseFile を利用して AST を取得するのですが、このデータの実態は ast.File でその中の情報にソースコードのコメント一覧が格納されているフィールドがあります。( Comments )

type File struct {
    Doc        *CommentGroup   // associated documentation; or nil
    Package    token.Pos       // position of "package" keyword
    Name       *Ident          // package name
    Decls      []Decl          // top-level declarations; or nil
    Scope      *Scope          // package scope (this file only)
    Imports    []*ImportSpec   // imports in this file
    Unresolved []*Ident        // unresolved identifiers in this file
    Comments   []*CommentGroup // list of all comments in the source file
}

format.Node を使って ast.File をソースコードに変換する際に、コメント情報が Comments から取られるので Comments を何かしらの方法で値が空の状態にしてあげればコメント情報が戻せなくなるという訳です。

今回は parser.ParseFile 実行時のモード指定を 0 にしていたので各ノードにコメント情報が存在していませんでしたが、モードに parser.ParseComments を含めて Commentsnil で初期化するとソースコードを戻す際にノードのコメント情報も見るようになるので、今回の例だと一部のコメントは消されず戻ってきます。

    } else if n, ok := node.(*ast.File); ok {
        // use ast.File comments, if any
        p.comments = n.Comments
    }

    // if there are no comments, use node comments
    p.useNodeComments = p.comments == nil

パース時に parser.ParseComments を指定して Commentsnil で初期化した ver

func main() {
    fset := token.NewFileSet()
    f, _ := parser.ParseFile(fset, "example.go", src, parser.ParseComments)
    ast.Print(fset, f)

    f.Comments = nil

    format.Node(os.Stdout, fset, f)
}

実行結果

package p

/*
 * sample
 */
func main() {
        a := 1
        a++
}

なんで一部だけ戻ってきたのかはまだ詳しく見てないのでわかっていないです。。。(わかったら追記します)

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1