Skip to content

Commit cec95ae

Browse files
committed
Rust: crate graph: generic parameters
1 parent a7ccba9 commit cec95ae

File tree

4 files changed

+160
-22
lines changed

4 files changed

+160
-22
lines changed

rust/extractor/src/crate_graph.rs

Lines changed: 119 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,17 +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::GenericDefId;
1415
use ra_ap_hir_def::Lookup;
1516
use ra_ap_hir_def::{
16-
AssocItemId, LocalModuleId, data::adt::VariantData, item_scope::ImportOrGlob,
17-
item_tree::ImportKind, nameres::ModuleData, path::ImportAlias,
17+
AssocItemId, ConstParamId, LocalModuleId, TypeOrConstParamId, data::adt::VariantData,
18+
generics::TypeOrConstParamData, item_scope::ImportOrGlob, item_tree::ImportKind,
19+
nameres::ModuleData, path::ImportAlias,
1820
};
1921
use ra_ap_hir_def::{HasModule, visibility::VisibilityExplicitness};
2022
use ra_ap_hir_def::{ModuleId, resolver::HasResolver};
2123
use ra_ap_hir_ty::GenericArg;
2224
use ra_ap_hir_ty::TraitRefExt;
2325
use ra_ap_hir_ty::Ty;
2426
use ra_ap_hir_ty::TyExt;
27+
use ra_ap_hir_ty::TyLoweringContext;
2528
use ra_ap_hir_ty::WhereClause;
2629
use ra_ap_hir_ty::db::InternedCallableDefId;
2730
use ra_ap_hir_ty::from_assoc_type_id;
@@ -432,7 +435,98 @@ fn emit_enum_variant(
432435
}
433436
items
434437
}
438+
fn emit_generic_param_list(
439+
trap: &mut TrapFile,
440+
db: &dyn HirDatabase,
441+
def: GenericDefId,
442+
) -> Option<trap::Label<generated::GenericParamList>> {
443+
let params = db.generic_params(def);
444+
let trait_self_param = params.trait_self_param();
445+
if params.is_empty() || params.len() == 1 && trait_self_param.is_some() {
446+
return None;
447+
}
448+
let mut generic_params = Vec::new();
449+
generic_params.extend(params.iter_lt().map(
450+
|(_, param)| -> trap::Label<generated::GenericParam> {
451+
let lifetime = trap
452+
.emit(generated::Lifetime {
453+
id: trap::TrapId::Star,
454+
text: Some(param.name.as_str().to_owned()),
455+
})
456+
.into();
435457

458+
trap.emit(generated::LifetimeParam {
459+
id: trap::TrapId::Star,
460+
attrs: vec![],
461+
lifetime,
462+
type_bound_list: None,
463+
})
464+
.into()
465+
},
466+
));
467+
generic_params.extend(
468+
params
469+
.iter_type_or_consts()
470+
.filter(|(id, _)| trait_self_param != Some(*id))
471+
.map(
472+
|(param_id, param)| -> trap::Label<generated::GenericParam> {
473+
match param {
474+
TypeOrConstParamData::TypeParamData(param) => {
475+
let name = Some(trap.emit(generated::Name {
476+
id: trap::TrapId::Star,
477+
text: param.name.as_ref().map(|name| name.as_str().to_owned()),
478+
}));
479+
let resolver = def.resolver(db.upcast());
480+
let mut ctx = TyLoweringContext::new(
481+
db,
482+
&resolver,
483+
&params.types_map,
484+
def.into(),
485+
);
486+
487+
let default_type = param
488+
.default
489+
.and_then(|ty| emit_hir_ty(trap, db, &ctx.lower_ty(ty)));
490+
trap.emit(generated::TypeParam {
491+
id: trap::TrapId::Star,
492+
attrs: vec![],
493+
name,
494+
default_type,
495+
type_bound_list: None,
496+
})
497+
.into()
498+
}
499+
TypeOrConstParamData::ConstParamData(param) => {
500+
let name = Some(trap.emit(generated::Name {
501+
id: trap::TrapId::Star,
502+
text: param.name.as_str().to_owned().into(),
503+
}));
504+
let param_id = TypeOrConstParamId {
505+
parent: def,
506+
local_id: param_id,
507+
};
508+
let ty = db.const_param_ty(ConstParamId::from_unchecked(param_id));
509+
let type_repr = emit_hir_ty(trap, db, &ty);
510+
trap.emit(generated::ConstParam {
511+
id: trap::TrapId::Star,
512+
attrs: vec![],
513+
name,
514+
default_val: None,
515+
is_const: true,
516+
type_repr,
517+
})
518+
.into()
519+
}
520+
}
521+
},
522+
),
523+
);
524+
trap.emit(generated::GenericParamList {
525+
id: trap::TrapId::Star,
526+
generic_params,
527+
})
528+
.into()
529+
}
436530
fn emit_adt(
437531
db: &dyn HirDatabase,
438532
name: &str,
@@ -441,6 +535,7 @@ fn emit_adt(
441535
visibility: Visibility,
442536
) -> Vec<trap::Label<generated::Item>> {
443537
let mut items = Vec::new();
538+
444539
match adt_id {
445540
ra_ap_hir_def::AdtId::StructId(struct_id) => {
446541
let name = Some(trap.emit(generated::Name {
@@ -449,13 +544,14 @@ fn emit_adt(
449544
}));
450545
let field_list = emit_variant_data(trap, db, struct_id.into()).into();
451546
let visibility = emit_visibility(db, trap, visibility);
547+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
452548
items.push(
453549
trap.emit(generated::Struct {
454550
id: trap::TrapId::Star,
455551
name,
456552
attrs: vec![],
457553
field_list,
458-
generic_param_list: None,
554+
generic_param_list,
459555
visibility,
460556
where_clause: None,
461557
})
@@ -493,12 +589,13 @@ fn emit_adt(
493589
text: Some(name.to_owned()),
494590
}));
495591
let visibility = emit_visibility(db, trap, visibility);
592+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
496593
items.push(
497594
trap.emit(generated::Enum {
498595
id: trap::TrapId::Star,
499596
name,
500597
attrs: vec![],
501-
generic_param_list: None,
598+
generic_param_list,
502599
variant_list,
503600
visibility,
504601
where_clause: None,
@@ -513,13 +610,14 @@ fn emit_adt(
513610
}));
514611
let struct_field_list = emit_variant_data(trap, db, union_id.into()).into();
515612
let visibility = emit_visibility(db, trap, visibility);
613+
let generic_param_list = emit_generic_param_list(trap, db, adt_id.into());
516614
items.push(
517615
trap.emit(generated::Union {
518616
id: trap::TrapId::Star,
519617
name,
520618
attrs: vec![],
521619
struct_field_list,
522-
generic_param_list: None,
620+
generic_param_list,
523621
visibility,
524622
where_clause: None,
525623
})
@@ -538,8 +636,8 @@ fn emit_trait(
538636
visibility: Visibility,
539637
) -> Vec<trap::Label<generated::Item>> {
540638
let mut items = Vec::new();
541-
let data = db.trait_items(trait_id);
542-
let assoc_items: Vec<trap::Label<generated::AssocItem>> = data
639+
let trait_items = db.trait_items(trait_id);
640+
let assoc_items: Vec<trap::Label<generated::AssocItem>> = trait_items
543641
.items
544642
.iter()
545643
.flat_map(|(name, item)| {
@@ -577,6 +675,7 @@ fn emit_trait(
577675
text: Some(name.as_str().to_owned()),
578676
}));
579677
let visibility = emit_visibility(db, trap, visibility);
678+
let generic_param_list = emit_generic_param_list(trap, db, (*function).into());
580679
Some(
581680
trap.emit(generated::Function {
582681
id: trap::TrapId::Star,
@@ -590,7 +689,7 @@ fn emit_trait(
590689
is_async: false,
591690
is_gen: false,
592691
is_unsafe: matches!(sig.to_fn_ptr().sig.safety, Safety::Unsafe),
593-
generic_param_list: None, //TODO
692+
generic_param_list,
594693
param_list: Some(param_list),
595694
ret_type,
596695
where_clause: None,
@@ -612,13 +711,14 @@ fn emit_trait(
612711
text: Some(name.to_owned()),
613712
}));
614713
let visibility = emit_visibility(db, trap, visibility);
714+
let generic_param_list = emit_generic_param_list(trap, db, trait_id.into());
615715
items.push(
616716
trap.emit(generated::Trait {
617717
id: trap::TrapId::Star,
618718
name,
619719
assoc_item_list,
620720
attrs: vec![],
621-
generic_param_list: None,
721+
generic_param_list,
622722
is_auto: false,
623723
is_unsafe: false,
624724
type_bound_list: None,
@@ -694,7 +794,7 @@ fn emit_module_impls(
694794
data.visibility
695795
.resolve(db.upcast(), &function.resolver(db.upcast())),
696796
);
697-
797+
let generic_param_list = emit_generic_param_list(trap, db, (*function).into());
698798
Some(
699799
trap.emit(generated::Function {
700800
id: trap::TrapId::Star,
@@ -708,7 +808,7 @@ fn emit_module_impls(
708808
is_async: false,
709809
is_gen: false,
710810
is_unsafe: matches!(sig.to_fn_ptr().sig.safety, Safety::Unsafe),
711-
generic_param_list: None, //TODO
811+
generic_param_list,
712812
param_list: Some(param_list),
713813
ret_type,
714814
where_clause: None,
@@ -725,14 +825,15 @@ fn emit_module_impls(
725825
assoc_items,
726826
attrs: vec![],
727827
}));
828+
let generic_param_list = emit_generic_param_list(trap, db, imp.into());
728829
items.push(
729830
trap.emit(generated::Impl {
730831
id: trap::TrapId::Star,
731832
trait_,
732833
self_ty,
733834
assoc_item_list,
734835
attrs: vec![],
735-
generic_param_list: None,
836+
generic_param_list,
736837
is_const: false,
737838
is_default: false,
738839
is_unsafe: false,
@@ -778,7 +879,6 @@ fn const_or_function(
778879
let callable_def_id =
779880
db.lookup_intern_callable_def(InternedCallableDefId::from(*fn_def_id));
780881
let data = db.fn_def_datum(callable_def_id);
781-
782882
let sig = ra_ap_hir_ty::CallableSig::from_def(db, *fn_def_id, parameters);
783883
let params = sig
784884
.params()
@@ -811,6 +911,11 @@ fn const_or_function(
811911
text: Some(name.to_owned()),
812912
}));
813913
let visibility = emit_visibility(db, trap, visibility);
914+
let callable_def_id = db.lookup_intern_callable_def((*fn_def_id).into());
915+
let generic_def_id = GenericDefId::from_callable(db.upcast(), callable_def_id);
916+
let generic_param_list: Option<trap::Label<generated::GenericParamList>> =
917+
emit_generic_param_list(trap, db, generic_def_id);
918+
814919
trap.emit(generated::Function {
815920
id: trap::TrapId::Star,
816921
name,
@@ -823,7 +928,7 @@ fn const_or_function(
823928
is_async: false,
824929
is_gen: false,
825930
is_unsafe: matches!(data.sig.safety, Safety::Unsafe),
826-
generic_param_list: None, //TODO
931+
generic_param_list,
827932
param_list: Some(param_list),
828933
ret_type,
829934
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)