• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

vcfxb / wright-lang / 15152019424

21 May 2025 02:18AM UTC coverage: 75.318% (-0.08%) from 75.402%
15152019424

push

github

vcfxb
chore: cargo fmt

2 of 6 new or added lines in 1 file covered. (33.33%)

2 existing lines in 1 file now uncovered.

946 of 1256 relevant lines covered (75.32%)

33.39 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

89.39
/wright/src/parser/decl/import.rs
1
//! Parser implementation for `use path::to::thing;` declaration.
2

3
use crate::{
4
    ast::{decl::import::ImportDecl, identifier::Identifier, path::Path},
5
    lexer::token::{Token, TokenTy},
6
    parser::{
7
        Parser,
8
        error::{ParserError, ParserErrorKind},
9
        whitespace,
10
    },
11
    source_tracking::fragment::Fragment,
12
};
13

14
impl ImportDecl {
15
    /// Parse an import declaration.
16
    ///
17
    /// This will advance the parser if `use` is seen -- if a valid formed import does not follow,
18
    /// the parser may be left in the middle of a malformed declaration.
19
    pub fn parse(parser: &mut Parser) -> Result<Self, ParserError> {
5✔
20
        let use_kw: Token = parser.next_if_is(TokenTy::KwUse).ok_or(
5✔
21
            ParserErrorKind::ExpectedImportDeclaration.at(parser.peek_fragment_or_rest_cloned()),
5✔
22
        )?;
×
23

24
        // Require a whitespace after the keyword.
25
        whitespace::require_whitespace(parser)?;
5✔
26
        // Parse the path.
27
        let path: Path = Path::parse(parser)?;
5✔
28

29
        // Whitespace and then "as ...;" or optional whitespace and semi ";".
30

31
        // The "as ...;" requires a whitespace.
32
        let imported_as = match parser.next_if_is(TokenTy::Whitespace) {
5✔
33
            // If there's no whitespace after the path, we expect it to be followed by a semicolon (no renaming).
34
            None => None,
1✔
35

36
            // If there is a whitespace, then it could be followed by `as ...;` or just `;`.
37
            Some(_) => {
38
                // Either way, consume any additional whitespace/comments.
39
                whitespace::optional_whitespace(parser);
4✔
40

41
                // Check if we have an `as` and if so read the renaming clause.
42
                // Otherwise pass on to reading the semicolon.
43
                match parser.next_if_is(TokenTy::KwAs) {
4✔
44
                    // No `as` -- do nothing (return no renaming clause).
45
                    None => None,
1✔
46

47
                    // `as ...;` -- consume the ` ...` part.
48
                    Some(_) => {
49
                        whitespace::require_whitespace(parser).map_err(|e| {
3✔
NEW
50
                            e.with_help("whitespace needed between \"as\" and binding.")
×
NEW
51
                        })?;
×
52

53
                        let imported_as = Identifier::parse(parser).map_err(|e| {
3✔
NEW
54
                            e.with_help("expected binding in \"use ... as\" declaration.")
×
NEW
55
                        })?;
×
56

57
                        Some(imported_as)
3✔
58
                    }
59
                }
60
            }
61
        };
62

63
        whitespace::optional_whitespace(parser);
5✔
64

65
        if let Some(semi) = parser.next_if_is(TokenTy::Semi) {
5✔
66
            Ok(ImportDecl {
5✔
67
                matching_source: Fragment::cover(&use_kw.fragment, &semi.fragment),
5✔
68
                imported_item: path,
5✔
69
                imported_as,
5✔
70
            })
5✔
71
        } else {
UNCOV
72
            Err(ParserErrorKind::ImportMustEndWithSemicolon
×
UNCOV
73
                .at(parser.peek_fragment_or_rest_cloned()))
×
74
        }
75
    }
5✔
76
}
77

78
#[cfg(test)]
79
mod tests {
80
    use crate::{ast::decl::import::ImportDecl, lexer::Lexer, parser::Parser};
81

82
    #[test]
83
    fn test_import() {
1✔
84
        let mut parser = Parser::new(Lexer::new_test("use wright::util;"));
1✔
85
        let import_decl = ImportDecl::parse(&mut parser).unwrap();
1✔
86
        assert!(parser.lexer.remaining.is_empty());
1✔
87
        assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
1✔
88
        assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
1✔
89
    }
1✔
90

91
    #[test]
92
    fn test_import_with_whitespace() {
1✔
93
        let mut parser = Parser::new(Lexer::new_test("use wright :: util ;"));
1✔
94
        let import_decl = ImportDecl::parse(&mut parser).unwrap();
1✔
95
        assert!(parser.lexer.remaining.is_empty());
1✔
96
        assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
1✔
97
        assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
1✔
98
    }
1✔
99

100
    #[test]
101
    fn test_import_as() {
1✔
102
        let mut parser = Parser::new(Lexer::new_test("use wright::util as u;"));
1✔
103
        let import_decl = ImportDecl::parse(&mut parser).unwrap();
1✔
104
        assert!(parser.lexer.remaining.is_empty());
1✔
105
        assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
1✔
106
        assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
1✔
107
        assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
1✔
108
    }
1✔
109

110
    #[test]
111
    fn test_import_as_with_comment() {
1✔
112
        let mut parser = Parser::new(Lexer::new_test("use wright::util as /* old_name */ u;"));
1✔
113
        let import_decl = ImportDecl::parse(&mut parser).unwrap();
1✔
114
        assert!(parser.lexer.remaining.is_empty());
1✔
115
        assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
1✔
116
        assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
1✔
117
        assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
1✔
118
    }
1✔
119

120
    #[test]
121
    fn test_import_as_with_preceding_comment() {
1✔
122
        let mut parser = Parser::new(Lexer::new_test("use wright::util /* as old_name */ as u;"));
1✔
123
        let import_decl = ImportDecl::parse(&mut parser).unwrap();
1✔
124
        assert!(parser.lexer.remaining.is_empty());
1✔
125
        assert_eq!(import_decl.imported_item.head.fragment.as_str(), "wright");
1✔
126
        assert_eq!(import_decl.imported_item.tail[0].fragment.as_str(), "util");
1✔
127
        assert_eq!(import_decl.imported_as.unwrap().fragment.as_str(), "u");
1✔
128
    }
1✔
129
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc