`from import names|*`: spec is URL, path, or bare name; `*` binds all exports. Names may be parenthesized for multi-line lists, trailing comma allowed. */
(&mut self)
| 32 | |
| 33 | /* `from <spec> import names|*`: spec is URL, path, or bare name; `*` binds all exports. Names may be parenthesized for multi-line lists, trailing comma allowed. */ |
| 34 | pub(super) fn do_from_stmt(&mut self) { |
| 35 | self.advance(); // 'from' |
| 36 | let (spec, spec_span) = self.read_module_spec(); |
| 37 | self.eat(TokenType::Import); |
| 38 | |
| 39 | if self.eat_if(TokenType::Star) { |
| 40 | self.resolve_and_bind_star(&spec, spec_span); |
| 41 | return; |
| 42 | } |
| 43 | |
| 44 | let parens = self.eat_if(TokenType::Lpar); |
| 45 | |
| 46 | let mut names: Vec<(String, String)> = Vec::new(); |
| 47 | loop { |
| 48 | // Peek flushes Nl/Comment inside parens and lets a trailing `,` end the list. |
| 49 | if parens && matches!(self.peek(), Some(TokenType::Rpar)) { break; } |
| 50 | let name = self.advance_text(); |
| 51 | let alias = if self.eat_if(TokenType::As) { self.advance_text() } else { name.clone() }; |
| 52 | names.push((name, alias)); |
| 53 | if !self.eat_if(TokenType::Comma) { break; } |
| 54 | } |
| 55 | |
| 56 | if parens { self.eat(TokenType::Rpar); } |
| 57 | |
| 58 | self.resolve_and_bind_named(&spec, spec_span, names); |
| 59 | } |
| 60 | |
| 61 | /* Reads a quoted or dotted spec; returns (spec, span) for diagnostics. */ |
| 62 | fn read_module_spec(&mut self) -> (String, (usize, usize)) { |
no test coverage detected