codeprysm_core/
embedded_queries.rs

1//! Embedded Tree-sitter queries for code parsing.
2//!
3//! This module contains all the tree-sitter query files embedded at compile time,
4//! allowing the binary to work without external query files.
5//!
6//! ## Query Types
7//!
8//! - **Code Tags**: Extract code entities (functions, classes, etc.) from source files
9//! - **Manifest Tags**: Extract component info and dependencies from manifest files
10
11use crate::parser::{ManifestLanguage, SupportedLanguage};
12
13// Base tag queries - embedded at compile time
14const C_TAGS: &str = include_str!("../queries/c-tags.scm");
15const CPP_TAGS: &str = include_str!("../queries/cpp-tags.scm");
16const CSHARP_TAGS: &str = include_str!("../queries/csharp-tags.scm");
17const GO_TAGS: &str = include_str!("../queries/go-tags.scm");
18const JAVASCRIPT_TAGS: &str = include_str!("../queries/javascript-tags.scm");
19const PYTHON_TAGS: &str = include_str!("../queries/python-tags.scm");
20const RUST_TAGS: &str = include_str!("../queries/rust-tags.scm");
21const TYPESCRIPT_TAGS: &str = include_str!("../queries/typescript-tags.scm");
22
23// Test overlay queries - embedded at compile time
24const C_TEST: &str = include_str!("../queries/overlays/c-test.scm");
25const CPP_TEST: &str = include_str!("../queries/overlays/cpp-test.scm");
26const CSHARP_TEST: &str = include_str!("../queries/overlays/csharp-test.scm");
27const GO_TEST: &str = include_str!("../queries/overlays/go-test.scm");
28const JAVASCRIPT_TEST: &str = include_str!("../queries/overlays/javascript-test.scm");
29const PYTHON_TEST: &str = include_str!("../queries/overlays/python-test.scm");
30const RUST_TEST: &str = include_str!("../queries/overlays/rust-test.scm");
31const TYPESCRIPT_TEST: &str = include_str!("../queries/overlays/typescript-test.scm");
32
33// Manifest tag queries - embedded at compile time
34const JSON_MANIFEST_TAGS: &str = include_str!("../queries/json-manifest-tags.scm");
35const TOML_MANIFEST_TAGS: &str = include_str!("../queries/toml-manifest-tags.scm");
36const GOMOD_MANIFEST_TAGS: &str = include_str!("../queries/gomod-manifest-tags.scm");
37const XML_MANIFEST_TAGS: &str = include_str!("../queries/xml-manifest-tags.scm");
38const CMAKE_MANIFEST_TAGS: &str = include_str!("../queries/cmake-manifest-tags.scm");
39
40/// Get the embedded query source for a language.
41///
42/// Returns the base tags query concatenated with any overlay queries.
43pub fn get_query(language: SupportedLanguage) -> Option<String> {
44    let base = get_base_query(language)?;
45    let overlay = get_test_overlay(language);
46
47    match overlay {
48        Some(test_query) => Some(format!("{}\n\n{}", base, test_query)),
49        None => Some(base.to_string()),
50    }
51}
52
53/// Get only the base tags query for a language.
54pub fn get_base_query(language: SupportedLanguage) -> Option<&'static str> {
55    match language {
56        SupportedLanguage::C => Some(C_TAGS),
57        SupportedLanguage::Cpp => Some(CPP_TAGS),
58        SupportedLanguage::CSharp => Some(CSHARP_TAGS),
59        SupportedLanguage::Go => Some(GO_TAGS),
60        SupportedLanguage::JavaScript => Some(JAVASCRIPT_TAGS),
61        SupportedLanguage::Python => Some(PYTHON_TAGS),
62        SupportedLanguage::Rust => Some(RUST_TAGS),
63        SupportedLanguage::TypeScript => Some(TYPESCRIPT_TAGS),
64        _ => None,
65    }
66}
67
68/// Get the test overlay query for a language.
69fn get_test_overlay(language: SupportedLanguage) -> Option<&'static str> {
70    match language {
71        SupportedLanguage::C => Some(C_TEST),
72        SupportedLanguage::Cpp => Some(CPP_TEST),
73        SupportedLanguage::CSharp => Some(CSHARP_TEST),
74        SupportedLanguage::Go => Some(GO_TEST),
75        SupportedLanguage::JavaScript => Some(JAVASCRIPT_TEST),
76        SupportedLanguage::Python => Some(PYTHON_TEST),
77        SupportedLanguage::Rust => Some(RUST_TEST),
78        SupportedLanguage::TypeScript => Some(TYPESCRIPT_TEST),
79        _ => None,
80    }
81}
82
83/// Check if embedded queries are available for a language.
84pub fn has_embedded_query(language: SupportedLanguage) -> bool {
85    get_base_query(language).is_some()
86}
87
88/// Get a list of all languages with embedded queries.
89pub fn supported_languages() -> &'static [SupportedLanguage] {
90    &[
91        SupportedLanguage::C,
92        SupportedLanguage::Cpp,
93        SupportedLanguage::CSharp,
94        SupportedLanguage::Go,
95        SupportedLanguage::JavaScript,
96        SupportedLanguage::Python,
97        SupportedLanguage::Rust,
98        SupportedLanguage::TypeScript,
99    ]
100}
101
102// ============================================================================
103// Manifest Queries
104// ============================================================================
105
106/// Get the embedded manifest query for a manifest language.
107///
108/// Returns the query source for extracting component names and dependencies
109/// from manifest files (package.json, Cargo.toml, etc.).
110pub fn get_manifest_query(language: ManifestLanguage) -> &'static str {
111    match language {
112        ManifestLanguage::Json => JSON_MANIFEST_TAGS,
113        ManifestLanguage::Toml => TOML_MANIFEST_TAGS,
114        ManifestLanguage::GoMod => GOMOD_MANIFEST_TAGS,
115        ManifestLanguage::Xml => XML_MANIFEST_TAGS,
116        ManifestLanguage::CMake => CMAKE_MANIFEST_TAGS,
117    }
118}
119
120/// Check if embedded manifest queries are available for a manifest language.
121///
122/// Always returns true since all manifest languages have embedded queries.
123pub fn has_manifest_query(language: ManifestLanguage) -> bool {
124    // All manifest languages have embedded queries
125    match language {
126        ManifestLanguage::Json
127        | ManifestLanguage::Toml
128        | ManifestLanguage::GoMod
129        | ManifestLanguage::Xml
130        | ManifestLanguage::CMake => true,
131    }
132}
133
134/// Get a list of all manifest languages with embedded queries.
135pub fn supported_manifest_languages() -> &'static [ManifestLanguage] {
136    &[
137        ManifestLanguage::Json,
138        ManifestLanguage::Toml,
139        ManifestLanguage::GoMod,
140        ManifestLanguage::Xml,
141        ManifestLanguage::CMake,
142    ]
143}
144
145/// Test function for verifying incremental sync works.
146/// This function exists solely to test that graph updates and search indexing work correctly.
147pub fn sync_verification_test_function() -> &'static str {
148    "sync_verification_success"
149}
150
151#[cfg(test)]
152mod tests {
153    use super::*;
154
155    #[test]
156    fn test_embedded_queries_exist() {
157        for lang in supported_languages() {
158            let query = get_query(*lang);
159            assert!(query.is_some(), "Query missing for {:?}", lang);
160            assert!(!query.unwrap().is_empty(), "Query empty for {:?}", lang);
161        }
162    }
163
164    #[test]
165    fn test_base_queries_contain_definitions() {
166        // All base queries should contain some form of definition pattern
167        for lang in supported_languages() {
168            let base = get_base_query(*lang).unwrap();
169            assert!(
170                base.contains("definition") || base.contains("@name"),
171                "Base query for {:?} should contain definition patterns",
172                lang
173            );
174        }
175    }
176
177    #[test]
178    fn test_test_overlays_contain_test_patterns() {
179        // All test overlays should contain test-related patterns
180        for lang in supported_languages() {
181            if let Some(overlay) = get_test_overlay(*lang) {
182                assert!(
183                    overlay.contains("test") || overlay.contains("Test"),
184                    "Test overlay for {:?} should contain test patterns",
185                    lang
186                );
187            }
188        }
189    }
190
191    // ========================================================================
192    // Manifest Query Tests
193    // ========================================================================
194
195    #[test]
196    fn test_manifest_queries_exist() {
197        for lang in supported_manifest_languages() {
198            let query = get_manifest_query(*lang);
199            assert!(!query.is_empty(), "Manifest query empty for {:?}", lang);
200        }
201    }
202
203    #[test]
204    fn test_manifest_queries_contain_component_patterns() {
205        // All manifest queries should contain component name patterns
206        for lang in supported_manifest_languages() {
207            let query = get_manifest_query(*lang);
208            assert!(
209                query.contains("manifest.component") || query.contains("@manifest"),
210                "Manifest query for {:?} should contain manifest.component patterns",
211                lang
212            );
213        }
214    }
215
216    #[test]
217    fn test_manifest_queries_contain_dependency_patterns() {
218        // All manifest queries should contain dependency patterns
219        for lang in supported_manifest_languages() {
220            let query = get_manifest_query(*lang);
221            assert!(
222                query.contains("manifest.dependency"),
223                "Manifest query for {:?} should contain manifest.dependency patterns",
224                lang
225            );
226        }
227    }
228
229    #[test]
230    fn test_has_manifest_query() {
231        for lang in supported_manifest_languages() {
232            assert!(
233                has_manifest_query(*lang),
234                "Should have manifest query for {:?}",
235                lang
236            );
237        }
238    }
239
240    #[test]
241    fn test_json_manifest_query_patterns() {
242        let query = get_manifest_query(ManifestLanguage::Json);
243        assert!(
244            query.contains("package.json")
245                || query.contains("vcpkg.json")
246                || query.contains("JSON")
247        );
248        assert!(query.contains("dependencies"));
249        assert!(query.contains("workspace"));
250    }
251
252    #[test]
253    fn test_toml_manifest_query_patterns() {
254        let query = get_manifest_query(ManifestLanguage::Toml);
255        assert!(
256            query.contains("Cargo.toml")
257                || query.contains("pyproject.toml")
258                || query.contains("TOML")
259        );
260        assert!(query.contains("[package]") || query.contains("package"));
261        assert!(query.contains("dependencies"));
262    }
263
264    #[test]
265    fn test_gomod_manifest_query_patterns() {
266        let query = get_manifest_query(ManifestLanguage::GoMod);
267        assert!(query.contains("go.mod") || query.contains("Go Module"));
268        assert!(query.contains("module_directive") || query.contains("module_path"));
269        assert!(query.contains("replace"));
270    }
271
272    #[test]
273    fn test_xml_manifest_query_patterns() {
274        let query = get_manifest_query(ManifestLanguage::Xml);
275        assert!(query.contains(".csproj") || query.contains("XML") || query.contains("MSBuild"));
276        assert!(query.contains("AssemblyName") || query.contains("assembly"));
277        assert!(query.contains("ProjectReference"));
278    }
279
280    #[test]
281    fn test_cmake_manifest_query_patterns() {
282        let query = get_manifest_query(ManifestLanguage::CMake);
283        assert!(query.contains("CMakeLists.txt") || query.contains("CMake"));
284        assert!(query.contains("project"));
285        assert!(query.contains("add_subdirectory"));
286    }
287
288    // ========================================================================
289    // Manifest Query Compilation Tests
290    // ========================================================================
291
292    use tree_sitter::Query;
293
294    #[test]
295    fn test_manifest_queries_compile_json() {
296        let query_src = get_manifest_query(ManifestLanguage::Json);
297        let lang = ManifestLanguage::Json.tree_sitter_language();
298        let result = Query::new(&lang, query_src);
299        assert!(
300            result.is_ok(),
301            "JSON manifest query failed to compile: {:?}",
302            result.err()
303        );
304    }
305
306    #[test]
307    fn test_manifest_queries_compile_toml() {
308        let query_src = get_manifest_query(ManifestLanguage::Toml);
309        let lang = ManifestLanguage::Toml.tree_sitter_language();
310        let result = Query::new(&lang, query_src);
311        assert!(
312            result.is_ok(),
313            "TOML manifest query failed to compile: {:?}",
314            result.err()
315        );
316    }
317
318    #[test]
319    fn test_manifest_queries_compile_gomod() {
320        let query_src = get_manifest_query(ManifestLanguage::GoMod);
321        let lang = ManifestLanguage::GoMod.tree_sitter_language();
322        let result = Query::new(&lang, query_src);
323        assert!(
324            result.is_ok(),
325            "GoMod manifest query failed to compile: {:?}",
326            result.err()
327        );
328    }
329
330    #[test]
331    fn test_manifest_queries_compile_xml() {
332        let query_src = get_manifest_query(ManifestLanguage::Xml);
333        let lang = ManifestLanguage::Xml.tree_sitter_language();
334        let result = Query::new(&lang, query_src);
335        assert!(
336            result.is_ok(),
337            "XML manifest query failed to compile: {:?}",
338            result.err()
339        );
340    }
341
342    #[test]
343    fn test_manifest_queries_compile_cmake() {
344        let query_src = get_manifest_query(ManifestLanguage::CMake);
345        let lang = ManifestLanguage::CMake.tree_sitter_language();
346        let result = Query::new(&lang, query_src);
347        assert!(
348            result.is_ok(),
349            "CMake manifest query failed to compile: {:?}",
350            result.err()
351        );
352    }
353}