OR-1 dataflow CPU sketch
at main 1088 lines 33 kB view raw
1#include "./node.h" 2#include "./conversions.h" 3#include "./tree.h" 4#include "./tree_cursor.h" 5#include "tree_sitter/api.h" 6 7#include <napi.h> 8#include <vector> 9 10using std::vector; 11using namespace Napi; 12 13namespace node_tree_sitter::node_methods { 14 15const uint32_t FIELD_COUNT_PER_NODE = 6; 16 17namespace { 18 19inline void setup_transfer_buffer(Napi::Env env, uint32_t node_count) { 20 auto *data = env.GetInstanceData<AddonData>(); 21 22 uint32_t new_length = node_count * FIELD_COUNT_PER_NODE; 23 if (new_length > data->transfer_buffer_length) { 24 data->transfer_buffer_length = new_length; 25 26 auto js_transfer_buffer = Uint32Array::New(env, data->transfer_buffer_length); 27 data->transfer_buffer = js_transfer_buffer.Data(); 28 29 data->module_exports.Value()["nodeTransferArray"] = js_transfer_buffer; 30 } 31} 32 33inline bool operator<=(const TSPoint &left, const TSPoint &right) { 34 if (left.row < right.row) { 35 return true; 36 } 37 if (left.row > right.row) { 38 return false; 39 } 40 return left.column <= right.column; 41} 42 43Napi::Value MarshalNodes(const Napi::CallbackInfo &info, 44 const Tree *tree, const TSNode *nodes, uint32_t node_count) { 45 return GetMarshalNodes(info, tree, nodes, node_count); 46} 47 48} // namespace 49 50Napi::Value MarshalNode(const Napi::CallbackInfo &info, const Tree *tree, TSNode node) { 51 return GetMarshalNode(info, tree, node); 52} 53 54Napi::Value GetMarshalNodes(const Napi::CallbackInfo &info, 55 const Tree *tree, const TSNode *nodes, uint32_t node_count) { 56 Env env = info.Env(); 57 auto *data = env.GetInstanceData<AddonData>(); 58 auto result = Array::New(env, node_count); 59 setup_transfer_buffer(env, node_count); 60 uint32_t *p = data->transfer_buffer; 61 for (unsigned i = 0; i < node_count; i++) { 62 TSNode node = nodes[i]; 63 const auto &cache_entry = tree->cached_nodes_.find(node.id); 64 Napi::Value value; 65 if (cache_entry != tree->cached_nodes_.end() && (value = cache_entry->second->node.Value(), !value.IsEmpty())) { 66 result[i] = value; 67 } else { 68 MarshalNodeId(node.id, p); 69 p += 2; 70 *(p++) = node.context[0]; 71 *(p++) = node.context[1]; 72 *(p++) = node.context[2]; 73 *(p++) = node.context[3]; 74 if (node.id != nullptr) { 75 result[i] = Number::New(env, ts_node_symbol(node)); 76 } else { 77 result[i] = env.Null(); 78 } 79 } 80 } 81 return result; 82} 83 84Napi::Value GetMarshalNode(const Napi::CallbackInfo &info, const Tree *tree, TSNode node) { 85 Env env = info.Env(); 86 auto* data = env.GetInstanceData<AddonData>(); 87 const auto &cache_entry = tree->cached_nodes_.find(node.id); 88 Napi::Value value; 89 if (cache_entry != tree->cached_nodes_.end() && (value = cache_entry->second->node.Value(), !value.IsEmpty())) { 90 return value; 91 } else { 92 setup_transfer_buffer(env, 1); 93 uint32_t *p = data->transfer_buffer; 94 MarshalNodeId(node.id, p); 95 p += 2; 96 *(p++) = node.context[0]; 97 *(p++) = node.context[1]; 98 *(p++) = node.context[2]; 99 *(p++) = node.context[3]; 100 if (node.id != nullptr) { 101 return Number::New(env, ts_node_symbol(node)); 102 } 103 } 104 return env.Null(); 105} 106 107TSNode UnmarshalNode(Napi::Env env, const Tree *tree, uint8_t offset) { 108 auto* data = env.GetInstanceData<AddonData>(); 109 TSNode result = {{0, 0, 0, 0}, nullptr, nullptr}; 110 result.tree = tree->tree_; 111 if (result.tree == nullptr) { 112 throw TypeError::New(env, "Argument must be a tree"); 113 } 114 115 result.id = UnmarshalNodeId(&data->transfer_buffer[offset * FIELD_COUNT_PER_NODE]); 116 result.context[0] = data->transfer_buffer[offset * FIELD_COUNT_PER_NODE + 2]; 117 result.context[1] = data->transfer_buffer[offset * FIELD_COUNT_PER_NODE + 3]; 118 result.context[2] = data->transfer_buffer[offset * FIELD_COUNT_PER_NODE + 4]; 119 result.context[3] = data->transfer_buffer[offset * FIELD_COUNT_PER_NODE + 5]; 120 return result; 121} 122 123struct SymbolSet { 124 void add(TSSymbol symbol) { symbols.push_back(symbol); } 125 [[nodiscard]] bool contains(TSSymbol symbol) const { return std::find(symbols.begin(), symbols.end(), symbol) != symbols.end(); } 126 private: 127 std::vector<TSSymbol> symbols; 128}; 129 130void symbol_set_from_js(SymbolSet *symbols, const Napi::Value &value, const TSLanguage *language) { 131 Env env = value.Env(); 132 133 if (!value.IsArray()) { 134 throw TypeError::New(env, "Argument must be a string or array of strings"); 135 } 136 137 unsigned symbol_count = ts_language_symbol_count(language); 138 139 auto js_types = value.As<Array>(); 140 for (unsigned i = 0, n = js_types.Length(); i < n; i++) { 141 Value js_node_type_value = js_types[i]; 142 if (js_node_type_value.IsString()) { 143 auto js_node_type = js_node_type_value.As<String>(); 144 std::string node_type = js_node_type.Utf8Value(); 145 146 if (node_type == "ERROR") { 147 symbols->add(static_cast<TSSymbol>(-1)); 148 } else { 149 for (TSSymbol j = 0; j < static_cast<TSSymbol>(symbol_count); j++) { 150 if (node_type == ts_language_symbol_name(language, j)) { 151 symbols->add(j); 152 } 153 } 154 } 155 156 continue; 157 } 158 159 throw TypeError::New(env, "Argument must be a string or array of strings"); 160 } 161} 162 163namespace { 164 165Napi::Value MarshalNullNode(Napi::Env env) { 166 auto *data = env.GetInstanceData<AddonData>(); 167 memset(data->transfer_buffer, 0, FIELD_COUNT_PER_NODE * sizeof(data->transfer_buffer[0])); 168 return env.Undefined(); 169} 170 171Napi::Value ToString(const Napi::CallbackInfo &info) { 172 Env env = info.Env(); 173 const Tree *tree = Tree::UnwrapTree(info[0]); 174 TSNode node = UnmarshalNode(env, tree); 175 if (node.id != nullptr) { 176 char *string = ts_node_string(node); 177 String result = String::New(env, string); 178 free(string); 179 return result; 180 } 181 182 return env.Undefined(); 183} 184 185Napi::Value FirstNamedChildForIndex(const Napi::CallbackInfo &info) { 186 Env env = info.Env(); 187 const Tree *tree = Tree::UnwrapTree(info[0]); 188 TSNode node = UnmarshalNode(env, tree); 189 if (node.id != nullptr) { 190 Napi::Maybe<uint32_t> byte = ByteCountFromJS(info[1]); 191 if (byte.IsJust()) { 192 return MarshalNode(info, tree, ts_node_first_named_child_for_byte(node, byte.Unwrap())); 193 } 194 } 195 return MarshalNullNode(env); 196} 197 198Napi::Value FirstChildForIndex(const Napi::CallbackInfo &info) { 199 Env env = info.Env(); 200 const Tree *tree = Tree::UnwrapTree(info[0]); 201 TSNode node = UnmarshalNode(env, tree); 202 203 if ((node.id != nullptr) && info.Length() > 1) { 204 Napi::Maybe<uint32_t> byte = ByteCountFromJS(info[1]); 205 if (byte.IsJust()) { 206 return MarshalNode(info, tree, ts_node_first_child_for_byte(node, byte.Unwrap())); 207 } 208 } 209 return MarshalNullNode(env); 210} 211 212Napi::Value NamedDescendantForIndex(const Napi::CallbackInfo &info) { 213 Env env = info.Env(); 214 const Tree *tree = Tree::UnwrapTree(info[0]); 215 TSNode node = UnmarshalNode(env, tree); 216 217 if (node.id != nullptr) { 218 Napi::Maybe<uint32_t> maybe_min = ByteCountFromJS(info[1]); 219 Napi::Maybe<uint32_t> maybe_max = ByteCountFromJS(info[2]); 220 if (maybe_min.IsJust() && maybe_max.IsJust()) { 221 uint32_t min = maybe_min.Unwrap(); 222 uint32_t max = maybe_max.Unwrap(); 223 return MarshalNode(info, tree, ts_node_named_descendant_for_byte_range(node, min, max)); 224 } 225 } 226 return MarshalNullNode(env); 227} 228 229Napi::Value DescendantForIndex(const Napi::CallbackInfo &info) { 230 Env env = info.Env(); 231 const Tree *tree = Tree::UnwrapTree(info[0]); 232 TSNode node = UnmarshalNode(env, tree); 233 234 if (node.id != nullptr) { 235 Napi::Maybe<uint32_t> maybe_min = ByteCountFromJS(info[1]); 236 Napi::Maybe<uint32_t> maybe_max = ByteCountFromJS(info[2]); 237 if (maybe_min.IsJust() && maybe_max.IsJust()) { 238 uint32_t min = maybe_min.Unwrap(); 239 uint32_t max = maybe_max.Unwrap(); 240 return MarshalNode(info, tree, ts_node_descendant_for_byte_range(node, min, max)); 241 } 242 } 243 return MarshalNullNode(env); 244} 245 246Napi::Value NamedDescendantForPosition(const Napi::CallbackInfo &info) { 247 Env env = info.Env(); 248 const Tree *tree = Tree::UnwrapTree(info[0]); 249 TSNode node = UnmarshalNode(env, tree); 250 251 if (node.id != nullptr) { 252 Napi::Maybe<TSPoint> maybe_min = PointFromJS(info[1]); 253 Napi::Maybe<TSPoint> maybe_max = PointFromJS(info[2]); 254 if (maybe_min.IsJust() && maybe_max.IsJust()) { 255 TSPoint min = maybe_min.Unwrap(); 256 TSPoint max = maybe_max.Unwrap(); 257 return MarshalNode(info, tree, ts_node_named_descendant_for_point_range(node, min, max)); 258 } 259 } 260 return MarshalNullNode(env); 261} 262 263Napi::Value DescendantForPosition(const Napi::CallbackInfo &info) { 264 Env env = info.Env(); 265 const Tree *tree = Tree::UnwrapTree(info[0]); 266 TSNode node = UnmarshalNode(env, tree); 267 268 if (node.id != nullptr) { 269 Napi::Maybe<TSPoint> maybe_min = PointFromJS(info[1]); 270 Napi::Maybe<TSPoint> maybe_max = PointFromJS(info[2]); 271 if (maybe_min.IsJust() && maybe_max.IsJust()) { 272 TSPoint min = maybe_min.Unwrap(); 273 TSPoint max = maybe_max.Unwrap(); 274 return MarshalNode(info, tree, ts_node_descendant_for_point_range(node, min, max)); 275 } 276 } 277 return MarshalNullNode(env); 278} 279 280Napi::Value Id(const Napi::CallbackInfo &info) { 281 Env env = info.Env(); 282 const Tree *tree = Tree::UnwrapTree(info[0]); 283 TSNode node = UnmarshalNode(env, tree); 284 285 if (node.id != nullptr) { 286 return Number::New(env, static_cast<double>(reinterpret_cast<uintptr_t>(node.id))); 287 } 288 289 return env.Undefined(); 290} 291 292Napi::Value TypeId(const Napi::CallbackInfo &info) { 293 Env env = info.Env(); 294 const Tree *tree = Tree::UnwrapTree(info[0]); 295 TSNode node = UnmarshalNode(env, tree); 296 297 if (node.id != nullptr) { 298 return Number::New(env, ts_node_symbol(node)); 299 } 300 301 return env.Undefined(); 302} 303 304Napi::Value GrammarId(const Napi::CallbackInfo &info) { 305 Env env = info.Env(); 306 const Tree *tree = Tree::UnwrapTree(info[0]); 307 TSNode node = UnmarshalNode(env, tree); 308 309 if (node.id != nullptr) { 310 return Number::New(env, ts_node_grammar_symbol(node)); 311 } 312 313 return env.Undefined(); 314} 315 316Napi::Value Type(const Napi::CallbackInfo &info) { 317 Env env = info.Env(); 318 const Tree *tree = Tree::UnwrapTree(info[0]); 319 TSNode node = UnmarshalNode(env, tree); 320 321 if (node.id != nullptr) { 322 return String::New(env, ts_node_type(node)); 323 } 324 325 return env.Undefined(); 326} 327 328Napi::Value GrammarType(const Napi::CallbackInfo &info) { 329 Env env = info.Env(); 330 const Tree *tree = Tree::UnwrapTree(info[0]); 331 TSNode node = UnmarshalNode(env, tree); 332 333 if (node.id != nullptr) { 334 return String::New(env, ts_node_grammar_type(node)); 335 } 336 337 return env.Undefined(); 338} 339 340Napi::Value IsNamed(const Napi::CallbackInfo &info) { 341 Env env = info.Env(); 342 const Tree *tree = Tree::UnwrapTree(info[0]); 343 TSNode node = UnmarshalNode(env, tree); 344 345 if (node.id != nullptr) { 346 return Boolean::New(env, ts_node_is_named(node)); 347 } 348 349 return env.Undefined(); 350} 351 352Napi::Value IsExtra(const Napi::CallbackInfo &info) { 353 Env env = info.Env(); 354 const Tree *tree = Tree::UnwrapTree(info[0]); 355 TSNode node = UnmarshalNode(env, tree); 356 357 if (node.id != nullptr) { 358 return Boolean::New(env, ts_node_is_extra(node)); 359 } 360 361 return env.Undefined(); 362} 363 364Napi::Value HasChanges(const Napi::CallbackInfo &info) { 365 Env env = info.Env(); 366 const Tree *tree = Tree::UnwrapTree(info[0]); 367 TSNode node = UnmarshalNode(env, tree); 368 if (node.id != nullptr) { 369 bool result = ts_node_has_changes(node); 370 return Boolean::New(env, result); 371 } 372 373 return env.Undefined(); 374} 375 376Napi::Value HasError(const Napi::CallbackInfo &info) { 377 Env env = info.Env(); 378 const Tree *tree = Tree::UnwrapTree(info[0]); 379 TSNode node = UnmarshalNode(env, tree); 380 if (node.id != nullptr) { 381 bool result = ts_node_has_error(node); 382 return Boolean::New(env, result); 383 } 384 385 return env.Undefined(); 386} 387 388Napi::Value IsError(const Napi::CallbackInfo &info) { 389 Env env = info.Env(); 390 const Tree *tree = Tree::UnwrapTree(info[0]); 391 TSNode node = UnmarshalNode(env, tree); 392 if (node.id != nullptr) { 393 bool result = ts_node_is_error(node); 394 return Boolean::New(env, result); 395 } 396 397 return env.Undefined(); 398} 399 400Napi::Value ParseState(const Napi::CallbackInfo &info) { 401 Env env = info.Env(); 402 const Tree *tree = Tree::UnwrapTree(info[0]); 403 TSNode node = UnmarshalNode(env, tree); 404 if (node.id != nullptr) { 405 return Number::New(env, ts_node_parse_state(node)); 406 } 407 return env.Undefined(); 408} 409 410Napi::Value NextParseState(const Napi::CallbackInfo &info) { 411 Env env = info.Env(); 412 const Tree *tree = Tree::UnwrapTree(info[0]); 413 TSNode node = UnmarshalNode(env, tree); 414 if (node.id != nullptr) { 415 return Number::New(env, ts_node_next_parse_state(node)); 416 } 417 return env.Undefined(); 418} 419 420Napi::Value IsMissing(const Napi::CallbackInfo &info) { 421 Env env = info.Env(); 422 const Tree *tree = Tree::UnwrapTree(info[0]); 423 TSNode node = UnmarshalNode(env, tree); 424 if (node.id != nullptr) { 425 bool result = ts_node_is_missing(node); 426 return Boolean::New(env, result); 427 } 428 429 return env.Undefined(); 430} 431 432Napi::Value StartIndex(const Napi::CallbackInfo &info) { 433 Env env = info.Env(); 434 const Tree *tree = Tree::UnwrapTree(info[0]); 435 TSNode node = UnmarshalNode(env, tree); 436 437 if (node.id != nullptr) { 438 auto result = static_cast<int32_t>(ts_node_start_byte(node) / 2); 439 return Number::New(env, result); 440 } 441 442 return env.Undefined(); 443} 444 445Napi::Value EndIndex(const Napi::CallbackInfo &info) { 446 Env env = info.Env(); 447 const Tree *tree = Tree::UnwrapTree(info[0]); 448 TSNode node = UnmarshalNode(env, tree); 449 450 if (node.id != nullptr) { 451 auto result = static_cast<int32_t>(ts_node_end_byte(node) / 2); 452 return Number::New(env, result); 453 } 454 455 return env.Undefined(); 456} 457 458Napi::Value StartPosition(const Napi::CallbackInfo &info) { 459 Env env = info.Env(); 460 const Tree *tree = Tree::UnwrapTree(info[0]); 461 TSNode node = UnmarshalNode(env, tree); 462 463 if (node.id != nullptr) { 464 TransferPoint(env, ts_node_start_point(node)); 465 } 466 467 return env.Undefined(); 468} 469 470Napi::Value EndPosition(const Napi::CallbackInfo &info) { 471 Env env = info.Env(); 472 const Tree *tree = Tree::UnwrapTree(info[0]); 473 TSNode node = UnmarshalNode(env, tree); 474 475 if (node.id != nullptr) { 476 TransferPoint(env, ts_node_end_point(node)); 477 } 478 479 return env.Undefined(); 480} 481 482Napi::Value Child(const Napi::CallbackInfo &info) { 483 Env env = info.Env(); 484 const Tree *tree = Tree::UnwrapTree(info[0]); 485 TSNode node = UnmarshalNode(env, tree); 486 487 if (node.id != nullptr) { 488 if (!info[1].IsNumber()) { 489 throw TypeError::New(env, "Second argument must be an integer"); 490 } 491 uint32_t index = info[1].As<Number>().Uint32Value(); 492 return MarshalNode(info, tree, ts_node_child(node, index)); 493 } 494 return MarshalNullNode(env); 495} 496 497Napi::Value ChildCount(const Napi::CallbackInfo &info) { 498 Env env = info.Env(); 499 const Tree *tree = Tree::UnwrapTree(info[0]); 500 TSNode node = UnmarshalNode(env, tree); 501 502 if (node.id != nullptr) { 503 return Number::New(env, ts_node_child_count(node)); 504 } 505 506 return env.Undefined(); 507} 508 509Napi::Value NamedChild(const Napi::CallbackInfo &info) { 510 Env env = info.Env(); 511 const Tree *tree = Tree::UnwrapTree(info[0]); 512 TSNode node = UnmarshalNode(env, tree); 513 514 if (node.id != nullptr) { 515 if (!info[1].IsNumber()) { 516 throw TypeError::New(env, "Second argument must be an integer"); 517 } 518 uint32_t index = info[1].As<Number>().Uint32Value(); 519 return MarshalNode(info, tree, ts_node_named_child(node, index)); 520 } 521 return MarshalNullNode(env); 522} 523 524Napi::Value NamedChildCount(const Napi::CallbackInfo &info) { 525 Env env = info.Env(); 526 const Tree *tree = Tree::UnwrapTree(info[0]); 527 TSNode node = UnmarshalNode(env, tree); 528 529 if (node.id != nullptr) { 530 return Number::New(env, ts_node_named_child_count(node)); 531 } 532 533 return env.Undefined(); 534} 535 536Napi::Value ChildForFieldName(const Napi::CallbackInfo &info) { 537 Env env = info.Env(); 538 const Tree *tree = Tree::UnwrapTree(info[0]); 539 TSNode node = UnmarshalNode(env, tree); 540 541 if (node.id != nullptr) { 542 if (!info[1].IsString()) { 543 throw TypeError::New(env, "Second argument must be a string"); 544 } 545 std::string field_name = info[1].As<String>().Utf8Value(); 546 return MarshalNode(info, tree, ts_node_child_by_field_name(node, field_name.c_str(), field_name.length())); 547 } 548 549 return MarshalNullNode(env); 550} 551 552Napi::Value ChildForFieldId(const Napi::CallbackInfo &info) { 553 Env env = info.Env(); 554 const Tree *tree = Tree::UnwrapTree(info[0]); 555 TSNode node = UnmarshalNode(env, tree); 556 if (node.id != nullptr) { 557 if (!info[1].IsNumber()) { 558 throw TypeError::New(env, "Second argument must be an integer"); 559 } 560 uint32_t field_id = info[1].As<Number>().Uint32Value(); 561 return MarshalNode(info, tree, ts_node_child_by_field_id(node, field_id)); 562 } 563 return MarshalNullNode(env); 564} 565 566Napi::Value FieldNameForChild(const Napi::CallbackInfo &info) { 567 Env env = info.Env(); 568 const Tree *tree = Tree::UnwrapTree(info[0]); 569 TSNode node = UnmarshalNode(env, tree); 570 if (node.id != nullptr) { 571 if (!info[1].IsNumber()) { 572 throw TypeError::New(env, "Second argument must be an integer"); 573 } 574 uint32_t child_id = info[1].As<Number>().Uint32Value(); 575 const char *field_name = ts_node_field_name_for_child(node, child_id); 576 if (field_name != nullptr) { 577 return String::New(env, field_name); 578 } 579 } 580 return env.Undefined(); 581} 582 583Napi::Value FieldNameForNamedChild(const Napi::CallbackInfo &info) { 584 Env env = info.Env(); 585 const Tree *tree = Tree::UnwrapTree(info[0]); 586 TSNode node = UnmarshalNode(env, tree); 587 if (node.id != nullptr) { 588 if (!info[1].IsNumber()) { 589 throw TypeError::New(env, "Second argument must be an integer"); 590 } 591 uint32_t child_id = info[1].As<Number>().Uint32Value(); 592 const char *field_name = ts_node_field_name_for_named_child(node, child_id); 593 if (field_name != nullptr) { 594 return String::New(env, field_name); 595 } 596 } 597 return env.Undefined(); 598} 599 600 601Napi::Value Children(const Napi::CallbackInfo &info) { 602 Env env = info.Env(); 603 auto* data = env.GetInstanceData<AddonData>(); 604 const Tree *tree = Tree::UnwrapTree(info[0]); 605 TSNode node = UnmarshalNode(env, tree); 606 if (node.id == nullptr) { 607 return env.Undefined(); 608 } 609 610 vector<TSNode> result; 611 ts_tree_cursor_reset(&data->scratch_cursor, node); 612 if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { 613 do { 614 TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); 615 result.push_back(child); 616 } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); 617 } 618 619 return MarshalNodes(info, tree, result.data(), result.size()); 620} 621 622Napi::Value NamedChildren(const Napi::CallbackInfo &info) { 623 Env env = info.Env(); 624 auto* data = env.GetInstanceData<AddonData>(); 625 const Tree *tree = Tree::UnwrapTree(info[0]); 626 TSNode node = UnmarshalNode(env, tree); 627 if (node.id == nullptr) { 628 return env.Undefined(); 629 } 630 631 vector<TSNode> result; 632 ts_tree_cursor_reset(&data->scratch_cursor, node); 633 if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { 634 do { 635 TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); 636 if (ts_node_is_named(child)) { 637 result.push_back(child); 638 } 639 } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); 640 } 641 642 return MarshalNodes(info, tree, result.data(), result.size()); 643} 644 645Napi::Value ChildrenForFieldName(const Napi::CallbackInfo &info) { 646 Env env = info.Env(); 647 const Tree *tree = Tree::UnwrapTree(info[0]); 648 TSNode node = UnmarshalNode(env, tree); 649 if (node.id == nullptr) { 650 return env.Undefined(); 651 } 652 653 if (!info[1].IsString()) { 654 throw TypeError::New(env, "First argument must be a string"); 655 } 656 std::string field_name = info[1].As<String>().Utf8Value(); 657 658 TSTreeCursor cursor = ts_tree_cursor_new(node); 659 660 const TSLanguage *language = ts_tree_language(node.tree); 661 TSFieldId field_id = ts_language_field_id_for_name(language, field_name.c_str(), field_name.length()); 662 663 bool done = field_id == 0; 664 if (!done) { 665 ts_tree_cursor_reset(&cursor, node); 666 ts_tree_cursor_goto_first_child(&cursor); 667 } 668 669 vector<TSNode> result; 670 while (!done) { 671 while (ts_tree_cursor_current_field_id(&cursor) != field_id) { 672 if (!ts_tree_cursor_goto_next_sibling(&cursor)) { 673 done = true; 674 break; 675 } 676 } 677 if (done) { 678 break; 679 } 680 TSNode result_node = ts_tree_cursor_current_node(&cursor); 681 if (!ts_tree_cursor_goto_next_sibling(&cursor)) { 682 done = true; 683 } 684 result.push_back(result_node); 685 } 686 687 return MarshalNodes(info, tree, result.data(), result.size()); 688} 689 690Napi::Value ChildrenForFieldId(const Napi::CallbackInfo &info) { 691 Env env = info.Env(); 692 const Tree *tree = Tree::UnwrapTree(info[0]); 693 TSNode node = UnmarshalNode(env, tree); 694 if (node.id == nullptr) { 695 return env.Undefined(); 696 } 697 698 if (!info[1].IsNumber()) { 699 throw TypeError::New(env, "First argument must be an integer"); 700 } 701 uint32_t field_id = info[1].As<Number>().Uint32Value(); 702 703 704 TSTreeCursor cursor = ts_tree_cursor_new(node); 705 706 bool done = field_id == 0; 707 if (!done) { 708 ts_tree_cursor_reset(&cursor, node); 709 ts_tree_cursor_goto_first_child(&cursor); 710 } 711 712 vector<TSNode> result; 713 while (!done) { 714 while (ts_tree_cursor_current_field_id(&cursor) != field_id) { 715 if (!ts_tree_cursor_goto_next_sibling(&cursor)) { 716 done = true; 717 break; 718 } 719 } 720 if (done) { 721 break; 722 } 723 TSNode result_node = ts_tree_cursor_current_node(&cursor); 724 if (!ts_tree_cursor_goto_next_sibling(&cursor)) { 725 done = true; 726 } 727 result.push_back(result_node); 728 } 729 730 return MarshalNodes(info, tree, result.data(), result.size()); 731} 732 733Napi::Value FirstChild(const Napi::CallbackInfo &info) { 734 Env env = info.Env(); 735 const Tree *tree = Tree::UnwrapTree(info[0]); 736 TSNode node = UnmarshalNode(env, tree); 737 if (node.id != nullptr) { 738 return MarshalNode(info, tree, ts_node_child(node, 0)); 739 } 740 return MarshalNullNode(env); 741} 742 743Napi::Value FirstNamedChild(const Napi::CallbackInfo &info) { 744 Env env = info.Env(); 745 const Tree *tree = Tree::UnwrapTree(info[0]); 746 TSNode node = UnmarshalNode(env, tree); 747 if (node.id != nullptr) { 748 return MarshalNode(info, tree, ts_node_named_child(node, 0)); 749 } 750 return MarshalNullNode(env); 751} 752 753Napi::Value LastChild(const Napi::CallbackInfo &info) { 754 Env env = info.Env(); 755 const Tree *tree = Tree::UnwrapTree(info[0]); 756 TSNode node = UnmarshalNode(env, tree); 757 if (node.id != nullptr) { 758 uint32_t child_count = ts_node_child_count(node); 759 if (child_count > 0) { 760 return MarshalNode(info, tree, ts_node_child(node, child_count - 1)); 761 } 762 } 763 return MarshalNullNode(env); 764} 765 766Napi::Value LastNamedChild(const Napi::CallbackInfo &info) { 767 Env env = info.Env(); 768 const Tree *tree = Tree::UnwrapTree(info[0]); 769 TSNode node = UnmarshalNode(env, tree); 770 if (node.id != nullptr) { 771 uint32_t child_count = ts_node_named_child_count(node); 772 if (child_count > 0) { 773 return MarshalNode(info, tree, ts_node_named_child(node, child_count - 1)); 774 } 775 } 776 return MarshalNullNode(env); 777} 778 779Napi::Value Parent(const Napi::CallbackInfo &info) { 780 Env env = info.Env(); 781 const Tree *tree = Tree::UnwrapTree(info[0]); 782 TSNode node = UnmarshalNode(env, tree); 783 if (node.id != nullptr) { 784 return MarshalNode(info, tree, ts_node_parent(node)); 785 } 786 return MarshalNullNode(env); 787} 788 789Napi::Value ChildWithDescendant(const Napi::CallbackInfo &info) { 790 Env env = info.Env(); 791 const Tree *tree = Tree::UnwrapTree(info[0]); 792 TSNode self = UnmarshalNode(env, tree); 793 const Tree *child_tree = Tree::UnwrapTree(info[1]); 794 TSNode child_node = UnmarshalNode(env, child_tree, 1); 795 if (self.id != nullptr && child_node.id != nullptr) { 796 return MarshalNode(info, tree, ts_node_child_with_descendant(self, child_node)); 797 } 798 return MarshalNullNode(env); 799} 800 801Napi::Value NextSibling(const Napi::CallbackInfo &info) { 802 Env env = info.Env(); 803 const Tree *tree = Tree::UnwrapTree(info[0]); 804 TSNode node = UnmarshalNode(env, tree); 805 if (node.id != nullptr) { 806 return MarshalNode(info, tree, ts_node_next_sibling(node)); 807 } 808 return MarshalNullNode(env); 809} 810 811Napi::Value NextNamedSibling(const Napi::CallbackInfo &info) { 812 Env env = info.Env(); 813 const Tree *tree = Tree::UnwrapTree(info[0]); 814 TSNode node = UnmarshalNode(env, tree); 815 if (node.id != nullptr) { 816 return MarshalNode(info, tree, ts_node_next_named_sibling(node)); 817 } 818 return MarshalNullNode(env); 819} 820 821Napi::Value PreviousSibling(const Napi::CallbackInfo &info) { 822 Env env = info.Env(); 823 const Tree *tree = Tree::UnwrapTree(info[0]); 824 TSNode node = UnmarshalNode(env, tree); 825 if (node.id != nullptr) { 826 return MarshalNode(info, tree, ts_node_prev_sibling(node)); 827 } 828 return MarshalNullNode(env); 829} 830 831Napi::Value PreviousNamedSibling(const Napi::CallbackInfo &info) { 832 Env env = info.Env(); 833 const Tree *tree = Tree::UnwrapTree(info[0]); 834 TSNode node = UnmarshalNode(env, tree); 835 if (node.id != nullptr) { 836 return MarshalNode(info, tree, ts_node_prev_named_sibling(node)); 837 } 838 return MarshalNullNode(env); 839} 840 841Napi::Value DescendantCount(const Napi::CallbackInfo &info) { 842 Env env = info.Env(); 843 const Tree *tree = Tree::UnwrapTree(info[0]); 844 TSNode node = UnmarshalNode(env, tree); 845 if (node.id != nullptr) { 846 return Number::New(env, ts_node_descendant_count(node)); 847 } 848 return env.Undefined(); 849} 850 851Napi::Value DescendantsOfType(const Napi::CallbackInfo &info) { 852 Env env = info.Env(); 853 auto* data = env.GetInstanceData<AddonData>(); 854 const Tree *tree = Tree::UnwrapTree(info[0]); 855 TSNode node = UnmarshalNode(env, tree); 856 if (node.id == nullptr) { 857 return env.Undefined(); 858 } 859 860 SymbolSet symbols; 861 symbol_set_from_js(&symbols, info[1], ts_tree_language(node.tree)); 862 863 TSPoint start_point = {0, 0}; 864 TSPoint end_point = {UINT32_MAX, UINT32_MAX}; 865 866 if (info.Length() > 2 && info[2].IsObject()) { 867 auto maybe_start_point = PointFromJS(info[2]); 868 if (maybe_start_point.IsNothing()) { 869 return env.Undefined(); 870 } 871 start_point = maybe_start_point.Unwrap(); 872 } 873 874 if (info.Length() > 3 && info[3].IsObject()) { 875 auto maybe_end_point = PointFromJS(info[3]); 876 if (maybe_end_point.IsNothing()) { 877 return env.Undefined(); 878 } 879 end_point = maybe_end_point.Unwrap(); 880 } 881 882 vector<TSNode> found; 883 ts_tree_cursor_reset(&data->scratch_cursor, node); 884 auto already_visited_children = false; 885 while (true) { 886 TSNode descendant = ts_tree_cursor_current_node(&data->scratch_cursor); 887 888 if (!already_visited_children) { 889 if (ts_node_end_point(descendant) <= start_point) { 890 if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { 891 already_visited_children = false; 892 } else { 893 if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) { 894 break; 895 } 896 already_visited_children = true; 897 } 898 continue; 899 } 900 901 if (end_point <= ts_node_start_point(descendant)) { 902 break; 903 } 904 905 if (symbols.contains(ts_node_symbol(descendant))) { 906 found.push_back(descendant); 907 } 908 909 if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { 910 already_visited_children = false; 911 } else if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { 912 already_visited_children = false; 913 } else { 914 if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) { 915 break; 916 } 917 already_visited_children = true; 918 } 919 } else { 920 if (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)) { 921 already_visited_children = false; 922 } else { 923 if (!ts_tree_cursor_goto_parent(&data->scratch_cursor)) { 924 break; 925 } 926 } 927 } 928 } 929 930 return MarshalNodes(info, tree, found.data(), found.size()); 931} 932 933Napi::Value ChildNodesForFieldId(const Napi::CallbackInfo &info) { 934 Env env = info.Env(); 935 auto* data = env.GetInstanceData<AddonData>(); 936 const Tree *tree = Tree::UnwrapTree(info[0]); 937 TSNode node = UnmarshalNode(env, tree); 938 if (node.id == nullptr) { 939 return env.Undefined(); 940 } 941 942 if (!info[1].IsNumber()) { 943 throw TypeError::New(env, "Second argument must be an integer"); 944 } 945 auto maybe_field_id = info[1].As<Number>(); 946 uint32_t field_id = maybe_field_id.Uint32Value(); 947 948 vector<TSNode> result; 949 ts_tree_cursor_reset(&data->scratch_cursor, node); 950 if (ts_tree_cursor_goto_first_child(&data->scratch_cursor)) { 951 do { 952 TSNode child = ts_tree_cursor_current_node(&data->scratch_cursor); 953 if (ts_tree_cursor_current_field_id(&data->scratch_cursor) == field_id) { 954 result.push_back(child); 955 } 956 } while (ts_tree_cursor_goto_next_sibling(&data->scratch_cursor)); 957 } 958 959 return MarshalNodes(info, tree, result.data(), result.size()); 960} 961 962Napi::Value ChildNodeForFieldId(const Napi::CallbackInfo &info) { 963 Env env = info.Env(); 964 const Tree *tree = Tree::UnwrapTree(info[0]); 965 TSNode node = UnmarshalNode(env, tree); 966 967 if (node.id != nullptr) { 968 if (!info[1].IsNumber()) { 969 throw TypeError::New(env, "Second argument must be an integer"); 970 } 971 auto maybe_field_id = info[1].As<Number>(); 972 uint32_t field_id = maybe_field_id.Uint32Value(); 973 return MarshalNode(info, tree, ts_node_child_by_field_id(node, field_id)); 974 } 975 return MarshalNullNode(env); 976} 977 978Napi::Value Closest(const Napi::CallbackInfo &info) { 979 Env env = info.Env(); 980 const Tree *tree = Tree::UnwrapTree(info[0]); 981 TSNode node = UnmarshalNode(env, tree); 982 if (node.id == nullptr) { 983 return env.Undefined(); 984 } 985 986 SymbolSet symbols; 987 symbol_set_from_js(&symbols, info[1], ts_tree_language(node.tree)); 988 989 for (;;) { 990 TSNode parent = ts_node_parent(node); 991 if (parent.id == nullptr) { 992 break; 993 } 994 if (symbols.contains(ts_node_symbol(parent))) { 995 return MarshalNode(info, tree, parent); 996 } 997 node = parent; 998 } 999 1000 return MarshalNullNode(env); 1001} 1002 1003Napi::Value Walk(const Napi::CallbackInfo &info) { 1004 Env env = info.Env(); 1005 const Tree *tree = Tree::UnwrapTree(info[0]); 1006 TSNode node = UnmarshalNode(env, tree); 1007 TSTreeCursor cursor = ts_tree_cursor_new(node); 1008 return TreeCursor::NewInstance(env, cursor); 1009} 1010 1011} // namespace 1012 1013void Init(Napi::Env env, Napi::Object exports) { 1014 auto *data = env.GetInstanceData<AddonData>(); 1015 1016 Object result = Object::New(env); 1017 1018 struct FunctionPair { 1019 const char *name; 1020 Napi::Function::Callback callback; 1021 }; 1022 1023 FunctionPair methods[] = { 1024 {"id", Id}, 1025 {"typeId", TypeId}, 1026 {"grammarId", GrammarId}, 1027 {"type", Type}, 1028 {"grammarType", GrammarType}, 1029 {"isNamed", IsNamed}, 1030 {"isExtra", IsExtra}, 1031 {"hasChanges", HasChanges}, 1032 {"hasError", HasError}, 1033 {"isError", IsError}, 1034 {"parseState", ParseState}, 1035 {"nextParseState", NextParseState}, 1036 {"isMissing", IsMissing}, 1037 {"startIndex", StartIndex}, 1038 {"endIndex", EndIndex}, 1039 {"startPosition", StartPosition}, 1040 {"endPosition", EndPosition}, 1041 {"child", Child}, 1042 {"childCount", ChildCount}, 1043 {"namedChild", NamedChild}, 1044 {"namedChildCount", NamedChildCount}, 1045 {"childForFieldName", ChildForFieldName}, 1046 {"childForFieldId", ChildForFieldId}, 1047 {"fieldNameForChild", FieldNameForChild}, 1048 {"fieldNameForNamedChild", FieldNameForNamedChild}, 1049 {"children", Children}, 1050 {"namedChildren", NamedChildren}, 1051 {"childrenForFieldName", ChildrenForFieldName}, 1052 {"childrenForFieldId", ChildrenForFieldId}, 1053 {"parent", Parent}, 1054 {"childWithDescendant", ChildWithDescendant}, 1055 {"nextSibling", NextSibling}, 1056 {"previousSibling", PreviousSibling}, 1057 {"nextNamedSibling", NextNamedSibling}, 1058 {"previousNamedSibling", PreviousNamedSibling}, 1059 {"descendantCount", DescendantCount}, 1060 {"descendantForIndex", DescendantForIndex}, 1061 {"namedDescendantForIndex", NamedDescendantForIndex}, 1062 {"descendantForPosition", DescendantForPosition}, 1063 {"namedDescendantForPosition", NamedDescendantForPosition}, 1064 {"toString", ToString}, 1065 {"walk", Walk}, 1066 {"firstChild", FirstChild}, 1067 {"lastChild", LastChild}, 1068 {"firstNamedChild", FirstNamedChild}, 1069 {"lastNamedChild", LastNamedChild}, 1070 {"firstChildForIndex", FirstChildForIndex}, 1071 {"firstNamedChildForIndex", FirstNamedChildForIndex}, 1072 {"descendantsOfType", DescendantsOfType}, 1073 {"closest", Closest}, 1074 {"childNodeForFieldId", ChildNodeForFieldId}, 1075 {"childNodesForFieldId", ChildNodesForFieldId}, 1076 }; 1077 1078 for (auto & method : methods) { 1079 result[method.name] = Napi::Function::New(env, method.callback); 1080 } 1081 1082 data->module_exports = Napi::Persistent(exports); 1083 setup_transfer_buffer(env, 1); 1084 1085 exports["NodeMethods"] = result; 1086} 1087 1088} // namespace node_tree_sitter::node_methods