syntax: cleanup parse_visibility.

This commit is contained in:
Mazdak Farrokhzad 2019-09-30 06:42:56 +02:00
parent 5b80ead489
commit 66bf323a3b

View file

@ -1417,66 +1417,82 @@ impl<'a> Parser<'a> {
// `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`. // `()` or a tuple might be allowed. For example, `struct Struct(pub (), pub (usize));`.
// Because of this, we only `bump` the `(` if we're assured it is appropriate to do so // Because of this, we only `bump` the `(` if we're assured it is appropriate to do so
// by the following tokens. // by the following tokens.
if self.is_keyword_ahead(1, &[kw::Crate]) && if self.is_keyword_ahead(1, &[kw::Crate])
self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)` && self.look_ahead(2, |t| t != &token::ModSep) // account for `pub(crate::foo)`
{ {
// `pub(crate)` return self.parse_vis_pub_crate(lo);
} else if self.is_keyword_ahead(1, &[kw::In]) {
return self.parse_vis_pub_in(lo);
} else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren))
&& self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower])
{
return self.parse_vis_self_super(lo);
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct.
self.recover_incorrect_vis_restriction()?;
// Emit diagnostic, but continue with public visibility.
}
}
Ok(respan(lo, VisibilityKind::Public))
}
/// Parse `pub(crate)`.
fn parse_vis_pub_crate(&mut self, lo: Span) -> PResult<'a, Visibility> {
self.bump(); // `(` self.bump(); // `(`
self.bump(); // `crate` self.bump(); // `crate`
self.expect(&token::CloseDelim(token::Paren))?; // `)` self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan( Ok(respan(
lo.to(self.prev_span), lo.to(self.prev_span),
VisibilityKind::Crate(CrateSugar::PubCrate), VisibilityKind::Crate(CrateSugar::PubCrate),
); ))
return Ok(vis) }
} else if self.is_keyword_ahead(1, &[kw::In]) {
// `pub(in path)` /// Parse `pub(in path)`.
fn parse_vis_pub_in(&mut self, lo: Span) -> PResult<'a, Visibility> {
self.bump(); // `(` self.bump(); // `(`
self.bump(); // `in` self.bump(); // `in`
let path = self.parse_path(PathStyle::Mod)?; // `path` let path = self.parse_path(PathStyle::Mod)?; // `path`
self.expect(&token::CloseDelim(token::Paren))?; // `)` self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path), path: P(path),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
}); }))
return Ok(vis) }
} else if self.look_ahead(2, |t| t == &token::CloseDelim(token::Paren)) &&
self.is_keyword_ahead(1, &[kw::Super, kw::SelfLower]) /// Parse `pub(self)` or `pub(super)`.
{ fn parse_vis_self_super(&mut self, lo: Span) -> PResult<'a, Visibility> {
// `pub(self)` or `pub(super)`
self.bump(); // `(` self.bump(); // `(`
let path = self.parse_path(PathStyle::Mod)?; // `super`/`self` let path = self.parse_path(PathStyle::Mod)?; // `super`/`self`
self.expect(&token::CloseDelim(token::Paren))?; // `)` self.expect(&token::CloseDelim(token::Paren))?; // `)`
let vis = respan(lo.to(self.prev_span), VisibilityKind::Restricted { Ok(respan(lo.to(self.prev_span), VisibilityKind::Restricted {
path: P(path), path: P(path),
id: ast::DUMMY_NODE_ID, id: ast::DUMMY_NODE_ID,
}); }))
return Ok(vis) }
} else if !can_take_tuple { // Provide this diagnostic if this is not a tuple struct
// `pub(something) fn ...` or `struct X { pub(something) y: Z }` /// Recovery for e.g. `pub(something) fn ...` or `struct X { pub(something) y: Z }`
fn recover_incorrect_vis_restriction(&mut self) -> PResult<'a, ()> {
self.bump(); // `(` self.bump(); // `(`
let path = self.parse_path(PathStyle::Mod)?;
self.expect(&token::CloseDelim(token::Paren))?; // `)`
let msg = "incorrect visibility restriction"; let msg = "incorrect visibility restriction";
let suggestion = r##"some possible visibility restrictions are: let suggestion = r##"some possible visibility restrictions are:
`pub(crate)`: visible only on the current crate `pub(crate)`: visible only on the current crate
`pub(super)`: visible only in the current module's parent `pub(super)`: visible only in the current module's parent
`pub(in path::to::module)`: visible only on the specified path"##; `pub(in path::to::module)`: visible only on the specified path"##;
let path = self.parse_path(PathStyle::Mod)?;
let sp = path.span; struct_span_err!(self.sess.span_diagnostic, path.span, E0704, "{}", msg)
let help_msg = format!("make this visible only to module `{}` with `in`", path);
self.expect(&token::CloseDelim(token::Paren))?; // `)`
struct_span_err!(self.sess.span_diagnostic, sp, E0704, "{}", msg)
.help(suggestion) .help(suggestion)
.span_suggestion( .span_suggestion(
sp, path.span,
&help_msg, &format!("make this visible only to module `{}` with `in`", path),
format!("in {}", path), format!("in {}", path),
Applicability::MachineApplicable, Applicability::MachineApplicable,
) )
.emit(); // Emit diagnostic, but continue with public visibility. .emit();
}
}
Ok(respan(lo, VisibilityKind::Public)) Ok(())
} }
/// Parses a string as an ABI spec on an extern type or module. Consumes /// Parses a string as an ABI spec on an extern type or module. Consumes