Add support for category comments in Nix option collection

The nix module now parses `/* */` comments as categories and associates
them with subsequent options. The output format has been updated to
include the category prefix before the option path. The internal state
is maintained during traversal to ensure correct category propagation
through nested structures.
This commit is contained in:
2025-12-01 00:43:23 +01:00
parent cb35269308
commit e6e1695084
2 changed files with 90 additions and 60 deletions

View File

@@ -17,8 +17,8 @@ fn main() {
eprintln!(); eprintln!();
} }
let options: Vec<(String, bool)> = nix::collect_nix_options_with_path(&ast.syntax(), ""); let options: Vec<(String, String, bool)> = nix::collect_nix_options(&ast.syntax());
for (path, value) in options { for (category, path, value) in options {
println!("{} = {};", path, value); println!("{}: {} = {};", category, path, value);
} }
} }

View File

@@ -1,12 +1,36 @@
use rnix::{NodeOrToken, SyntaxKind, SyntaxNode}; use rnix::{NodeOrToken, SyntaxKind, SyntaxNode, SyntaxToken};
pub fn collect_nix_options_with_path(node: &SyntaxNode, current_path: &str) -> Vec<(String, bool)> { pub fn collect_nix_options(node: &SyntaxNode) -> Vec<(String, String, bool)> {
let mut result: Vec<(String, bool)> = Vec::new(); collect_nix_options_with_path(node, "", "")
}
for child in node.children_with_tokens() { fn collect_nix_options_with_path(
if let NodeOrToken::Node(child_node) = child { node: &SyntaxNode,
match child_node.kind() { current_path: &str,
SyntaxKind::NODE_ATTRPATH_VALUE => { current_category: &str,
) -> Vec<(String, String, bool)> {
let mut result: Vec<(String, String, bool)> = Vec::new();
let mut category: String = current_category.to_string();
let children: Vec<NodeOrToken<SyntaxNode, SyntaxToken>> = node.children_with_tokens().collect();
for i in 0..children.len() {
match &children[i] {
NodeOrToken::Token(token) if token.kind() == SyntaxKind::TOKEN_COMMENT => {
let text: &str = token.text();
if text.starts_with("/*") && text.ends_with("*/") {
let content: String = text
.trim_start_matches("/*")
.trim_end_matches("*/")
.trim()
.to_string();
category = content;
}
}
NodeOrToken::Node(child_node)
if child_node.kind() == SyntaxKind::NODE_ATTRPATH_VALUE =>
{
let mut attr_path: String = String::new(); let mut attr_path: String = String::new();
let mut value_node: Option<SyntaxNode> = None; let mut value_node: Option<SyntaxNode> = None;
@@ -32,6 +56,7 @@ pub fn collect_nix_options_with_path(node: &SyntaxNode, current_path: &str) -> V
result.extend(collect_nix_options_with_path( result.extend(collect_nix_options_with_path(
&grand_node, &grand_node,
&new_path, &new_path,
&category,
)); ));
} }
_ => {} _ => {}
@@ -53,14 +78,19 @@ pub fn collect_nix_options_with_path(node: &SyntaxNode, current_path: &str) -> V
bool_value = true; bool_value = true;
} }
result.push((full_path, bool_value)); result.push((category.clone(), full_path, bool_value));
} }
} }
_ => { NodeOrToken::Node(child_node) => {
result.extend(collect_nix_options_with_path(&child_node, current_path)); result.extend(collect_nix_options_with_path(
} child_node,
current_path,
&category,
));
} }
_ => {}
} }
} }