Skip to content

Commit 86e83b1

Browse files
committed
Rust: crate graph: generic parameters
1 parent 0a97476 commit 86e83b1

File tree

4 files changed

+160
-24
lines changed

4 files changed

+160
-24
lines changed

rust/extractor/src/crate_graph.rs

Lines changed: 119 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -11,19 +11,20 @@ use ra_ap_base_db::{Crate, RootQueryDb};
1111
use ra_ap_cfg::CfgAtom;
1212
use ra_ap_hir::{DefMap, ModuleDefId, PathKind, db::HirDatabase};
1313
use ra_ap_hir::{VariantId, Visibility, db::DefDatabase};
14-
use ra_ap_hir_def::Lookup;
1514
use ra_ap_hir_def::{
16-
AssocItemId, LocalModuleId, data::adt::VariantData, item_scope::ImportOrGlob,
17-
item_tree::ImportKind, nameres::ModuleData, path::ImportAlias,
15+
AssocItemId, ConstParamId, LocalModuleId, TypeOrConstParamId, data::adt::VariantData,
16+
generics::TypeOrConstParamData, item_scope::ImportOrGlob, item_tree::ImportKind,
17+
nameres::ModuleData, path::ImportAlias,
1818
};
19+
use ra_ap_hir_def::{GenericDefId, Lookup};
1920
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2021
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
21-
use ra_ap_hir_ty::TraitRefExt;
2222
use ra_ap_hir_ty::TyExt;
2323
use ra_ap_hir_ty::WhereClause;
2424
use ra_ap_hir_ty::{Binders, FnPointer};
2525
use ra_ap_hir_ty::{GenericArg, Ty};
2626
use ra_ap_hir_ty::{Interner, ProjectionTy};
27+
use ra_ap_hir_ty::{TraitRefExt, TyLoweringContext};
2728
use ra_ap_ide_db::RootDatabase;
2829
use ra_ap_vfs::{Vfs, VfsPath};
2930
use std::hash::Hasher;
@@ -428,7 +429,98 @@ fn emit_enum_variant(
428429
}
429430
items
430431
}
432+
fn emit_generic_param_list(
433+
trap: &mut TrapFile,
434+
db: &dyn HirDatabase,
435+
def: GenericDefId,
436+
) -> Option<trap::Label<generated::GenericParamList>> {
437+
let params = db.generic_params(def);
438+
let trait_self_param = params.trait_self_param();
439+
if params.is_empty() || params.len() == 1 && trait_self_param.is_some() {
440+
return None;
441+
}
442+
let mut generic_params = Vec::new();
443+
generic_params.extend(params.iter_lt().map(
444+
|(_, param)| -> trap::Label<generated::GenericParam> {
445+
let lifetime = trap
446+
.emit(generated::Lifetime {
447+
id: trap::TrapId::Star,
448+
text: Some(param.name.as_str().to_owned()),
449+
})
450+
.into();
431451

452+
trap.emit(generated::LifetimeParam {
453+
id: trap::TrapId::Star,
454+
attrs: vec![],
455+
lifetime,
456+
type_bound_list: None,
457+
})
458+
.into()
459+
},
460+
));
461+
generic_params.extend(
462+
params
463+
.iter_type_or_consts()
464+
.filter(|(id, _)| trait_self_param != Some(*id))
465+
.map(
466+
|(param_id, param)| -> trap::Label<generated::GenericParam> {
467+
match param {
468+
TypeOrConstParamData::TypeParamData(param) => {
469+
let name = Some(trap.emit(generated::Name {
470+
id: trap::TrapId::Star,
471+
text: param.name.as_ref().map(|name| name.as_str().to_owned()),
472+
}));
473+
let resolver = def.resolver(db.upcast());
474+
let mut ctx = TyLoweringContext::new(
475+
db,
476+
&resolver,
477+
&params.types_map,
478+
def.into(),
479+
);
480+
481+
let default_type = param
482+
.default
483+
.and_then(|ty| emit_hir_ty(trap, db, &ctx.lower_ty(ty)));
484+
trap.emit(generated::TypeParam {
485+
id: trap::TrapId::Star,
486+
attrs: vec![],
487+
name,
488+
default_type,
489+
type_bound_list: None,
490+
})
491+
.into()
492+
}
493+
TypeOrConstParamData::ConstParamData(param) => {
494+
let name = Some(trap.emit(generated::Name {
495+
id: trap::TrapId::Star,
496+
text: param.name.as_str().to_owned().into(),
497+
}));
498+
let param_id = TypeOrConstParamId {
499+
parent: def,
500+
local_id: param_id,
501+
};
502+
let ty = db.const_param_ty(ConstParamId::from_unchecked(param_id));
503+
let type_repr = emit_hir_ty(trap, db, &ty);
504+
trap.emit(generated::ConstParam {
505+
id: trap::TrapId::Star,
506+
attrs: vec![],
507+
name,
508+
default_val: None,
509+
is_const: true,
510+
type_repr,
511+
})
512+
.into()
513+
}
514+
}
515+
},
516+
),
517+
);
518+
trap.emit(generated::GenericParamList {
519+
id: trap::TrapId::Star,
520+
generic_params,
521+
})
522+
.into()
523+
}
432524
fn emit_adt(
433525
db: &dyn HirDatabase,
434526
name: &str,
@@ -437,6 +529,7 @@ fn emit_adt(
437529
visibility: Visibility,
438530
) -> Vec<trap::Label<generated::Item>> {
439531
let mut items = Vec::new();
532+
440533
match adt_id {
441534
ra_ap_hir_def::AdtId::StructId(struct_id) => {
442535
let name = Some(trap.emit(generated::Name {
@@ -445,13 +538,14 @@ fn emit_adt(
445538
}));
446539
let field_list = emit_variant_data(trap, db, struct_id.into()).into();
447540
let visibility = emit_visibility(db, trap, visibility);
541+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
448542
items.push(
449543
trap.emit(generated::Struct {
450544
id: trap::TrapId::Star,
451545
name,
452546
attrs: vec![],
453547
field_list,
454-
generic_param_list: None,
548+
generic_param_list,
455549
visibility,
456550
where_clause: None,
457551
})
@@ -489,12 +583,13 @@ fn emit_adt(
489583
text: Some(name.to_owned()),
490584
}));
491585
let visibility = emit_visibility(db, trap, visibility);
586+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
492587
items.push(
493588
trap.emit(generated::Enum {
494589
id: trap::TrapId::Star,
495590
name,
496591
attrs: vec![],
497-
generic_param_list: None,
592+
generic_param_list,
498593
variant_list,
499594
visibility,
500595
where_clause: None,
@@ -509,13 +604,14 @@ fn emit_adt(
509604
}));
510605
let struct_field_list = emit_variant_data(trap, db, union_id.into()).into();
511606
let visibility = emit_visibility(db, trap, visibility);
607+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
512608
items.push(
513609
trap.emit(generated::Union {
514610
id: trap::TrapId::Star,
515611
name,
516612
attrs: vec![],
517613
struct_field_list,
518-
generic_param_list: None,
614+
generic_param_list,
519615
visibility,
520616
where_clause: None,
521617
})
@@ -534,8 +630,8 @@ fn emit_trait(
534630
visibility: Visibility,
535631
) -> Vec<trap::Label<generated::Item>> {
536632
let mut items = Vec::new();
537-
let data = db.trait_items(trait_id);
538-
let assoc_items: Vec<trap::Label<generated::AssocItem>> = data
633+
let trait_items = db.trait_items(trait_id);
634+
let assoc_items: Vec<trap::Label<generated::AssocItem>> = trait_items
539635
.items
540636
.iter()
541637
.flat_map(|(name, item)| {
@@ -573,6 +669,7 @@ fn emit_trait(
573669
text: Some(name.as_str().to_owned()),
574670
}));
575671
let visibility = emit_visibility(db, trap, visibility);
672+
let generic_param_list = emit_generic_param_list(trap, db, (*function).into());
576673
Some(
577674
trap.emit(generated::Function {
578675
id: trap::TrapId::Star,
@@ -586,7 +683,7 @@ fn emit_trait(
586683
is_async: false,
587684
is_gen: false,
588685
is_unsafe: matches!(sig.to_fn_ptr().sig.safety, Safety::Unsafe),
589-
generic_param_list: None, //TODO
686+
generic_param_list,
590687
param_list: Some(param_list),
591688
ret_type,
592689
where_clause: None,
@@ -608,13 +705,14 @@ fn emit_trait(
608705
text: Some(name.to_owned()),
609706
}));
610707
let visibility = emit_visibility(db, trap, visibility);
708+
let generic_param_list = emit_generic_param_list(trap, db, trait_id.into());
611709
items.push(
612710
trap.emit(generated::Trait {
613711
id: trap::TrapId::Star,
614712
name,
615713
assoc_item_list,
616714
attrs: vec![],
617-
generic_param_list: None,
715+
generic_param_list,
618716
is_auto: false,
619717
is_unsafe: false,
620718
type_bound_list: None,
@@ -690,7 +788,7 @@ fn emit_module_impls(
690788
data.visibility
691789
.resolve(db.upcast(), &function.resolver(db.upcast())),
692790
);
693-
791+
let generic_param_list = emit_generic_param_list(trap, db, (*function).into());
694792
Some(
695793
trap.emit(generated::Function {
696794
id: trap::TrapId::Star,
@@ -704,7 +802,7 @@ fn emit_module_impls(
704802
is_async: false,
705803
is_gen: false,
706804
is_unsafe: matches!(sig.to_fn_ptr().sig.safety, Safety::Unsafe),
707-
generic_param_list: None, //TODO
805+
generic_param_list,
708806
param_list: Some(param_list),
709807
ret_type,
710808
where_clause: None,
@@ -721,14 +819,15 @@ fn emit_module_impls(
721819
assoc_items,
722820
attrs: vec![],
723821
}));
822+
let generic_param_list = emit_generic_param_list(trap, db, imp.into());
724823
items.push(
725824
trap.emit(generated::Impl {
726825
id: trap::TrapId::Star,
727826
trait_,
728827
self_ty,
729828
assoc_item_list,
730829
attrs: vec![],
731-
generic_param_list: None,
830+
generic_param_list,
732831
is_const: false,
733832
is_default: false,
734833
is_unsafe: false,
@@ -772,7 +871,6 @@ fn const_or_function(
772871
match type_.kind(ra_ap_hir_ty::Interner) {
773872
chalk_ir::TyKind::FnDef(fn_def_id, parameters) => {
774873
let data = db.fn_def_datum(*fn_def_id);
775-
776874
let sig = ra_ap_hir_ty::CallableSig::from_def(db, *fn_def_id, parameters);
777875
let params = sig
778876
.params()
@@ -805,6 +903,11 @@ fn const_or_function(
805903
text: Some(name.to_owned()),
806904
}));
807905
let visibility = emit_visibility(db, trap, visibility);
906+
let callable_def_id = db.lookup_intern_callable_def((*fn_def_id).into());
907+
let generic_def_id = GenericDefId::from_callable(db.upcast(), callable_def_id);
908+
let generic_param_list: Option<trap::Label<generated::GenericParamList>> =
909+
emit_generic_param_list(trap, db, generic_def_id);
910+
808911
trap.emit(generated::Function {
809912
id: trap::TrapId::Star,
810913
name,
@@ -817,7 +920,7 @@ fn const_or_function(
817920
is_async: false,
818921
is_gen: false,
819922
is_unsafe: matches!(data.sig.safety, Safety::Unsafe),
820-
generic_param_list: None, //TODO
923+
generic_param_list,
821924
param_list: Some(param_list),
822925
ret_type,
823926
where_clause: None,

rust/ql/test/extractor-tests/crate_graph/module.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -48,8 +48,11 @@ pub struct LocalKey<T: 'static> {
4848
inner: fn(Option<&mut Option<T>>) -> *const T,
4949
}
5050

51-
impl From<usize> for X {
52-
fn from(x: usize) -> Self {
53-
X::A
51+
pub struct Thing<T> {
52+
x: T,
53+
}
54+
impl From<usize> for Thing<X> {
55+
fn from(_x: usize) -> Self {
56+
Thing { x: X::A }
5457
}
5558
}

rust/ql/test/extractor-tests/crate_graph/modules.expected

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
#-----| impl ...::Display for ...::X { ... }
2121
#-----| -> fn fmt
2222

23-
#-----| impl ...::From::<...> for ...::X { ... }
23+
#-----| impl ...::From::<...> for ...::Thing::<...> { ... }
2424
#-----| -> fn from
2525

2626
lib.rs:
@@ -34,8 +34,9 @@ lib.rs:
3434
#-----| -> fn length
3535
#-----| -> impl ...::AsString for ...::X { ... }
3636
#-----| -> impl ...::Display for ...::X { ... }
37-
#-----| -> impl ...::From::<...> for ...::X { ... }
38-
#-----| -> struct LocalKey
37+
#-----| -> impl ...::From::<...> for ...::Thing::<...> { ... }
38+
#-----| -> struct LocalKey<T>
39+
#-----| -> struct Thing<T>
3940
#-----| -> struct X_List
4041
#-----| -> trait AsString
4142
#-----| -> use ...::DirBuilder
@@ -69,7 +70,9 @@ lib.rs:
6970
#-----| -> use ...::symlink_metadata
7071
#-----| -> use ...::write
7172

72-
#-----| struct LocalKey
73+
#-----| struct LocalKey<T>
74+
75+
#-----| struct Thing<T>
7376

7477
#-----| struct X_List
7578

rust/ql/test/extractor-tests/crate_graph/modules.ql

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,33 @@ class RelevantNode extends Item {
1313
this.getParentNode*() =
1414
any(Crate m | m.getName() = "test" and m.getVersion() = "0.0.1").getModule()
1515
}
16+
17+
string label() { result = this.toString() }
18+
}
19+
20+
class HasGenericParams extends RelevantNode {
21+
private GenericParamList params;
22+
23+
HasGenericParams() {
24+
params = this.(Function).getGenericParamList() or
25+
params = this.(Enum).getGenericParamList() or
26+
params = this.(Struct).getGenericParamList() or
27+
params = this.(Union).getGenericParamList() or
28+
params = this.(Impl).getGenericParamList() or
29+
params = this.(Enum).getGenericParamList() or
30+
params = this.(Trait).getGenericParamList() or
31+
params = this.(TraitAlias).getGenericParamList()
32+
}
33+
34+
override string label() {
35+
result =
36+
super.toString() + "<" +
37+
strictconcat(string part, int index |
38+
part = params.getGenericParam(index).toString()
39+
|
40+
part, ", " order by index
41+
) + ">"
42+
}
1643
}
1744

1845
predicate edges(RelevantNode container, RelevantNode element) {
@@ -25,7 +52,7 @@ query predicate nodes(RelevantNode node, string attr, string val) {
2552
nodes(node) and
2653
(
2754
attr = "semmle.label" and
28-
val = node.toString()
55+
val = node.label()
2956
or
3057
attr = "semmle.order" and
3158
val =

0 commit comments

Comments
 (0)