Skip to main content

i_slint_compiler/passes/
key_bindings.rs

1// Copyright © SixtyFPS GmbH <info@slint.dev>
2// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-2.0 OR LicenseRef-Slint-Software-3.0
3
4use 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}