fix/audit-findings #5
4 changed files with 42 additions and 0 deletions
fix(c): parse .c files with the C grammar
`.c` files were parsed with tree-sitter-cpp, so valid C that uses C++ keywords as identifiers (`int delete = 0; int new = 1;`, a parameter named `class`) produced grammar-error diagnostics and lost symbols. `.c` files now parse with tree-sitter-c (pinned =0.24.2, backend `c:0.24.2`) while staying on the shared C/C++ extraction path, so C sources and the headers they include still share one include/declaration index. Headers (`.h`) keep the C++ grammar, which parses the C subset. Test: cpp_xtu::c_sources_parse_with_the_c_grammar fails before this change (grammar errors in util.c).
commit
e03fa40ccc
11
Cargo.lock
generated
11
Cargo.lock
generated
|
|
@ -84,6 +84,7 @@ dependencies = [
|
|||
"serde_json",
|
||||
"tempfile",
|
||||
"tree-sitter",
|
||||
"tree-sitter-c",
|
||||
"tree-sitter-cpp",
|
||||
"tree-sitter-dart",
|
||||
"tree-sitter-javascript",
|
||||
|
|
@ -423,6 +424,16 @@ dependencies = [
|
|||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-c"
|
||||
version = "0.24.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a9b2eb57a55fed6b00812912e730b7a275cf4fe98bfd6a5d76263d4438371728"
|
||||
dependencies = [
|
||||
"cc",
|
||||
"tree-sitter-language",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tree-sitter-cpp"
|
||||
version = "0.23.4"
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ regex = "1.12"
|
|||
serde = { version = "1.0", features = ["derive"] }
|
||||
serde_json = "1.0"
|
||||
tree-sitter = "=0.26.13"
|
||||
tree-sitter-c = "=0.24.2"
|
||||
tree-sitter-cpp = "=0.23.4"
|
||||
tree-sitter-javascript = "=0.25.0"
|
||||
tree-sitter-typescript = "=0.23.2"
|
||||
|
|
|
|||
|
|
@ -184,6 +184,9 @@ fn preprocessor_alternative_lines(source: &str) -> Vec<bool> {
|
|||
|
||||
pub(crate) fn extract(language: &str, path: &str, source: &str) -> Result<Document> {
|
||||
let (grammar, version) = match language {
|
||||
// `.c` shares the C/C++ extraction path (and header index) but must parse
|
||||
// as C: identifiers such as `new`, `delete` or `class` are valid C.
|
||||
"cpp" if path.ends_with(".c") => (tree_sitter_c::LANGUAGE, "c:0.24.2"),
|
||||
"cpp" => (tree_sitter_cpp::LANGUAGE, "cpp:0.23.4"),
|
||||
"rust" => (tree_sitter_rust::LANGUAGE, "rust:0.24.2"),
|
||||
"javascript" => (tree_sitter_javascript::LANGUAGE, "javascript:0.25.0"),
|
||||
|
|
|
|||
|
|
@ -406,3 +406,30 @@ fn preprocessor_alternative_branches_are_not_call_targets() {
|
|||
Some("alternative")
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn c_sources_parse_with_the_c_grammar() {
|
||||
// `.c` files went through the C++ grammar, so valid C using C++ keywords as
|
||||
// identifiers produced grammar-error diagnostics and damaged extraction.
|
||||
let model = scan_files(&[
|
||||
("src/util.h", "int twice(int new);\n"),
|
||||
(
|
||||
"src/util.c",
|
||||
"#include \"util.h\"\nint twice(int new) { int delete = new; return delete * 2; }\n",
|
||||
),
|
||||
(
|
||||
"src/main.c",
|
||||
"#include \"util.h\"\nint main(void) { int class = 1; return twice(class); }\n",
|
||||
),
|
||||
]);
|
||||
let grammar_errors: Vec<_> = model
|
||||
.diagnostics
|
||||
.iter()
|
||||
.filter(|d| d.path.as_deref().is_some_and(|p| p.ends_with(".c")))
|
||||
.map(|d| d.message.clone())
|
||||
.collect();
|
||||
assert!(grammar_errors.is_empty(), "{grammar_errors:?}");
|
||||
let (target, reason) = single_call(&model, function(&model, "src/main.c", "main"));
|
||||
assert_eq!(target.path.as_deref(), Some("src/util.c"));
|
||||
assert_eq!(reason, None);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue