1use crate::facts::{
11 Declaration, DeclarationKind, Facts, Import, ImportBinding, Reference, ReferenceKind, Span,
12};
13use crate::syntax::Language;
14use crate::token::{Mode, Token, TokenKind, Tokenizer};
15
16#[must_use]
18pub fn extract(source: &str, language: Language) -> Facts {
19 let tokens = Tokenizer::new(source, language)
20 .mode(Mode::Lite)
21 .collect::<Vec<_>>();
22 let mut state = Extractor {
23 source,
24 tokens: &tokens,
25 language,
26 rules: Rules::of(language),
27 facts: Facts::default(),
28 scopes: Vec::new(),
29 depth: 0,
30 };
31 state.run();
32 state.facts
33}
34
35struct Rules {
37 declarations: &'static [(&'static str, DeclarationKind)],
39 imports: &'static [&'static str],
41 modifiers: &'static [&'static str],
43 braced_members: bool,
45 grouped_declarations: bool,
48 typed_functions: bool,
51 exported_keyword: Option<&'static str>,
53 scope_keywords: &'static [&'static str],
57}
58
59impl Rules {
60 const fn of(language: Language) -> Self {
61 match language {
62 Language::Rust => Self::rust(),
63 Language::Swift => Self::swift(),
64 Language::Go => Self::go(),
65 Language::Java | Language::CSharp => Self::managed(),
66 Language::Solidity => Self::solidity(),
67 _ => Self::c_family(),
68 }
69 }
70
71 const fn rust() -> Self {
72 Self {
73 declarations: &[
74 ("fn", DeclarationKind::Function),
75 ("struct", DeclarationKind::Struct),
76 ("enum", DeclarationKind::Enum),
77 ("trait", DeclarationKind::Trait),
78 ("type", DeclarationKind::TypeAlias),
79 ("const", DeclarationKind::Constant),
80 ("static", DeclarationKind::Constant),
81 ("mod", DeclarationKind::Module),
82 ],
83 imports: &["use", "mod"],
84 modifiers: &["pub", "async", "unsafe", "extern", "default"],
85 braced_members: false,
86 grouped_declarations: false,
87 typed_functions: false,
88 exported_keyword: Some("pub"),
89 scope_keywords: &["impl"],
90 }
91 }
92
93 const fn swift() -> Self {
94 Self {
95 declarations: &[
96 ("func", DeclarationKind::Function),
97 ("class", DeclarationKind::Class),
98 ("struct", DeclarationKind::Struct),
99 ("actor", DeclarationKind::Class),
100 ("enum", DeclarationKind::Enum),
101 ("protocol", DeclarationKind::Interface),
102 ("typealias", DeclarationKind::TypeAlias),
103 ("associatedtype", DeclarationKind::TypeAlias),
104 ("let", DeclarationKind::Constant),
105 ("var", DeclarationKind::Variable),
106 ("init", DeclarationKind::Method),
107 ("subscript", DeclarationKind::Method),
108 ],
109 imports: &["import"],
110 modifiers: &[
111 "public",
112 "private",
113 "internal",
114 "fileprivate",
115 "open",
116 "static",
117 "final",
118 "override",
119 "mutating",
120 "nonmutating",
121 "lazy",
122 "weak",
123 "unowned",
124 "required",
125 "convenience",
126 "indirect",
127 "dynamic",
128 "optional",
129 "async",
130 "throws",
131 ],
132 braced_members: false,
133 grouped_declarations: false,
134 typed_functions: false,
135 exported_keyword: Some("public"),
137 scope_keywords: &["extension"],
138 }
139 }
140
141 const fn go() -> Self {
142 Self {
143 declarations: &[
144 ("func", DeclarationKind::Function),
145 ("type", DeclarationKind::Struct),
146 ("const", DeclarationKind::Constant),
147 ("var", DeclarationKind::Variable),
148 ],
149 imports: &["import"],
150 modifiers: &[],
151 braced_members: false,
152 grouped_declarations: true,
153 typed_functions: false,
154 exported_keyword: None,
155 scope_keywords: &[],
156 }
157 }
158
159 const fn managed() -> Self {
160 Self {
161 declarations: &[
162 ("class", DeclarationKind::Class),
163 ("interface", DeclarationKind::Interface),
164 ("enum", DeclarationKind::Enum),
165 ("record", DeclarationKind::Struct),
166 ("struct", DeclarationKind::Struct),
167 ],
168 imports: &["import", "using"],
169 modifiers: &[
170 "public",
171 "private",
172 "protected",
173 "static",
174 "final",
175 "abstract",
176 "sealed",
177 "internal",
178 "override",
179 "async",
180 "virtual",
181 "readonly",
182 ],
183 braced_members: true,
184 grouped_declarations: false,
185 typed_functions: false,
186 exported_keyword: Some("public"),
187 scope_keywords: &[],
188 }
189 }
190
191 const fn solidity() -> Self {
192 Self {
193 declarations: &[
194 ("contract", DeclarationKind::Class),
195 ("library", DeclarationKind::Class),
196 ("interface", DeclarationKind::Interface),
197 ("struct", DeclarationKind::Struct),
198 ("enum", DeclarationKind::Enum),
199 ("function", DeclarationKind::Function),
200 ("constructor", DeclarationKind::Method),
201 ("modifier", DeclarationKind::Function),
202 ("event", DeclarationKind::Field),
203 ("error", DeclarationKind::Struct),
204 ],
205 imports: &["import"],
206 modifiers: &[
207 "abstract", "virtual", "override", "public", "private", "internal", "external",
208 "pure", "view", "payable",
209 ],
210 braced_members: false,
211 grouped_declarations: false,
212 typed_functions: false,
213 exported_keyword: Some("public"),
215 scope_keywords: &[],
216 }
217 }
218
219 const fn c_family() -> Self {
220 Self {
221 declarations: &[
222 ("struct", DeclarationKind::Struct),
223 ("class", DeclarationKind::Class),
224 ("enum", DeclarationKind::Enum),
225 ("namespace", DeclarationKind::Module),
226 ],
227 imports: &["#include", "include"],
228 modifiers: &["static", "inline", "extern", "const", "virtual"],
229 braced_members: true,
230 grouped_declarations: false,
231 typed_functions: true,
232 exported_keyword: None,
233 scope_keywords: &[],
234 }
235 }
236}
237
238struct Scope {
239 name: String,
240 depth: Option<i32>,
241 declaration: Option<usize>,
242 type_body: bool,
243 test_only: bool,
244}
245
246struct Extractor<'source, 'tokens> {
247 source: &'source str,
248 tokens: &'tokens [Token],
249 language: Language,
250 rules: Rules,
251 facts: Facts,
252 scopes: Vec<Scope>,
253 depth: i32,
254}
255
256mod calls;
257mod declarations;
258mod fields;
259mod imports;
260mod scopes;
261mod traversal;
262
263#[cfg(test)]
264mod tests;