Skip to content

Commit fde5dea

Browse files
committed
Rust: extract ValueItems
1 parent ece3ec0 commit fde5dea

File tree

1 file changed

+312
-3
lines changed

1 file changed

+312
-3
lines changed

rust/extractor/src/main.rs

Lines changed: 312 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,8 @@ use itertools::Itertools;
77
use log::{info, warn};
88
use ra_ap_base_db::{CrateId, SourceDatabase};
99
use ra_ap_cfg::CfgAtom;
10-
use ra_ap_hir::db::DefDatabase;
11-
use ra_ap_hir::{DefMap, Semantics};
10+
use ra_ap_hir::db::{DefDatabase, HirDatabase};
11+
use ra_ap_hir::{DefMap, ModPath, ModuleDefId, Semantics, TypeRef, Variant};
1212
use ra_ap_hir_def::LocalModuleId;
1313
use ra_ap_ide_db::line_index::{LineCol, LineIndex};
1414
use ra_ap_ide_db::RootDatabase;
@@ -39,6 +39,203 @@ struct Extractor<'a> {
3939
steps: Vec<ExtractionStep>,
4040
}
4141

42+
fn emit_hir_path(
43+
trap: &mut TrapFile,
44+
path: &ra_ap_hir_def::path::Path,
45+
) -> trap::Label<generated::Path> {
46+
let part = path.segments().last().map(|segment| {
47+
let name_ref = trap.emit(generated::NameRef {
48+
id: trap::TrapId::Star,
49+
text: Some(segment.name.as_str().to_owned()),
50+
});
51+
trap.emit(generated::PathSegment {
52+
id: trap::TrapId::Star,
53+
generic_arg_list: None,
54+
name_ref: Some(name_ref),
55+
param_list: None,
56+
path_type: None,
57+
ret_type: None,
58+
return_type_syntax: None,
59+
type_repr: None,
60+
})
61+
});
62+
let qualifier = path
63+
.mod_path()
64+
.filter(|p| !p.segments().is_empty())
65+
.and_then(|_| path.qualifier().as_ref().map(|p| emit_hir_path(trap, p)));
66+
trap.emit(generated::Path {
67+
id: trap::TrapId::Star,
68+
qualifier,
69+
part,
70+
})
71+
}
72+
fn emit_hir_fn(
73+
trap: &mut TrapFile,
74+
self_type: Option<&TypeRef>,
75+
params: &[&TypeRef],
76+
ret_type: &TypeRef,
77+
is_async: bool,
78+
is_const: bool,
79+
is_unsafe: bool,
80+
) -> trap::Label<generated::FnPtrTypeRepr> {
81+
let ret = emit_hir_typeref(trap, ret_type);
82+
83+
let ret = trap.emit(generated::RetTypeRepr {
84+
id: trap::TrapId::Star,
85+
type_repr: ret,
86+
});
87+
let self_param = self_type.map(|ty| {
88+
let type_repr = emit_hir_typeref(trap, ty);
89+
trap.emit(generated::SelfParam {
90+
id: trap::TrapId::Star,
91+
attrs: vec![],
92+
type_repr,
93+
is_mut: false,
94+
lifetime: None,
95+
name: None,
96+
})
97+
});
98+
let params = params
99+
.iter()
100+
.map(|t| {
101+
let type_repr = emit_hir_typeref(trap, t);
102+
trap.emit(generated::Param {
103+
id: trap::TrapId::Star,
104+
attrs: vec![],
105+
type_repr,
106+
pat: None,
107+
})
108+
})
109+
.collect();
110+
let params = trap.emit(generated::ParamList {
111+
id: trap::TrapId::Star,
112+
params,
113+
self_param,
114+
});
115+
trap.emit(generated::FnPtrTypeRepr {
116+
id: trap::TrapId::Star,
117+
abi: None,
118+
is_async,
119+
is_const,
120+
is_unsafe,
121+
param_list: Some(params),
122+
ret_type: Some(ret),
123+
})
124+
}
125+
fn emit_hir_typeref(trap: &mut TrapFile, ty: &TypeRef) -> Option<trap::Label<generated::TypeRepr>> {
126+
match ty {
127+
TypeRef::Never => Some(
128+
trap.emit(generated::NeverTypeRepr {
129+
id: trap::TrapId::Star,
130+
})
131+
.into(),
132+
),
133+
TypeRef::Placeholder => Some(
134+
trap.emit(generated::InferTypeRepr {
135+
id: trap::TrapId::Star,
136+
})
137+
.into(),
138+
),
139+
TypeRef::Tuple(fields) => {
140+
let fields = fields
141+
.iter()
142+
.flat_map(|field| emit_hir_typeref(trap, field))
143+
.collect();
144+
Some(
145+
trap.emit(generated::TupleTypeRepr {
146+
id: trap::TrapId::Star,
147+
fields,
148+
})
149+
.into(),
150+
)
151+
}
152+
TypeRef::RawPtr(type_ref, mutability) => {
153+
let type_repr = emit_hir_typeref(trap, type_ref);
154+
Some(
155+
trap.emit(generated::PtrTypeRepr {
156+
id: trap::TrapId::Star,
157+
is_const: mutability.is_shared(),
158+
is_mut: mutability.is_mut(),
159+
type_repr,
160+
})
161+
.into(),
162+
)
163+
}
164+
TypeRef::Reference(type_ref, lifetime_ref, mutability) => {
165+
let type_repr = emit_hir_typeref(trap, type_ref);
166+
let lifetime = lifetime_ref.as_ref().map(|x| {
167+
trap.emit(generated::Lifetime {
168+
id: trap::TrapId::Star,
169+
text: Some(x.name.as_str().to_owned()),
170+
})
171+
});
172+
Some(
173+
trap.emit(generated::RefTypeRepr {
174+
id: trap::TrapId::Star,
175+
is_mut: mutability.is_mut(),
176+
type_repr,
177+
lifetime,
178+
})
179+
.into(),
180+
)
181+
}
182+
TypeRef::Array(type_ref, _const_ref) => {
183+
let element_type_repr = emit_hir_typeref(trap, type_ref);
184+
// TODO: handle array size constant
185+
let const_arg = None;
186+
Some(
187+
trap.emit(generated::ArrayTypeRepr {
188+
id: trap::TrapId::Star,
189+
element_type_repr,
190+
const_arg,
191+
})
192+
.into(),
193+
)
194+
}
195+
TypeRef::Slice(type_ref) => {
196+
let type_repr = emit_hir_typeref(trap, type_ref);
197+
Some(
198+
trap.emit(generated::SliceTypeRepr {
199+
id: trap::TrapId::Star,
200+
type_repr,
201+
})
202+
.into(),
203+
)
204+
}
205+
TypeRef::Fn(params, _, is_unsafe, _symbol) => {
206+
let (ret_type, params) = params.split_last().unwrap();
207+
let params: Vec<_> = params.as_ref().iter().map(|x| &x.1).collect();
208+
Some(
209+
emit_hir_fn(
210+
trap,
211+
None,
212+
&params[..],
213+
&ret_type.1,
214+
false,
215+
false,
216+
*is_unsafe,
217+
)
218+
.into(),
219+
)
220+
}
221+
TypeRef::Path(path) => {
222+
let path = Some(emit_hir_path(trap, path));
223+
224+
Some(
225+
trap.emit(generated::PathTypeRepr {
226+
id: trap::TrapId::Star,
227+
path,
228+
})
229+
.into(),
230+
)
231+
}
232+
TypeRef::ImplTrait(_) => None, // TODO handle impl
233+
TypeRef::DynTrait(_) => None, // TODO handle dyn
234+
TypeRef::Macro(_) => None,
235+
TypeRef::Error => None,
236+
}
237+
}
238+
42239
impl<'a> Extractor<'a> {
43240
pub fn new(archiver: &'a Archiver, traps: &'a trap::TrapFileProvider) -> Self {
44241
Self {
@@ -237,18 +434,130 @@ impl<'a> Extractor<'a> {
237434
trap.commit();
238435

239436
fn go(
240-
db: &dyn DefDatabase,
437+
db: &dyn HirDatabase,
241438
map: &DefMap,
242439
parent: trap::Label<generated::ModuleContainer>,
243440
name: &str,
244441
module: LocalModuleId,
245442
trap: &mut TrapFile,
246443
) {
247444
let module = &map.modules[module];
445+
let items = &module.scope;
446+
let mut values = Vec::new();
447+
448+
for (name, item) in items.entries() {
449+
let def = item.with_visibility(ra_ap_hir::Visibility::Public);
450+
if let Some((value, _, _import)) = def.values {
451+
match value {
452+
ModuleDefId::FunctionId(function) => {
453+
let function = db.function_data(function);
454+
let params: Vec<_> =
455+
function.params.iter().map(|x| x.as_ref()).collect();
456+
let (self_type, params) = if function.has_self_param() {
457+
(Some(params[0]), &params[1..])
458+
} else {
459+
(None, &params[..])
460+
};
461+
let ret_type = function.ret_type.as_ref();
462+
let type_ = emit_hir_fn(
463+
trap,
464+
self_type,
465+
params,
466+
ret_type,
467+
function.is_async(),
468+
function.is_const(),
469+
function.is_unsafe(),
470+
)
471+
.into();
472+
473+
values.push(trap.emit(generated::ValueItem {
474+
id: trap::TrapId::Star,
475+
name: name.as_str().to_owned(),
476+
type_,
477+
}));
478+
}
479+
ModuleDefId::ConstId(konst) => {
480+
let konst = db.const_data(konst);
481+
if let Some(type_) = emit_hir_typeref(trap, &konst.type_ref) {
482+
values.push(trap.emit(generated::ValueItem {
483+
id: trap::TrapId::Star,
484+
name: name.as_str().to_owned(),
485+
type_,
486+
}));
487+
}
488+
}
489+
ModuleDefId::StaticId(statik) => {
490+
let statik = db.static_data(statik);
491+
if let Some(type_) = emit_hir_typeref(trap, &statik.type_ref) {
492+
values.push(trap.emit(generated::ValueItem {
493+
id: trap::TrapId::Star,
494+
name: name.as_str().to_owned(),
495+
type_,
496+
}));
497+
}
498+
}
499+
ModuleDefId::EnumVariantId(variant_id) => {
500+
let variant: Variant = variant_id.into();
501+
let tp = variant.parent_enum(db);
502+
let mut mod_path = ModPath::from_kind(ra_ap_hir::PathKind::Abs);
503+
504+
mod_path.extend(
505+
tp.module(db)
506+
.path_to_root(db)
507+
.iter()
508+
.flat_map(|x| x.name(db)),
509+
);
510+
mod_path.push_segment(tp.name(db));
511+
let ret_type = TypeRef::Path(
512+
ra_ap_hir_def::path::Path::from_known_path_with_no_generic(
513+
mod_path,
514+
),
515+
);
516+
//
517+
let variant_data = db.enum_variant_data(variant_id);
518+
let type_ = match variant_data.variant_data.as_ref() {
519+
ra_ap_hir_def::data::adt::VariantData::Unit => {
520+
emit_hir_typeref(trap, &ret_type)
521+
}
522+
ra_ap_hir_def::data::adt::VariantData::Tuple(arena) => {
523+
let params: Vec<_> =
524+
arena.values().map(|f| f.type_ref.as_ref()).collect();
525+
Some(
526+
emit_hir_fn(
527+
trap,
528+
None,
529+
&params[..],
530+
&ret_type,
531+
false,
532+
false,
533+
false,
534+
)
535+
.into(),
536+
)
537+
}
538+
ra_ap_hir_def::data::adt::VariantData::Record(_) => {
539+
// record enums are not "values"
540+
None
541+
}
542+
};
543+
if let Some(type_) = type_ {
544+
values.push(trap.emit(generated::ValueItem {
545+
id: trap::TrapId::Star,
546+
name: name.as_str().to_owned(),
547+
type_,
548+
}));
549+
}
550+
}
551+
_ => (),
552+
}
553+
}
554+
if let Some((_type_id, _, _import)) = def.types {}
555+
}
248556
let label = trap.emit(generated::CrateModule {
249557
id: trap::TrapId::Star,
250558
name: name.to_owned(),
251559
parent,
560+
values,
252561
});
253562
for (name, child) in module
254563
.children

0 commit comments

Comments
 (0)