weavatrix_parse/shell/
mod.rs1use crate::facts::{Declaration, DeclarationKind, Facts, Import, Reference, ReferenceKind, Span};
14use crate::syntax::Language;
15use crate::token::{Mode, Token, TokenKind, Tokenizer};
16
17#[must_use]
19pub fn extract(source: &str) -> Facts {
20 let tokens = Tokenizer::new(source, Language::Bash)
21 .mode(Mode::Lite)
22 .collect::<Vec<_>>();
23 let mut state = Extractor {
24 source,
25 tokens: &tokens,
26 facts: Facts::default(),
27 function: None,
28 depth: 0,
29 };
30 state.run();
31 state.facts
32}
33
34const CLIENTS: &[&str] = &[
36 "curl", "wget", "http", "https", "xh", "httpie", "nc", "ncat", "grpcurl", "ab", "hey", "siege",
37 "wrk",
38];
39
40const RUNNERS: &[&str] = &["source", ".", "bash", "sh", "zsh", "ksh"];
42
43const KEYWORDS: &[&str] = &[
45 "then", "do", "else", "elif", "fi", "done", "if", "while", "until", "for", "case", "esac",
46 "in", "function", "return", "local", "export", "declare", "readonly", "eval", "exec", "time",
47];
48
49struct Extractor<'source, 'tokens> {
50 source: &'source str,
51 tokens: &'tokens [Token],
52 facts: Facts,
53 function: Option<(String, i32)>,
55 depth: i32,
56}
57
58fn endpoints(arguments: &[String]) -> Vec<String> {
64 let mut found = Vec::new();
65 let mut expecting_method = false;
66 for argument in arguments {
67 if expecting_method {
68 found.push(argument.clone());
69 expecting_method = false;
70 continue;
71 }
72 if argument == "-X" || argument == "--request" {
73 expecting_method = true;
74 continue;
75 }
76 if argument.contains("://") || argument.starts_with("localhost:") {
77 found.push(argument.clone());
78 }
79 }
80 found
81}
82
83mod extractor;
84
85#[cfg(test)]
86mod tests;