Iterative variable walker for config languages with nested structure. Used by YAML, TOML, INI, JSON.
| 5251 | // Iterative variable walker for config languages with nested structure. |
| 5252 | // Used by YAML, TOML, INI, JSON. |
| 5253 | static void walk_variables_iter(CBMExtractCtx *ctx, TSNode root, const CBMLangSpec *spec) { |
| 5254 | TSNodeStack stack; |
| 5255 | ts_nstack_init(&stack, ctx->arena, CBM_SZ_256); |
| 5256 | ts_nstack_push(&stack, ctx->arena, root); |
| 5257 | |
| 5258 | while (stack.count > 0) { |
| 5259 | TSNode node = ts_nstack_pop(&stack); |
| 5260 | uint32_t count = ts_node_child_count(node); |
| 5261 | for (int i = (int)count - SKIP_CHAR; i >= 0; i--) { |
| 5262 | TSNode child = ts_node_child(node, (uint32_t)i); |
| 5263 | if (ts_node_is_null(child)) { |
| 5264 | continue; |
| 5265 | } |
| 5266 | if (cbm_kind_in_set(child, spec->variable_node_types)) { |
| 5267 | /* parent of `child` is `node` (we're iterating its children) — |
| 5268 | * pass it directly to avoid the O(n) ts_node_parent rescan. */ |
| 5269 | if (cbm_is_module_level_p(node, ctx->language)) { |
| 5270 | extract_var_names(ctx, child, spec); |
| 5271 | } |
| 5272 | } |
| 5273 | const char *ck = ts_node_type(child); |
| 5274 | if (strcmp(ck, "document") == 0 || strcmp(ck, "block_node") == 0 || |
| 5275 | strcmp(ck, "block_mapping") == 0 || strcmp(ck, "stream") == 0 || |
| 5276 | strcmp(ck, "table") == 0 || strcmp(ck, "table_array_element") == 0 || |
| 5277 | strcmp(ck, "section") == 0 || strcmp(ck, "object") == 0 || |
| 5278 | strcmp(ck, "array") == 0 || strcmp(ck, "pair") == 0 || strcmp(ck, "element") == 0 || |
| 5279 | strcmp(ck, "content") == 0) { |
| 5280 | ts_nstack_push(&stack, ctx->arena, child); |
| 5281 | } |
| 5282 | } |
| 5283 | } |
| 5284 | } |
| 5285 | |
| 5286 | // True if the file's basename is values.yaml / values.yml (Helm values, #338). |
| 5287 | static bool is_helm_values_file(const char *rel) { |
no test coverage detected