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 type_body: bool,
242 test_only: bool,
243}
244
245struct Extractor<'source, 'tokens> {
246 source: &'source str,
247 tokens: &'tokens [Token],
248 language: Language,
249 rules: Rules,
250 facts: Facts,
251 scopes: Vec<Scope>,
252 depth: i32,
253}
254
255mod calls;
256mod declarations;
257mod fields;
258mod imports;
259mod scopes;
260mod traversal;
261
262#[cfg(test)]
263mod tests;