{"_id":"@asgerf/dts-tree-sitter","_rev":"3-ece33e69621781f91f4bee12fcabe2e5","name":"@asgerf/dts-tree-sitter","dist-tags":{"latest":"0.21.0"},"versions":{"0.1.0":{"name":"@asgerf/dts-tree-sitter","version":"0.1.0","_id":"@asgerf/dts-tree-sitter@0.1.0","maintainers":[{"name":"asgerf","email":"asger.feldthaus@gmail.com"}],"dist":{"shasum":"d4b77cb5f03a0b1e5141bf4e6fab98f388fc061e","tarball":"https://registry.npmjs.org/@asgerf/dts-tree-sitter/-/dts-tree-sitter-0.1.0.tgz","fileCount":4,"integrity":"sha512-L1SaiDRbBXLIOxwaW/S3H/LvevCdRLrQh48gFqMX/CCtR1IMYGFqAt3/x8kK/SwEzzH0Ke8JrRHD3w3kVgubTg==","signatures":[{"sig":"MEQCIHF5buD2feQmS7fqjP8448pBCacFqPDNYCG8s6JpQr1DAiByLwiPaIt+TCErxoqj+2ZRQub3mgkYozW8F1PsN4evQA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17482,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfIUMOCRA9TVsSAnZWagAAl38QAIImO+EjtPlz9Y8QWSce\nKkTgpY+wpPTzmqRG/lxqv0V6BwMxR9pqvVmwKZ9qfr3ifZAEGwoB/Ra0hlMk\nrfbVpTah2iB1pVRHArFIMgapGBALxuVb7Ovgmkl8bxkOHF3RltgCSAzeK4Dk\nMyNWX4/wf1ylGoqdVET0B2CLlLx2MdJfRGudw9cY5HyYHj/ewjx1xoAy9APS\npWmSrnK152kB1Drm5JTg9mjPOi6xOdYjASvJCYCLSjpeXpCIj9cUCeWC2OJU\nySapzLlZbZRqeTQasdJVOWnsbLaCqACmMbLfXO9x59n6DrtfKkqkpeX3ng0T\nUFcxx/YgpLNWKHYZS8anUOXrMI/VW3IAnOYz08WN9SvZF3SJHwHj52C0R35H\nKwCstOc9qY3YUWVKHMt/++9yorCvb1C7171bIal6CFrI44A8tMEf1ct512OM\nxS6i0Oq4qfGZSQ1SoHsgwOH8NFK/NTIPy1p1N0i7ao8urwENoPu9OvJn5ytF\nykJA71rcNWWSlnZxU19mXlPSGIECuXL+USz4qZjOJC7iyINgQBtTPMPwbvIQ\nV6tK/P8F4NQaEpBwNOGuh5mdKKB1/WjLuF6dd0WMpxEVTPjSnG8cZyfQ2GP6\nRfPCdUE66Po4DfKbXZCgwIrFNaCzhuPNryuRr0UMhMzcJIkf5CshBadyzzJt\n5Qlv\r\n=hAzd\r\n-----END PGP SIGNATURE-----\r\n"},"main":"build/src/index.js","gitHead":"12d37f057843708c46f09f3d751506389b6a28da","scripts":{"watch":"tsc -p .; tsc -p . -w","prepare":"tsc -p .","gen-example":"tsc -p . && npm run gen-example-now","run-example":"tsc -p examples/javascript && node build/examples/javascript","gen-example-now":"node build/src/index.js tree-sitter-javascript > examples/javascript/generated.d.ts"},"_npmUser":{"name":"asgerf","email":"asger.feldthaus@gmail.com"},"_npmVersion":"6.14.5","description":"Generates TypeScript .d.ts files for using tree-sitter grammars.","directories":{},"_nodeVersion":"12.18.2","dependencies":{"tree-sitter":"^0.16.1"},"_hasShrinkwrap":false,"devDependencies":{"typescript":"^3.9.6","@types/node":"^14.0.14","tree-sitter-javascript":"^0.16.0"},"_npmOperationalInternal":{"tmp":"tmp/dts-tree-sitter_0.1.0_1596015373584_0.464920480648884","host":"s3://npm-registry-packages"}},"0.21.0":{"name":"@asgerf/dts-tree-sitter","version":"0.21.0","description":"Generates TypeScript .d.ts files for using tree-sitter grammars.","dependencies":{"tree-sitter":"^0.21.1"},"devDependencies":{"@types/node":"^16.0.0","tree-sitter-javascript":"^0.23.0","typescript":"^5.0.0"},"engines":{"node":">=16"},"scripts":{"watch":"tsc -p .; tsc -p . -w","gen-example-now":"node build/src/index.js tree-sitter-javascript > examples/javascript/generated.d.ts","gen-example":"tsc -p . && npm run gen-example-now","run-example":"tsc -p examples/javascript && node build/examples/javascript","prepare":"tsc -p . && chmod +x build/src/index.js"},"bin":{"dts-tree-sitter":"build/src/index.js"},"_id":"@asgerf/dts-tree-sitter@0.21.0","gitHead":"caa0b819c1d1bf1595d921475e0eef669cb0ee11","_nodeVersion":"20.11.1","_npmVersion":"10.2.4","dist":{"integrity":"sha512-habiFcvSC1BjO818ETw0DTrlwrTsf2rKJLm+qzUAr+NcY4HLNkJKgAveru+Gk7p8GseBrH5wcZHfFyW1jgxT0A==","shasum":"d95820e2ae50408bc97e7fd94048916aaf4fe53d","tarball":"https://registry.npmjs.org/@asgerf/dts-tree-sitter/-/dts-tree-sitter-0.21.0.tgz","fileCount":4,"unpackedSize":18133,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIFKhwhhVbaZd2O4BsUB8BB0LTudjvTzf/tu9iUV45kyHAiEA6wMCWjs6wR6DC2gbHhIoL+8ruuR0zpg+s9SZ/hDQSbI="}]},"_npmUser":{"name":"asgerf","email":"asger.feldthaus@gmail.com"},"directories":{},"maintainers":[{"name":"asgerf","email":"asger.feldthaus@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/dts-tree-sitter_0.21.0_1744408090630_0.3324723174198978"},"_hasShrinkwrap":false}},"time":{"created":"2020-07-29T09:36:13.548Z","modified":"2025-04-11T21:48:11.014Z","0.1.0":"2020-07-29T09:36:13.768Z","0.21.0":"2025-04-11T21:48:10.830Z"},"description":"Generates TypeScript .d.ts files for using tree-sitter grammars.","maintainers":[{"name":"asgerf","email":"asger.feldthaus@gmail.com"}],"readme":"# dts-tree-sitter\n\n**dts-tree-sitter** generates TypeScript `.d.ts` files for interacting the AST from a given tree-sitter grammar.\n\n## Usage\n\n```sh\nnpm i @asgerf/dts-tree-sitter\n\nnpx @asgerf/dts-tree-sitter INPUT > OUTPUT.d.ts\n```\nAlternative if you prefer to run without `npx`:\n\n```sh\nnode ./node_modules/@asgerf/dts-tree-sitter/build/src/index.js INPUT > OUTPUT.d.ts\n```\n\nwhere `INPUT` is used to locate a `node-types.json` file in one of the following locations:\n- `${INPUT}`\n- `${INPUT}/node-types.json`\n- `${INPUT}/src/node-types.json`\n- `node_modules/${INPUT}/src/node-types.json`\n\n## Example\n\nThe `tree-sitter-javascript` grammar can be compiled like this:\n\n```sh\nnpm i tree-sitter-javascript\nnpx @asgerf/dts-tree-sitter tree-sitter-javascript > generated.d.ts\n```\n\nAlternative if you prefer to run without `npx`:\n\n```sh\nnode ./node_modules/@asgerf/dts-tree-sitter/build/src/index.js tree-sitter-javascript > generated.d.ts\n```\n\nIn the resulting grammar, two of the node types look like this:\n```ts\nexport interface ClassDeclarationNode extends SyntaxNodeBase {\n  type: SyntaxType.ClassDeclaration;\n  bodyNode: ClassBodyNode;\n  decoratorNodes?: DecoratorNode[];\n  nameNode: IdentifierNode;\n}\n\nexport interface ClassBodyNode extends SyntaxNodeBase {\n  type: SyntaxType.ClassBody;\n  memberNodes?: (MethodDefinitionNode | PublicFieldDefinitionNode)[];\n}\n```\n\nThis can be used like this (see [full example](examples/javascript/index.ts)):\n```ts\nimport * as g from \"./generated\";\n\nfunction getMemberNames(node: g.ClassDeclarationNode) {\n    let result = [];\n    for (let member of node.bodyNode.memberNodes) {\n        if (member.type === g.SyntaxType.MethodDefinition) {\n            result.push(member.nameNode.text);\n        } else {\n            result.push(member.propertyNode.text);\n        }\n    }\n    return result;\n}\n```\n\nObserve TypeScript do its magic: the type check in the `if` promotes the type of `member` to a `MethodDefinitionNode`\nin the 'then' branch, and to `PublicFieldDefinitionNode` in the 'else' branch.\n\n## Typed Tree Cursors\n\nTree sitter's `TreeCursor` allows fast traversal of an AST, and has two properties with correlated types: `nodeType`, and `currentNode`.\nOnce you've checked `nodeType`, it's annoying to have to cast `currentNode` to the correponding type right afterwards:\n```ts\nif (cursor.nodeType === g.SyntaxType.Function) {\n  let node = cursor.currentNode as g.Function; // annoying cast\n}\n```\n\nThere's another way, which is handy in large switches: Cast the cursor itself to a `TypedTreeCursor` before switching on `nodeType`.\nThen the guarded use of `currentNode` has the expected type. For example:\n```ts\nfunction printDeclaredNames() {\n    let cursor = tree.walk();\n    do {\n        const c = cursor as g.TypedTreeCursor;\n        switch (c.nodeType) {\n            case g.SyntaxType.ClassDeclaration:\n            case g.SyntaxType.FunctionDeclaration:\n            case g.SyntaxType.VariableDeclarator: {\n                let node = c.currentNode;\n                console.log(node.nameNode.text);\n                break;\n            }\n        }\n    } while(gotoPreorderSucc(cursor));\n}\n```\n- `node` gets the type `ClassDeclarationNode | FunctionDeclarationNode | VariableDeclaratorNode`.\n- This allows safe access to `node.nameNode`, since each of those types have a `name` field.\n- We don't pay the cost of invoking `currentNode` for other types of nodes.\n\n## Trouble-shooting\n\n### I get an error about \"excessive stack depth\" during compilation\n\nThis happens if you compare types from the general `tree-sitter.d.ts` file with those from the generated `.d.ts` file.\nEvery type from `tree-sitter.d.ts` has a stronger version in the generated file; make sure you don't mix and match.\n\n\n### I get `UnnamedNode` types in places where I don't expect them\n\nThis can happen if the grammar contains rules and literals with the same name. For example this grammar rule,\n```js\n  func: $ => seq('func', $.name, $.body)\n```\nwill produce a named node with type `func`, while the `'func'` literal will produce an unnamed node with type `func` as well.\n\nThis means a check like `node.type === 'func'` is not an exact type check, and the type of `node` will only be restricted to `FuncNode | UnnamedNode<'func'>`. This is _not_ a bug in the generated `.d.ts` file: there really are two kinds of nodes you need to handle after that check.\n\nSome possible solutions are:\n- Change the grammar to avoid rules with the same name as a keyword.\n- Write the check as `node.isNamed && node.type === 'func'`.\n- Change the declared type of `node` from `SyntaxNode` to `NamedNode`.\n","readmeFilename":"README.md"}