{"id":17091024,"url":"https://github.com/lu4p/astextract","last_synced_at":"2025-03-17T10:34:39.380Z","repository":{"id":45174815,"uuid":"274766938","full_name":"lu4p/astextract","owner":"lu4p","description":"Convert a go file to its ast representation","archived":false,"fork":false,"pushed_at":"2023-03-27T18:56:41.000Z","size":7345,"stargazers_count":84,"open_issues_count":2,"forks_count":8,"subscribers_count":7,"default_branch":"master","last_synced_at":"2024-10-15T13:57:15.631Z","etag":null,"topics":["ast","ast-generation","ast-parser","golang","webassembly"],"latest_commit_sha":null,"homepage":"https://astextract.lu4p.xyz/","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"unlicense","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lu4p.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"lu4p"}},"created_at":"2020-06-24T20:50:24.000Z","updated_at":"2024-02-28T18:49:36.000Z","dependencies_parsed_at":"2024-06-20T15:35:41.840Z","dependency_job_id":"2e2dde6f-b5db-4391-bcc2-bee9c30321f7","html_url":"https://github.com/lu4p/astextract","commit_stats":null,"previous_names":[],"tags_count":4,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu4p%2Fastextract","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu4p%2Fastextract/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu4p%2Fastextract/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lu4p%2Fastextract/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lu4p","download_url":"https://codeload.github.com/lu4p/astextract/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":221675317,"owners_count":16861860,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ast","ast-generation","ast-parser","golang","webassembly"],"created_at":"2024-10-14T13:57:21.485Z","updated_at":"2024-10-27T12:34:06.536Z","avatar_url":"https://github.com/lu4p.png","language":"Go","funding_links":["https://github.com/sponsors/lu4p"],"categories":["Go"],"sub_categories":[],"readme":"# astextract\n[![Test](https://github.com/lu4p/astextract/workflows/Test/badge.svg)](https://github.com/lu4p/astextract/actions?query=workflow%3ATest)\n[![Go Report Card](https://goreportcard.com/badge/github.com/lu4p/astextract)](https://goreportcard.com/report/github.com/lu4p/astextract)\n\n\nastextract converts a given go file to its [ast](https://pkg.go.dev/go/ast) representation.\n\nThis is useful for easliy writing typesafe `go generate` tools, which don't concatenate strings for generating code. \n\nThe output of astextract is 100% valid go, so it can be used in go code directly without any modifications.\n\nAll zero/null value struct fields are ommited for a more compact ast representation.\n\nAbsolute Position info is stripped, because positions change if you add any dynamic content to the ast.\n\nI already wrote [binclude](https://github.com/lu4p/binclude) a tool for resource embedding with the help of astextraxt, and added string obfuscation to [garble](https://github.com/mvdan/garble).\n\n## Web app\nastextract be used as a Web app: https://astextract.lu4p.xyz/\n\nThe Web app was created using the amazing [go-app](https://github.com/maxence-charriere/go-app) package.\n\n\n## Install\n`GO111MODULE=on go get -u github.com/lu4p/astextract/cmd/astextract`\n\n## Usage\n`astextract [flags] file`\n\nSee `astextract -h` for up to date usage information.\n\n## Example \nmain.go:\n```go\npackage main\n\nfunc main() {\n\tprintln(\"Hello, World!\")\n}\n```\n\nCommand: `astextract main.go`\n\nOutput:\n```go\n\u0026ast.File {\n  Package: 1,\n  Name: \u0026ast.Ident {\n    Name: \"main\",\n  },\n  Decls: []ast.Decl {\n    \u0026ast.FuncDecl {\n      Name: \u0026ast.Ident {\n        Name: \"main\",\n      },\n      Type: \u0026ast.FuncType {\n        Params: \u0026ast.FieldList {},\n      },\n      Body: \u0026ast.BlockStmt {\n        List: []ast.Stmt {\n          \u0026ast.ExprStmt {\n            X: \u0026ast.CallExpr {\n              Fun: \u0026ast.Ident {\n                Name: \"println\",\n              },\n              Args: []ast.Expr {\n                \u0026ast.BasicLit {\n                  Kind: token.STRING,\n                  Value: \"\\\"Hello, World!\\\"\",\n                },\n              },\n            },\n          },\n        },\n      },\n    },\n  },\n}\n```\n\n\n## How to convert go/ast back to go\nExample taken from binclude [generateFile()](https://github.com/lu4p/binclude/blob/f796cc285c1e76e072386a639b8209284aaf3369/cmd/binclude/inject.go#L160)\n\n```go\nbincludeFile :=  \u0026ast.File{\n\t\tDoc: \u0026ast.CommentGroup{\n\t\t\tList: []*ast.Comment{\n\t\t\t\t{\n\t\t\t\t\tSlash: 1,\n\t\t\t\t\tText:  \"// Code generated by binclude; DO NOT EDIT.\",\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tPackage: 45,\n\t\tName:    pkgName,\n\t\tDecls: []ast.Decl{\n\t\t\t\u0026ast.GenDecl{\n\t\t\t\tTok:   token.IMPORT,\n\t\t\t\tSpecs: imports,\n\t\t\t},\n\t\t\t\u0026ast.GenDecl{\n\t\t\t\tTok:   token.VAR,\n\t\t\t\tSpecs: astVars,\n\t\t\t},\n\t\t},\n    }\n\nf, err := os.OpenFile(\"binclude.go\", os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0644)\nif err != nil {\n\treturn err\n}\ndefer f.Close()\n\nerr = printer.Fprint(f, fset, bincludeFile)\nif err != nil {\n\treturn err\n}\n```\n\n`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.\n\n## Alternatives\n- [go2ast](https://github.com/reflog/go2ast): only converts a single line and doesn't support top level definitions.\n- [go/ast Print](https://pkg.go.dev/go/ast?tab=doc#Print): prints a representation which is unsuitable for usage in code generation\n\nFrom the go/ast documentation:\n\nThis example shows what an AST looks like when printed for debugging. \nCode:\n```go\n// src is the input for which we want to print the AST.\nsrc := `\npackage main\nfunc main() {\n\tprintln(\"Hello, World!\")\n}\n`\n\n// Create the AST by parsing src.\nfset := token.NewFileSet() // positions are relative to fset\nf, err := parser.ParseFile(fset, \"\", src, 0)\nif err != nil {\n\tpanic(err)\n}\n\n// Print the AST.\nast.Print(fset, f)\n```\nOutput: \n```\n     0  *ast.File {\n     1  .  Package: 2:1\n     2  .  Name: *ast.Ident {\n     3  .  .  NamePos: 2:9\n     4  .  .  Name: \"main\"\n     5  .  }\n     6  .  Decls: []ast.Decl (len = 1) {\n     7  .  .  0: *ast.FuncDecl {\n     8  .  .  .  Name: *ast.Ident {\n     9  .  .  .  .  NamePos: 3:6\n    10  .  .  .  .  Name: \"main\"\n    11  .  .  .  .  Obj: *ast.Object {\n    12  .  .  .  .  .  Kind: func\n    13  .  .  .  .  .  Name: \"main\"\n    14  .  .  .  .  .  Decl: *(obj @ 7)\n    15  .  .  .  .  }\n    16  .  .  .  }\n    17  .  .  .  Type: *ast.FuncType {\n    18  .  .  .  .  Func: 3:1\n    19  .  .  .  .  Params: *ast.FieldList {\n    20  .  .  .  .  .  Opening: 3:10\n    21  .  .  .  .  .  Closing: 3:11\n    22  .  .  .  .  }\n    23  .  .  .  }\n    24  .  .  .  Body: *ast.BlockStmt {\n    25  .  .  .  .  Lbrace: 3:13\n    26  .  .  .  .  List: []ast.Stmt (len = 1) {\n    27  .  .  .  .  .  0: *ast.ExprStmt {\n    28  .  .  .  .  .  .  X: *ast.CallExpr {\n    29  .  .  .  .  .  .  .  Fun: *ast.Ident {\n    30  .  .  .  .  .  .  .  .  NamePos: 4:2\n    31  .  .  .  .  .  .  .  .  Name: \"println\"\n    32  .  .  .  .  .  .  .  }\n    33  .  .  .  .  .  .  .  Lparen: 4:9\n    34  .  .  .  .  .  .  .  Args: []ast.Expr (len = 1) {\n    35  .  .  .  .  .  .  .  .  0: *ast.BasicLit {\n    36  .  .  .  .  .  .  .  .  .  ValuePos: 4:10\n    37  .  .  .  .  .  .  .  .  .  Kind: STRING\n    38  .  .  .  .  .  .  .  .  .  Value: \"\\\"Hello, World!\\\"\"\n    39  .  .  .  .  .  .  .  .  }\n    40  .  .  .  .  .  .  .  }\n    41  .  .  .  .  .  .  .  Ellipsis: -\n    42  .  .  .  .  .  .  .  Rparen: 4:25\n    43  .  .  .  .  .  .  }\n    44  .  .  .  .  .  }\n    45  .  .  .  .  }\n    46  .  .  .  .  Rbrace: 5:1\n    47  .  .  .  }\n    48  .  .  }\n    49  .  }\n    50  .  Scope: *ast.Scope {\n    51  .  .  Objects: map[string]*ast.Object (len = 1) {\n    52  .  .  .  \"main\": *(obj @ 11)\n    53  .  .  }\n    54  .  }\n    55  .  Unresolved: []*ast.Ident (len = 1) {\n    56  .  .  0: *(obj @ 29)\n    57  .  }\n    58  }\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flu4p%2Fastextract","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flu4p%2Fastextract","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flu4p%2Fastextract/lists"}