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
72
73
74
75
76
77
78
79
80
81
82
83
use std::result;

use crate::hir::error::{Error, ErrorKind};
use crate::hir::exports::Exports;
use crate::hir::import::parse::{ParsedFilter, ParsedImportSet};

type Result<T> = result::Result<T, Vec<Error>>;

fn apply_filter(filter: ParsedFilter, exports: &Exports) -> Result<Exports> {
    match filter {
        ParsedFilter::Only(only_spanned_names) => Ok(only_spanned_names
            .into_vec()
            .into_iter()
            .map(|(span, name)| {
                if let Some(binding) = exports.get(&name) {
                    Ok((name, binding.clone()))
                } else {
                    Err(Error::new(span, ErrorKind::UnboundIdent(name)))
                }
            })
            .collect::<result::Result<Exports, Error>>()?),

        ParsedFilter::Exclude(exclude_spanned_names) => {
            let mut exports = exports.clone();
            let mut errors = vec![];

            for (span, name) in exclude_spanned_names.into_vec().into_iter() {
                if exports.remove(&name).is_none() {
                    errors.push(Error::new(span, ErrorKind::UnboundIdent(name)));
                }
            }

            if errors.is_empty() {
                Ok(exports)
            } else {
                Err(errors)
            }
        }

        ParsedFilter::Rename(rename_spanned_names) => {
            let mut exports = exports.clone();
            let mut errors = vec![];

            for ((from_span, from_name), to_name) in rename_spanned_names.into_vec().into_iter() {
                match exports.remove(&from_name) {
                    Some(binding) => {
                        exports.insert(to_name, binding);
                    }
                    None => {
                        errors.push(Error::new(from_span, ErrorKind::UnboundIdent(from_name)));
                    }
                }
            }

            if errors.is_empty() {
                Ok(exports)
            } else {
                Err(errors)
            }
        }

        ParsedFilter::Prefix(prefix_name) => Ok(exports
            .iter()
            .map(|(name, binding)| (format!("{}{}", prefix_name, name).into(), binding.clone()))
            .collect()),
    }
}

/// Applies the parsed import to the passed exports
///
/// If there are no filters to apply then `exports` will be directly returned.
pub fn filter_imported_exports(
    parsed_import_set: ParsedImportSet,
    exports: &Exports,
) -> Result<Exports> {
    match parsed_import_set {
        ParsedImportSet::Module(_, _) => Ok(exports.clone()),
        ParsedImportSet::Filter(filter, inner_parsed_import) => {
            let inner_exports = filter_imported_exports(*inner_parsed_import, exports)?;
            Ok(apply_filter(filter, &inner_exports)?)
        }
    }
}