loalang 0.1.15

Loa is a general-purpose, purely immutable, object-oriented programming language.
Documentation
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,
        );
    }
}