1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::semantics::*;
use crate::syntax::*;
use crate::*;

pub struct DuplicateDeclaration;

impl DuplicateDeclaration {
    fn check_kind(
        kind: DeclarationKind,
        analysis: &mut Analysis,
        diagnostics: &mut Vec<Diagnostic>,
        reported_symbols: &mut Vec<Id>,
    ) {
        for scope_root in analysis.navigator.all_scope_roots() {
            let mut declarations_by_name = HashMap::new();

            for declaration in analysis
                .navigator
                .all_declarations_in_scope(&scope_root, kind)
            {
                if let Some((name, symbol)) = analysis.navigator.symbol_of(&declaration) {
                    if !declarations_by_name.contains_key(&name) {
                        declarations_by_name.insert(name.clone(), vec![]);
                    }

                    declarations_by_name.get_mut(&name).unwrap().push(symbol);
                }
            }

            for (name, declarations) in declarations_by_name {
                let count = declarations.len();

                if count < 2 {
                    continue;
                }

                for symbol in declarations {
                    if reported_symbols.contains(&symbol.id) {
                        continue;
                    }

                    diagnostics.push(Diagnostic::DuplicatedDeclaration(
                        symbol.span,
                        name.clone(),
                        count,
                    ));

                    reported_symbols.push(symbol.id);
                }
            }
        }
    }
}

impl Checker for DuplicateDeclaration {
    fn check(&self, analysis: &mut Analysis, diagnostics: &mut Vec<Diagnostic>) {
        let mut reported_symbols = vec![];
        Self::check_kind(
            DeclarationKind::Type,
            analysis,
            diagnostics,
            &mut reported_symbols,
        );
        Self::check_kind(
            DeclarationKind::Value,
            analysis,
            diagnostics,
            &mut reported_symbols,
        );
    }
}