1
0

patch-tree-sitter-dart.js 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #!/usr/bin/env node
  2. /**
  3. * Patches tree-sitter-dart to use NAPI bindings compatible with tree-sitter 0.22+
  4. *
  5. * tree-sitter-dart v1.0.0 ships with NAN-style bindings that are incompatible
  6. * with tree-sitter 0.22+ which expects NAPI-style bindings with type-tagged
  7. * externals. This script rewrites the binding files and rebuilds.
  8. */
  9. const { writeFileSync, existsSync } = require('fs');
  10. const { join } = require('path');
  11. const { execSync } = require('child_process');
  12. const DART_DIR = join(__dirname, '..', 'node_modules', 'tree-sitter-dart');
  13. if (!existsSync(DART_DIR)) {
  14. // tree-sitter-dart not installed, skip
  15. process.exit(0);
  16. }
  17. // Check if already patched (look for NAPI-style binding)
  18. const bindingPath = join(DART_DIR, 'bindings', 'node', 'binding.cc');
  19. const { readFileSync } = require('fs');
  20. try {
  21. const existing = readFileSync(bindingPath, 'utf8');
  22. if (existing.includes('napi.h')) {
  23. // Already patched, check if build exists
  24. const buildPath = join(DART_DIR, 'build', 'Release', 'tree_sitter_dart_binding.node');
  25. if (existsSync(buildPath)) {
  26. console.log('tree-sitter-dart: already patched and built.');
  27. process.exit(0);
  28. }
  29. // Patched but not built, fall through to rebuild
  30. }
  31. } catch {
  32. // Can't read, continue with patch
  33. }
  34. console.log('Patching tree-sitter-dart for NAPI compatibility...');
  35. // Write NAPI-compatible binding.cc
  36. const bindingCC = `#include <napi.h>
  37. typedef struct TSLanguage TSLanguage;
  38. extern "C" TSLanguage *tree_sitter_dart();
  39. // "tree-sitter", "language" hashed with BLAKE2
  40. const napi_type_tag LANGUAGE_TYPE_TAG = {
  41. 0x8AF2E5212AD58ABF, 0xD5006CAD83ABBA16
  42. };
  43. Napi::Object Init(Napi::Env env, Napi::Object exports) {
  44. exports["name"] = Napi::String::New(env, "dart");
  45. auto language = Napi::External<TSLanguage>::New(env, tree_sitter_dart());
  46. language.TypeTag(&LANGUAGE_TYPE_TAG);
  47. exports["language"] = language;
  48. return exports;
  49. }
  50. NODE_API_MODULE(tree_sitter_dart_binding, Init)
  51. `;
  52. writeFileSync(bindingPath, bindingCC);
  53. // Write NAPI-compatible binding.gyp
  54. const bindingGyp = `{
  55. "targets": [
  56. {
  57. "target_name": "tree_sitter_dart_binding",
  58. "dependencies": [
  59. "<!(node -p \\"require('node-addon-api').targets\\"):node_addon_api_except"
  60. ],
  61. "include_dirs": [
  62. "src"
  63. ],
  64. "sources": [
  65. "src/parser.c",
  66. "bindings/node/binding.cc",
  67. "src/scanner.c"
  68. ],
  69. "conditions": [
  70. ["OS!='win'", {
  71. "cflags_c": [
  72. "-std=c99"
  73. ]
  74. }, {
  75. "cflags_c": [
  76. "/std:c11",
  77. "/utf-8"
  78. ]
  79. }]
  80. ]
  81. }
  82. ]
  83. }
  84. `;
  85. writeFileSync(join(DART_DIR, 'binding.gyp'), bindingGyp);
  86. // Rebuild native module
  87. try {
  88. execSync('npx node-gyp rebuild', {
  89. cwd: DART_DIR,
  90. stdio: 'pipe',
  91. timeout: 120000,
  92. });
  93. console.log('tree-sitter-dart: patched and rebuilt successfully.');
  94. } catch (error) {
  95. console.error('Warning: Failed to rebuild tree-sitter-dart native module.');
  96. console.error('Dart language support may not work.');
  97. if (process.env.DEBUG) {
  98. console.error(error.stderr?.toString());
  99. }
  100. }