{"id":21025242,"url":"https://github.com/samvv/tsastgen","last_synced_at":"2025-05-15T09:34:51.555Z","repository":{"id":42816203,"uuid":"268092467","full_name":"samvv/tsastgen","owner":"samvv","description":"Generate TypeScript AST definitions from a simple specification file","archived":false,"fork":false,"pushed_at":"2023-02-09T14:12:04.000Z","size":282,"stargazers_count":4,"open_issues_count":1,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-11-10T09:34:47.200Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://npmjs.com/package/tsastgen","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/samvv.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","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}},"created_at":"2020-05-30T14:10:15.000Z","updated_at":"2024-02-08T01:17:26.000Z","dependencies_parsed_at":"2023-02-18T09:31:26.263Z","dependency_job_id":null,"html_url":"https://github.com/samvv/tsastgen","commit_stats":{"total_commits":105,"total_committers":3,"mean_commits":35.0,"dds":0.3904761904761904,"last_synced_commit":"d5881953e3bc055fce6d19f2281f0654b8e5ee2c"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samvv%2Ftsastgen","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samvv%2Ftsastgen/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samvv%2Ftsastgen/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/samvv%2Ftsastgen/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/samvv","download_url":"https://codeload.github.com/samvv/tsastgen/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":225342964,"owners_count":17459506,"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":[],"created_at":"2024-11-19T11:31:48.301Z","updated_at":"2024-11-19T11:31:49.079Z","avatar_url":"https://github.com/samvv.png","language":"TypeScript","readme":"AST Generator for TypeScript\n============================\n\nThis tool generates complete definitions for an abstract syntax tree (AST) in\nthe TypeScript language. It reads an ordinary TypeScript file as a\nspecification file, and will automatically generate classes, contstructors,\nunion types, visitors, and predicates based on this specification.\n\n## Features\n\n - Mix your own code with code generated by `tsastgen`. TypeScript goes in,\n   TypeScript comes out.\n - Efficient type-checking and dispatching using TypeScript enums and\n   discriminated unions.\n - Generate typed reflection functions such as `Node.getChildNodes()` and\n   `isFoo()`\n - Generate typed factory functions that are able to automatically lift simple\n   primitive values to entire nodes _(experimental)_.\n - Ability to generate typed links to the parent node that only lists node\n   types that can actually be a parent.\n\n## Basic Usage\n\nFirst you have to install the package:\n\n```\nnpm install -g tsastgen\n````\n\nNow a binary called `tsastgen` should be available in your favorite shell.\nIf not, check your `PATH` variable and that _npm_ is properly configured.\n\nNext, create a specification file. Here's an example:\n\n**calc-spec.ts**\n\n```ts\nexport interface AST {}\n\nexport interface Definition extends AST {\n  name: string;\n  expression: Expression;\n}\n\nexport interface Expression extends AST {\n  lazyEvaluatedResult?: number;\n}\n\nexport interface ConstantExpression extends Expression {\n  value: number;\n}\n\nexport interface BinaryExpression extends Expression {\n  left: Expression;\n  right: Expression;\n}\n\nexport interface SubtractExpression extends BinaryExpression {\n\n}\n\nexport interface AddExpression extends BinaryExpression {\n\n}\n\nexport interface MultiplyExpression extends BinaryExpression {\n\n}\n\nexport interface DivideExpression extends BinaryExpression {\n\n}\n\nexport type CommutativeExpression \n  = AddExpression\n  | SubtractExpression\n  | MultiplyExpression;\n```\n\nNow all you need to do is to run `tsastgen` and make sure it knows what the\noutput file and the root node is.\n\n```\ntsastgen --root-node=AST calc-spec.ts:calc.ts\n```\n\nRead the [example][1] for a much more detailed explanation of how code is generated.\n\n[1]: https://github.com/samvv/tsastgen/blob/master/examples/calculator.ts\n\n### How to match certain generated AST nodes\n\nHere's an example of how the generated code might be used:\n\n```ts\nimport { Expression } from \"./calc\"\n\nexport function calculate(node: Expression): number {\n  switch (node.kind) {\n    case SyntaxKind.AddExpression:\n       return node.left + node.right;\n    case SyntaxKind.SubtractExpression:\n      // and so on ...\n    default:\n      throw new Error(`I did not know how to process the given node.`);\n  }\n}\n```\n\nIn the above example, due to the way in which the code is generated, the\ncompiler automatically knows when certain fields are present.\n\nAlternatively, you can use the generated AST predicates combined with an\nif-statement to prevent casting:\n\n```ts\nconst node = generateANewNodeSomehow();\n\nif (isDefinition(node)) {\n  // The fields 'name' and 'expression' are now available.\n}\n```\n\nNo matter which style you use, you will almost never have to cast to another\nexpression.\n\n### How to create new AST nodes\n\nCreating nodes is also very easy:\n\n```ts\nimport {\n  createAddExpression,\n  createConstantExpression,\n} from \"./calc\";\n\nconst n1 = createConstantExpression(1);\nconst n2 = createConstantExpression(2);\nconst add = createAddExpression(n1, n2);\n\nconsole.log(`The result of 1 + 2 is ${calculate(add)}`);\n```\n\nIt is recommended to not use the `new` operator. Instead, use the wrapping\n`createX` function.  The motivation is that in the future we might use a more\nefficient representation than a class, using `createX`-functions guarantees\nforward compatibility.\n\n## API\n\nIn the following documented signatures, `Foo` stands for an arbitrary node type\ngenerated by `tsastgen` and `node` for an instance of `Foo`.\n`Syntax` refers to the node type specified with `--root-node` and `field` to a\nspecified field of `Foo`.\n\n### SyntaxKind\n\nA large enumeration that contains all of your node types. You can access the\nkind of a node using the `node.kind` property documented below.\n\n### isSyntax(value)\n\nCheck whether `value` is an AST node. Any JavaScript value may be passed in.\nUse this function if you don't know anything about `value` and before using a\nfunction such as `isFoo`.\n\n### isFoo(node)\n\nCheck whether the given node is of the specific node type `Foo`. For\nperformance reasons, you should only pass in valid node objects. Do not use\nthis function to check whether any random JavaScript value is a node\nobject.\n\n### node.kind\n\nGet the `SyntaxKind` enumeration value that discriminates the type of this\nnode from the other node types.\n\n### node.getChildNodes()\n\nReturns an iterable (not an array) of all nodes that can be found in the fields\nof `node`.\n\n### node.parentNode\n\nA typed reference to a node that is the parent of this node, or `null` if this\nnode is the root node or if the parent has not been set.\n\n### node.field\n\nA property to get the value of a specified field of `node`.\n\n### FooParent\n\nA type alias that lists all node types that in theory can be a parent of `Foo`.\n\n### FooChild\n\nA type alias that lists all node types that in theory can occur in the fields\nof `Foo`.\n\n### createFoo(...fields)\n\nCreate a new node object of the type `Foo`. The required fields go first after\nwhich the optional fields may be specified. Use your code editor's hint dialogs\nto see what field goes where.\n\nIf a field refers to a node that only contains one field, you may be able to\njust specify that field directly and `createFoo` will convert it into the\ndesired node type for you.\n\n## CLI Options\n\n```\ntsastgen [input-file[:output-file]..] --root-node=\u003cname\u003e\n```\n\n### input-file\n\nThe specification file that AST definitions will be generated from.\n\n### output-file\n\nIf present, the file where the transformed `input-file` must be written to.\n\nIf not present, the program will output the result to standard output.\n\n### --root-node\n\nThe name of the node that serves as the root node of the abstract syntax\ntree.It will automatically be converted to a union type containing all possible\nAST node types.\n\nIf `--root-node` is not specified, _tsastgen_ will search for a declaration\nnamed `Syntax`.\n\n### --with-parent-member\n\nThe name of the field that is used to refer to the parent node of a node type.\nIf enabled, `tsastgen` will treat this node specially and inject/replace fully\ntyped member fields with the name you provided.\n\nIf `--with-parent-member` is not specified, this feature is not enabled and\nyour member will be passed through without any modifications.\n\n### --with-mutators\n\nAlso generate methods that mutate a node or field on each node type.\n\n### --with-coercions\n\nEnable experimental code generation of coercion statements in factory\nfunctions. Currently, due to limitations in the built-in type checking\nalgorithm, this will not work for complex ASTs.\n\n## Known Issues and Limitations\n\nCoercions in factory functions will not always be generated because we only\nemulate a small subset the typing rule of TypeScript. If something cannot be\nchecked, the tool will error or skip it. This is  due to poor support of the\nTypeScript compiler to inspect the types of AST nodes in detail. Unfortunately,\nthis appears to be by design, so this won't get fixed easily. If we were to\ncover all cases of TypeScript's AST, we would effectively have written a second\ncompiler.\n\n## License\n\nI chose to license this piece of software under the MIT license, in the hope\nthat you may find it useful. You may freely use this generator in your own\nprojects, but it is always nice if you can give a bit of credit.\n\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamvv%2Ftsastgen","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsamvv%2Ftsastgen","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsamvv%2Ftsastgen/lists"}