Popularity
3.9
Growing
Activity
0.0
Declining
84
7
6

Description

astextract converts a given go file to its ast representation.

This is useful for easliy writing typesafe go generate tools, which don't concatenate strings for generating code.

The output of astextract is 100% valid go, so it can be used in go code directly without any modifications.

All zero/null value struct fields are ommited for a more compact ast representation.

Absolute Position info is stripped, because positions change if you add any dynamic content to the ast.

I already wrote binclude a tool for resource embedding with the help of astextraxt, and added string obfuscation to garble.

Programming language: Go
License: The Unlicense
Latest version: v0.1.2

astextract alternatives and similar packages

Based on the "Go Generate Tools" category.
Alternatively, view astextract alternatives based on common mentions on social networks and blogs.

Do you think we are missing an alternative of astextract or a related project?

Add another 'Go Generate Tools' Package

README

astextract

Test Go Report Card

astextract converts a given go file to its ast representation.

This is useful for easliy writing typesafe go generate tools, which don't concatenate strings for generating code.

The output of astextract is 100% valid go, so it can be used in go code directly without any modifications.

All zero/null value struct fields are ommited for a more compact ast representation.

Absolute Position info is stripped, because positions change if you add any dynamic content to the ast.

I already wrote binclude a tool for resource embedding with the help of astextraxt, and added string obfuscation to garble.

Web app

astextract be used as a Web app: https://lu4p.github.io/astextract/

The Web app was created using the amazing go-app package.

Install

GO111MODULE=on go get -u github.com/lu4p/astextract/cmd/astextract

Usage

astextract [flags] file

See astextract -h for up to date usage information.

Example

main.go:

package main

func main() {
    println("Hello, World!")
}

Command: astextract main.go

Output:

&ast.File {
  Package: 1,
  Name: &ast.Ident {
    Name: "main",
  },
  Decls: []ast.Decl {
    &ast.FuncDecl {
      Name: &ast.Ident {
        Name: "main",
      },
      Type: &ast.FuncType {
        Params: &ast.FieldList {},
      },
      Body: &ast.BlockStmt {
        List: []ast.Stmt {
          &ast.ExprStmt {
            X: &ast.CallExpr {
              Fun: &ast.Ident {
                Name: "println",
              },
              Args: []ast.Expr {
                &ast.BasicLit {
                  Kind: token.STRING,
                  Value: "\"Hello, World!\"",
                },
              },
            },
          },
        },
      },
    },
  },
}

How to convert go/ast back to go

Example taken from binclude generateFile()

bincludeFile :=  &ast.File{
        Doc: &ast.CommentGroup{
            List: []*ast.Comment{
                {
                    Slash: 1,
                    Text:  "// Code generated by binclude; DO NOT EDIT.",
                },
            },
        },
        Package: 45,
        Name:    pkgName,
        Decls: []ast.Decl{
            &ast.GenDecl{
                Tok:   token.IMPORT,
                Specs: imports,
            },
            &ast.GenDecl{
                Tok:   token.VAR,
                Specs: astVars,
            },
        },
    }

f, err := os.OpenFile("binclude.go", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)
if err != nil {
    return err
}
defer f.Close()

err = printer.Fprint(f, fset, bincludeFile)
if err != nil {
    return err
}

astextract -out=filename main.go generates a go file containing the ast of main.go and an example on how to generate go code from the ast.

Alternatives

  • go2ast: only converts a single line and doesn't support top level definitions.
  • go/ast Print: prints a representation which is unsuitable for usage in code generation

From the go/ast documentation:

This example shows what an AST looks like when printed for debugging. Code:

// src is the input for which we want to print the AST.
src := `
package main
func main() {
    println("Hello, World!")
}
`

// Create the AST by parsing src.
fset := token.NewFileSet() // positions are relative to fset
f, err := parser.ParseFile(fset, "", src, 0)
if err != nil {
    panic(err)
}

// Print the AST.
ast.Print(fset, f)

Output:

     0  *ast.File {
     1  .  Package: 2:1
     2  .  Name: *ast.Ident {
     3  .  .  NamePos: 2:9
     4  .  .  Name: "main"
     5  .  }
     6  .  Decls: []ast.Decl (len = 1) {
     7  .  .  0: *ast.FuncDecl {
     8  .  .  .  Name: *ast.Ident {
     9  .  .  .  .  NamePos: 3:6
    10  .  .  .  .  Name: "main"
    11  .  .  .  .  Obj: *ast.Object {
    12  .  .  .  .  .  Kind: func
    13  .  .  .  .  .  Name: "main"
    14  .  .  .  .  .  Decl: *(obj @ 7)
    15  .  .  .  .  }
    16  .  .  .  }
    17  .  .  .  Type: *ast.FuncType {
    18  .  .  .  .  Func: 3:1
    19  .  .  .  .  Params: *ast.FieldList {
    20  .  .  .  .  .  Opening: 3:10
    21  .  .  .  .  .  Closing: 3:11
    22  .  .  .  .  }
    23  .  .  .  }
    24  .  .  .  Body: *ast.BlockStmt {
    25  .  .  .  .  Lbrace: 3:13
    26  .  .  .  .  List: []ast.Stmt (len = 1) {
    27  .  .  .  .  .  0: *ast.ExprStmt {
    28  .  .  .  .  .  .  X: *ast.CallExpr {
    29  .  .  .  .  .  .  .  Fun: *ast.Ident {
    30  .  .  .  .  .  .  .  .  NamePos: 4:2
    31  .  .  .  .  .  .  .  .  Name: "println"
    32  .  .  .  .  .  .  .  }
    33  .  .  .  .  .  .  .  Lparen: 4:9
    34  .  .  .  .  .  .  .  Args: []ast.Expr (len = 1) {
    35  .  .  .  .  .  .  .  .  0: *ast.BasicLit {
    36  .  .  .  .  .  .  .  .  .  ValuePos: 4:10
    37  .  .  .  .  .  .  .  .  .  Kind: STRING
    38  .  .  .  .  .  .  .  .  .  Value: "\"Hello, World!\""
    39  .  .  .  .  .  .  .  .  }
    40  .  .  .  .  .  .  .  }
    41  .  .  .  .  .  .  .  Ellipsis: -
    42  .  .  .  .  .  .  .  Rparen: 4:25
    43  .  .  .  .  .  .  }
    44  .  .  .  .  .  }
    45  .  .  .  .  }
    46  .  .  .  .  Rbrace: 5:1
    47  .  .  .  }
    48  .  .  }
    49  .  }
    50  .  Scope: *ast.Scope {
    51  .  .  Objects: map[string]*ast.Object (len = 1) {
    52  .  .  .  "main": *(obj @ 11)
    53  .  .  }
    54  .  }
    55  .  Unresolved: []*ast.Ident (len = 1) {
    56  .  .  0: *(obj @ 29)
    57  .  }
    58  }