Skip to content

Commit

Permalink
Cleanup import parsing
Browse files Browse the repository at this point in the history
Fix spans of root segments
  • Loading branch information
petrochenkov committed Mar 17, 2018
1 parent f881626 commit 636357b
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 54 deletions.
2 changes: 1 addition & 1 deletion src/libsyntax/parse/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,7 +713,7 @@ mod tests {
id: ast::DUMMY_NODE_ID,
node: ast::ExprKind::Path(None, ast::Path {
span: sp(0, 6),
segments: vec![ast::PathSegment::crate_root(sp(0, 2)),
segments: vec![ast::PathSegment::crate_root(sp(0, 0)),
str2seg("a", 2, 3),
str2seg("b", 5, 6)]
}),
Expand Down
75 changes: 22 additions & 53 deletions src/libsyntax/parse/parser.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1990,7 +1990,7 @@ impl<'a> Parser<'a> {
let lo = self.meta_var_span.unwrap_or(self.span);
let mut segments = Vec::new();
if self.eat(&token::ModSep) {
segments.push(PathSegment::crate_root(lo));
segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
}
self.parse_path_segments(&mut segments, style, enable_warning)?;

Expand Down Expand Up @@ -2025,7 +2025,7 @@ impl<'a> Parser<'a> {
loop {
segments.push(self.parse_path_segment(style, enable_warning)?);

if self.is_import_coupler(false) || !self.eat(&token::ModSep) {
if self.is_import_coupler() || !self.eat(&token::ModSep) {
return Ok(());
}
}
Expand Down Expand Up @@ -6483,9 +6483,8 @@ impl<'a> Parser<'a> {
let item_ = ItemKind::Use(P(self.parse_use_tree()?));
self.expect(&token::Semi)?;

let prev_span = self.prev_span;
let invalid = keywords::Invalid.ident();
let item = self.mk_item(lo.to(prev_span), invalid, item_, visibility, attrs);
let span = lo.to(self.prev_span);
let item = self.mk_item(span, keywords::Invalid.ident(), item_, visibility, attrs);
return Ok(Some(item));
}

Expand Down Expand Up @@ -6960,83 +6959,53 @@ impl<'a> Parser<'a> {
}))
}

/// `{` or `::{` or `*` or `::*`
/// `::{` or `::*` (also `{` or `*` if unprefixed is true)
fn is_import_coupler(&mut self, unprefixed: bool) -> bool {
self.is_import_coupler_inner(&token::OpenDelim(token::Brace), unprefixed) ||
self.is_import_coupler_inner(&token::BinOp(token::Star), unprefixed)
}

fn is_import_coupler_inner(&mut self, token: &token::Token, unprefixed: bool) -> bool {
if self.check(&token::ModSep) {
self.look_ahead(1, |t| t == token)
} else if unprefixed {
self.check(token)
} else {
false
}
/// `::{` or `::*`
fn is_import_coupler(&mut self) -> bool {
self.check(&token::ModSep) &&
self.look_ahead(1, |t| *t == token::OpenDelim(token::Brace) ||
*t == token::BinOp(token::Star))
}

/// Parse UseTree
///
/// USE_TREE = `*` |
/// `{` USE_TREE_LIST `}` |
/// USE_TREE = [`::`] `*` |
/// [`::`] `{` USE_TREE_LIST `}` |
/// PATH `::` `*` |
/// PATH `::` `{` USE_TREE_LIST `}` |
/// PATH [`as` IDENT]
fn parse_use_tree(&mut self) -> PResult<'a, UseTree> {
let lo = self.span;

let mut prefix = ast::Path {
segments: vec![],
span: lo.to(self.span),
};

let kind = if self.is_import_coupler(true) {
// `use *;` or `use ::*;` or `use {...};` `use ::{...};`

// Remove the first `::`
let mut prefix = ast::Path { segments: Vec::new(), span: lo.shrink_to_lo() };
let kind = if self.check(&token::OpenDelim(token::Brace)) ||
self.check(&token::BinOp(token::Star)) ||
self.is_import_coupler() {
// `use *;` or `use ::*;` or `use {...};` or `use ::{...};`
if self.eat(&token::ModSep) {
prefix.segments.push(PathSegment::crate_root(self.prev_span));
prefix.segments.push(PathSegment::crate_root(lo.shrink_to_lo()));
}

if self.eat(&token::BinOp(token::Star)) {
// `use *;`
UseTreeKind::Glob
} else if self.check(&token::OpenDelim(token::Brace)) {
// `use {...};`
UseTreeKind::Nested(self.parse_use_tree_list()?)
} else {
return self.unexpected();
UseTreeKind::Nested(self.parse_use_tree_list()?)
}
} else {
// `use path::...;`
let mut parsed = self.parse_path(PathStyle::Mod)?;

prefix.segments.append(&mut parsed.segments);
prefix.span = prefix.span.to(parsed.span);
// `use path::*;` or `use path::{...};` or `use path;` or `use path as bar;`
prefix = self.parse_path(PathStyle::Mod)?;

if self.eat(&token::ModSep) {
if self.eat(&token::BinOp(token::Star)) {
// `use path::*;`
UseTreeKind::Glob
} else if self.check(&token::OpenDelim(token::Brace)) {
// `use path::{...};`
UseTreeKind::Nested(self.parse_use_tree_list()?)
} else {
return self.unexpected();
UseTreeKind::Nested(self.parse_use_tree_list()?)
}
} else {
// `use path::foo;` or `use path::foo as bar;`
UseTreeKind::Simple(self.parse_rename()?)
}
};

Ok(UseTree {
span: lo.to(self.prev_span),
kind,
prefix,
})
Ok(UseTree { prefix, kind, span: lo.to(self.prev_span) })
}

/// Parse UseTreeKind::Nested(list)
Expand Down

0 comments on commit 636357b

Please sign in to comment.