Skip to content

Commit a900d47

Browse files
asukaminato0721meta-codesync[bot]
authored andcommitted
fix auto complete dict key when possible #1189 (#1515)
Summary: fix #1189 Introduced dict key completions: added facet chains and literal facet propagation. Pull Request resolved: #1515 Reviewed By: stroxler Differential Revision: D86695925 Pulled By: kinto0 fbshipit-source-id: 113bf6141794c1aec220e582aab8ed6729283408
1 parent c10f0f5 commit a900d47

File tree

6 files changed

+547
-54
lines changed

6 files changed

+547
-54
lines changed

crates/pyrefly_types/src/type_info.rs

Lines changed: 188 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,18 @@ impl TypeInfo {
9898
}
9999
}
100100

101+
pub fn record_key_completion(&mut self, facets: &Vec1<FacetKind>, ty: Option<Type>) {
102+
if let Some((facet, rest)) = facets.as_slice().split_first() {
103+
let narrowed = self
104+
.facets
105+
.get_or_insert_with(|| Box::new(NarrowedFacets::default()));
106+
narrowed.ensure_completion_path(facet, rest, ty);
107+
}
108+
}
109+
101110
pub fn type_at_facet(&self, facet: &FacetKind) -> Option<&Type> {
102111
match self.get_at_facet(facet) {
103-
None | Some(NarrowedFacet::WithoutRoot(..)) => None,
112+
None | Some(NarrowedFacet::WithoutRoot { .. }) => None,
104113
Some(NarrowedFacet::Leaf(ty)) | Some(NarrowedFacet::WithRoot(ty, _)) => Some(ty),
105114
}
106115
}
@@ -109,9 +118,9 @@ impl TypeInfo {
109118
match self.get_at_facet(facet) {
110119
None => TypeInfo::of_ty(fallback()),
111120
Some(NarrowedFacet::Leaf(ty)) => Self::of_ty(ty.clone()),
112-
Some(NarrowedFacet::WithoutRoot(narrowed_facets)) => Self {
121+
Some(NarrowedFacet::WithoutRoot { facets, .. }) => Self {
113122
ty: fallback(),
114-
facets: Some(Box::new(narrowed_facets.clone())),
123+
facets: Some(Box::new(facets.clone())),
115124
},
116125
Some(NarrowedFacet::WithRoot(ty, narrowed_facets)) => Self {
117126
ty: ty.clone(),
@@ -228,6 +237,66 @@ impl TypeInfo {
228237
}
229238
}
230239

240+
/// Return the known narrowings for dictionary-style key facets at the provided prefix.
241+
///
242+
/// The `prefix` is the sequence of facets (attributes, indexes, and keys) that identify the
243+
/// container whose keys we are interested in. When the prefix is empty, this inspects the
244+
/// top-level facets on the `TypeInfo` itself.
245+
pub fn key_facets_at(&self, prefix: &[FacetKind]) -> Vec<(String, Option<Type>)> {
246+
fn collect_keys(facets: &NarrowedFacets) -> Vec<(String, Option<Type>)> {
247+
facets
248+
.0
249+
.iter()
250+
.filter_map(|(facet, narrowed)| {
251+
if let FacetKind::Key(key) = facet {
252+
let ty = match narrowed {
253+
NarrowedFacet::Leaf(ty) => Some(ty.clone()),
254+
NarrowedFacet::WithRoot(ty, _) => Some(ty.clone()),
255+
NarrowedFacet::WithoutRoot { completion_ty, .. } => {
256+
completion_ty.clone()
257+
}
258+
};
259+
Some((key.clone(), ty))
260+
} else {
261+
None
262+
}
263+
})
264+
.collect()
265+
}
266+
267+
fn descend<'a>(
268+
mut current: &'a NarrowedFacets,
269+
prefix: &[FacetKind],
270+
) -> Option<&'a NarrowedFacets> {
271+
for facet in prefix {
272+
let narrowed = current.0.get(facet)?;
273+
match narrowed {
274+
NarrowedFacet::Leaf(_) => return None,
275+
NarrowedFacet::WithRoot(_, nested) => {
276+
current = nested;
277+
}
278+
NarrowedFacet::WithoutRoot { facets, .. } => {
279+
current = facets;
280+
}
281+
}
282+
}
283+
Some(current)
284+
}
285+
286+
match &self.facets {
287+
Some(facets) => {
288+
if prefix.is_empty() {
289+
collect_keys(facets.as_ref())
290+
} else if let Some(target) = descend(facets.as_ref(), prefix) {
291+
collect_keys(target)
292+
} else {
293+
Vec::new()
294+
}
295+
}
296+
None => Vec::new(),
297+
}
298+
}
299+
231300
pub fn ty(&self) -> &Type {
232301
&self.ty
233302
}
@@ -276,6 +345,12 @@ const NARROWED_FACETS_LIMIT: usize = 50;
276345
#[derive(Debug, Clone, PartialEq, Eq, TypeEq)]
277346
struct NarrowedFacets(SmallMap<FacetKind, NarrowedFacet>);
278347

348+
impl Default for NarrowedFacets {
349+
fn default() -> Self {
350+
Self(SmallMap::new())
351+
}
352+
}
353+
279354
impl NarrowedFacets {
280355
fn insert(&mut self, facet: FacetKind, value: NarrowedFacet) {
281356
// Only insert if there is space, or if the key is already present (so we overwrite)
@@ -328,9 +403,9 @@ impl NarrowedFacets {
328403
narrowed_facet.add_narrow(more_facets, ty);
329404
}
330405
NarrowedFacet::Leaf(..) => {}
331-
NarrowedFacet::WithoutRoot(narrowed_facets)
332-
| NarrowedFacet::WithRoot(_, narrowed_facets) => {
333-
narrowed_facets.update_for_assignment(next_facet, remaining_facets, ty);
406+
NarrowedFacet::WithoutRoot { facets, .. }
407+
| NarrowedFacet::WithRoot(_, facets) => {
408+
facets.update_for_assignment(next_facet, remaining_facets, ty);
334409
}
335410
}
336411
} else if let Some(ty) = ty {
@@ -349,6 +424,35 @@ impl NarrowedFacets {
349424
Self(smallmap! {facet => NarrowedFacet::new(more_facets, ty)})
350425
}
351426

427+
fn ensure_completion_path(
428+
&mut self,
429+
facet: &FacetKind,
430+
rest: &[FacetKind],
431+
completion_ty: Option<Type>,
432+
) {
433+
let entry = self.0.entry(facet.clone()).or_insert_with(|| {
434+
if rest.is_empty() {
435+
NarrowedFacet::WithoutRoot {
436+
completion_ty: None,
437+
facets: NarrowedFacets::default(),
438+
}
439+
} else {
440+
let mut nested = NarrowedFacets::default();
441+
nested.ensure_completion_path(&rest[0], &rest[1..], completion_ty.clone());
442+
NarrowedFacet::WithoutRoot {
443+
completion_ty: None,
444+
facets: nested,
445+
}
446+
}
447+
});
448+
449+
if let Some((next, tail)) = rest.split_first() {
450+
entry.ensure_completion_child(next, tail, completion_ty);
451+
} else {
452+
entry.set_completion_ty(completion_ty);
453+
}
454+
}
455+
352456
fn join(
353457
mut branches: Vec<Self>,
354458
union_types: &impl Fn(Vec<Type>) -> Type,
@@ -413,7 +517,7 @@ impl NarrowedFacets {
413517
write!(f, ", ")?;
414518
facets.fmt_with_prefix_and_facet(prefix, facet, f)
415519
}
416-
NarrowedFacet::WithoutRoot(facets) => {
520+
NarrowedFacet::WithoutRoot { facets, .. } => {
417521
facets.fmt_with_prefix_and_facet(prefix, facet, f)
418522
}
419523
}?;
@@ -478,16 +582,20 @@ enum NarrowedFacet {
478582
/// This facet is narrowed, and has one or more narrowed sub-facet (WithRoot)
479583
WithRoot(Type, NarrowedFacets),
480584
/// This facet is not narrowed, and has one or more narrowed sub-facet (WithoutRoot)
481-
WithoutRoot(NarrowedFacets),
585+
WithoutRoot {
586+
completion_ty: Option<Type>,
587+
facets: NarrowedFacets,
588+
},
482589
}
483590

484591
impl NarrowedFacet {
485592
fn new(facets: &[FacetKind], ty: Type) -> Self {
486593
match facets {
487594
[] => Self::Leaf(ty),
488-
[facet, more_facets @ ..] => {
489-
Self::WithoutRoot(NarrowedFacets::of_narrow((*facet).clone(), more_facets, ty))
490-
}
595+
[facet, more_facets @ ..] => Self::WithoutRoot {
596+
completion_ty: None,
597+
facets: NarrowedFacets::of_narrow((*facet).clone(), more_facets, ty),
598+
},
491599
}
492600
}
493601

@@ -501,41 +609,68 @@ impl NarrowedFacet {
501609
fn clear_index_narrows(&mut self, facets: &[FacetKind]) {
502610
match self {
503611
Self::Leaf(_) => {}
504-
Self::WithRoot(_, narrowed_facets) | Self::WithoutRoot(narrowed_facets) => {
505-
narrowed_facets.clear_index_narrows(facets)
506-
}
612+
Self::WithRoot(_, narrowed_facets)
613+
| Self::WithoutRoot {
614+
facets: narrowed_facets,
615+
..
616+
} => narrowed_facets.clear_index_narrows(facets),
507617
}
508618
}
509619

510620
fn with_narrow(self, facets: &[FacetKind], narrowed_ty: Type) -> Self {
511621
match facets {
512-
[] => {
513-
// We are setting a narrow at the current node (potentially overriding an existing narrow; it is
514-
// up to callers to make sure this works correctly, we just take what was given).
515-
match self {
516-
Self::Leaf(_) => Self::Leaf(narrowed_ty),
517-
Self::WithRoot(_, narrowed_facets) | Self::WithoutRoot(narrowed_facets) => {
518-
Self::WithRoot(narrowed_ty, narrowed_facets)
519-
}
622+
[] => match self {
623+
Self::Leaf(_) => Self::Leaf(narrowed_ty),
624+
Self::WithRoot(_, narrowed_facets)
625+
| Self::WithoutRoot {
626+
facets: narrowed_facets,
627+
..
628+
} => Self::WithRoot(narrowed_ty, narrowed_facets),
629+
},
630+
[facet, more_facets @ ..] => match self {
631+
Self::Leaf(root_ty) => {
632+
let narrowed_facets =
633+
NarrowedFacets::of_narrow((*facet).clone(), more_facets, narrowed_ty);
634+
Self::WithRoot(root_ty, narrowed_facets)
520635
}
521-
}
522-
[facet, more_facets @ ..] => {
523-
// We are setting a narrow in a subtree. We need to preserve any existing tree.
524-
match self {
525-
Self::Leaf(root_ty) => {
526-
let narrowed_facets =
527-
NarrowedFacets::of_narrow((*facet).clone(), more_facets, narrowed_ty);
528-
Self::WithRoot(root_ty, narrowed_facets)
529-
}
530-
Self::WithoutRoot(mut narrowed_facets) => {
531-
narrowed_facets.add_narrow(facet, more_facets, narrowed_ty);
532-
Self::WithoutRoot(narrowed_facets)
533-
}
534-
Self::WithRoot(root_ty, mut narrowed_facets) => {
535-
narrowed_facets.add_narrow(facet, more_facets, narrowed_ty);
536-
Self::WithRoot(root_ty, narrowed_facets)
636+
Self::WithoutRoot { mut facets, .. } => {
637+
facets.add_narrow(facet, more_facets, narrowed_ty);
638+
Self::WithoutRoot {
639+
completion_ty: None,
640+
facets,
537641
}
538642
}
643+
Self::WithRoot(root_ty, mut narrowed_facets) => {
644+
narrowed_facets.add_narrow(facet, more_facets, narrowed_ty);
645+
Self::WithRoot(root_ty, narrowed_facets)
646+
}
647+
},
648+
}
649+
}
650+
651+
fn set_completion_ty(&mut self, ty: Option<Type>) {
652+
if let NarrowedFacet::WithoutRoot { completion_ty, .. } = self {
653+
*completion_ty = ty;
654+
}
655+
}
656+
657+
fn ensure_completion_child(
658+
&mut self,
659+
facet: &FacetKind,
660+
rest: &[FacetKind],
661+
completion_ty: Option<Type>,
662+
) {
663+
match self {
664+
Self::Leaf(root_ty) => {
665+
let mut nested = NarrowedFacets::default();
666+
nested.ensure_completion_path(facet, rest, completion_ty);
667+
*self = Self::WithRoot(root_ty.clone(), nested);
668+
}
669+
Self::WithRoot(_, nested) => {
670+
nested.ensure_completion_path(facet, rest, completion_ty);
671+
}
672+
Self::WithoutRoot { facets, .. } => {
673+
facets.ensure_completion_path(facet, rest, completion_ty);
539674
}
540675
}
541676
}
@@ -554,20 +689,19 @@ impl NarrowedFacet {
554689
acc.push(item)
555690
}
556691
}
557-
};
692+
}
558693
}
559694
let mut ty_branches = Some(Vec::with_capacity(branches.len()));
560695
let mut facets_branches = Some(Vec::with_capacity(branches.len()));
561-
for facet in branches {
562-
let (ty, facets) = match facet {
696+
for branch in branches {
697+
let (ty, facets) = match branch {
563698
Self::WithRoot(ty, facets) => (Some(ty), Some(facets)),
564699
Self::Leaf(ty) => (Some(ty), None),
565-
Self::WithoutRoot(facets) => (None, Some(facets)),
700+
Self::WithoutRoot { facets, .. } => (None, Some(facets)),
566701
};
567702
monadic_push_option(&mut ty_branches, ty);
568703
monadic_push_option(&mut facets_branches, facets);
569704
if let (None, None) = (&ty_branches, &facets_branches) {
570-
// Not needed for correctness, but saves some work.
571705
return None;
572706
}
573707
}
@@ -577,25 +711,24 @@ impl NarrowedFacet {
577711
union_types,
578712
is_subset_eq,
579713
join_style.flat_map(|base_facet| {
580-
base_facet.as_ref().and_then(|f| match f {
714+
base_facet.as_ref().and_then(|facet| match facet {
581715
NarrowedFacet::WithRoot(ty, _) | NarrowedFacet::Leaf(ty) => {
582716
Some(ty.clone())
583717
}
584-
NarrowedFacet::WithoutRoot(_) => None,
718+
NarrowedFacet::WithoutRoot { .. } => None,
585719
})
586720
}),
587721
)
588722
});
589-
let facets = facets_branches.and_then(|facets_branches| {
723+
let facets = facets_branches.and_then(|branches| {
590724
NarrowedFacets::join(
591-
facets_branches,
725+
branches,
592726
union_types,
593727
is_subset_eq,
594728
join_style.map(|base_facet| {
595-
base_facet.as_ref().and_then(|f| match f {
596-
NarrowedFacet::WithRoot(_, facets) | NarrowedFacet::WithoutRoot(facets) => {
597-
Some(facets.clone())
598-
}
729+
base_facet.as_ref().and_then(|facet| match facet {
730+
NarrowedFacet::WithRoot(_, facets)
731+
| NarrowedFacet::WithoutRoot { facets, .. } => Some(facets.clone()),
599732
NarrowedFacet::Leaf(_) => None,
600733
})
601734
}),
@@ -605,7 +738,10 @@ impl NarrowedFacet {
605738
(None, None) => None,
606739
(Some(ty), None) => Some(Self::Leaf(ty)),
607740
(Some(ty), Some(facets)) => Some(Self::WithRoot(ty, facets)),
608-
(None, Some(facets)) => Some(Self::WithoutRoot(facets)),
741+
(None, Some(facets)) => Some(Self::WithoutRoot {
742+
completion_ty: None,
743+
facets,
744+
}),
609745
}
610746
}
611747
}

0 commit comments

Comments
 (0)