i_slint_compiler/passes/
key_bindings.rs1use std::{
5 collections::{HashMap, hash_map::Entry},
6 rc::Rc,
7};
8
9use crate::{
10 diagnostics::BuildDiagnostics,
11 expression_tree::Expression,
12 object_tree::{Component, recurse_elem_including_sub_components},
13};
14
15pub fn warn_duplicates(component: &Rc<Component>, diagnostics: &mut BuildDiagnostics) {
16 recurse_elem_including_sub_components(component, &(), &mut |elem, _| {
17 let elem = elem.borrow();
18 let is_focus_scope =
19 elem.builtin_type().map(|builtin| builtin.name == "FocusScope").unwrap_or_default();
20 if is_focus_scope {
21 let shortcuts = elem
22 .children
23 .iter()
24 .filter_map(|child| {
25 let child = child.borrow();
26 if child.builtin_type().map(|b| b.name == "KeyBinding").unwrap_or_default() {
27 Some(child)
28 } else {
29 None
30 }
31 })
32 .filter_map(|shortcut| {
33 let keys_expr = shortcut.bindings.get("keys")?.borrow();
34 if let Expression::Keys(ref keys) = keys_expr.expression {
35 Some((keys.clone(), keys_expr.clone()))
36 } else {
37 None
38 }
39 });
40
41 let mut seen_shortcuts = HashMap::new();
42 for (shortcut, span) in shortcuts {
43 match seen_shortcuts.entry(shortcut.clone()) {
44 Entry::Vacant(entry) => {
45 entry.insert(span);
46 }
47 Entry::Occupied(first) => {
48 diagnostics.push_error(
49 "This KeyBinding element has the same keys as an existing KeyBinding - it is undefined which binding activates".into(),
50 &span,
51 );
52 diagnostics.push_note(
53 "First duplicate KeyBinding defined here".into(),
54 first.get(),
55 );
56 }
57 }
58 }
59 }
60 });
61}