package_parser/helper/
mod.rs1use std::path::Path;
2
3use ignore::{types::Types, DirEntry, Walk, WalkBuilder};
4use tree_sitter::{Node, Query, QueryCapture, QueryCursor};
5
6pub fn query_matches<'tree>(
7 node: Node<'tree>,
8 query: &Query,
9 code_raw: &[u8],
10) -> Vec<Vec<QueryCapture<'tree>>> {
11 let mut cursor = QueryCursor::new();
12
13 let mut ret = vec![];
14 for m in cursor.matches(query, node, code_raw) {
15 ret.push(m.captures.to_vec())
16 }
17 ret
18}
19
20pub fn build_walker<P: AsRef<Path>>(path: P, types: &[&str]) -> (Walk, Types) {
21 let mut types_builder = ignore::types::TypesBuilder::new();
22 types_builder.add_defaults();
23 for ty in types {
24 types_builder.select(ty);
25 }
26 let matcher = types_builder.build().unwrap();
27
28 (
29 WalkBuilder::new(path)
30 .git_global(false)
31 .parents(false)
32 .types(matcher.clone())
33 .build(),
34 matcher,
35 )
36}
37
38pub fn match_ftyp(entry: &DirEntry, matcher: &Types) -> Option<String> {
39 let file_type = entry.file_type()?;
40
41 if file_type.is_dir() {
42 return None;
43 }
44
45 if let ignore::Match::Whitelist(x) = matcher.matched(entry.path(), false) {
46 x.file_type_def().map(|def| def.name().to_owned())
47 } else {
48 None
49 }
50}
51
52#[cfg(test)]
53pub mod testing {
54 use ignore::WalkBuilder;
55 use std::path::{Path, PathBuf};
56
57 pub fn all_files_with_extensions<'a>(
59 dir: &Path,
60 extensions: &'a [&'a str],
61 ) -> impl Iterator<Item = Result<PathBuf, ignore::Error>> + 'a {
62 WalkBuilder::new(dir)
63 .build()
64 .filter_map(|result| match result {
65 Ok(entry) => {
66 if entry.file_type().unwrap().is_file() {
67 let path = entry.path();
68
69 if let Some(ext) = path.extension() {
70 if extensions.contains(&ext.to_str().unwrap()) {
71 Some(Ok(path.to_path_buf()))
72 } else {
73 None
74 }
75 } else {
76 None
77 }
78 } else {
79 None
80 }
81 }
82 Err(e) => Some(Err(e)),
83 })
84 }
85}