recover wrong-cased uses (Use, USE, etc)

This commit is contained in:
Maybe Waffle 2022-07-29 23:06:13 +04:00
parent de341fe668
commit 3694429d09
5 changed files with 77 additions and 3 deletions

View File

@ -143,8 +143,15 @@ fn parse_item_common_(
let lo = self.token.span;
let vis = self.parse_visibility(FollowedByType::No)?;
let mut def = self.parse_defaultness();
let kind =
self.parse_item_kind(&mut attrs, mac_allowed, lo, &vis, &mut def, fn_parse_mode)?;
let kind = self.parse_item_kind(
&mut attrs,
mac_allowed,
lo,
&vis,
&mut def,
fn_parse_mode,
false,
)?;
if let Some((ident, kind)) = kind {
self.error_on_unconsumed_default(def, &kind);
let span = lo.to(self.prev_token.span);
@ -205,11 +212,12 @@ fn parse_item_kind(
vis: &Visibility,
def: &mut Defaultness,
fn_parse_mode: FnParseMode,
kw_case_insensitive: bool,
) -> PResult<'a, Option<ItemInfo>> {
let def_final = def == &Defaultness::Final;
let mut def = || mem::replace(def, Defaultness::Final);
let info = if self.eat_keyword(kw::Use) {
let info = if self.eat_keyword_case(kw::Use, kw_case_insensitive) {
self.parse_use_item()?
} else if self.check_fn_front_matter(def_final) {
// FUNCTION ITEM
@ -286,6 +294,17 @@ fn parse_item_kind(
} else if self.isnt_macro_invocation() && vis.kind.is_pub() {
self.recover_missing_kw_before_item()?;
return Ok(None);
} else if self.isnt_macro_invocation() && !kw_case_insensitive {
// Recover wrong cased keywords
return self.parse_item_kind(
attrs,
macros_allowed,
lo,
vis,
&mut def(),
fn_parse_mode,
true,
);
} else if macros_allowed && self.check_path() {
// MACRO INVOCATION ITEM
(Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?)))

View File

@ -616,6 +616,33 @@ pub fn eat_keyword(&mut self, kw: Symbol) -> bool {
}
}
/// Eats a keyword, optionally ignoring the case.
/// If the case differs (and is ignored) an error is issued.
/// This is useful for recovery.
fn eat_keyword_case(&mut self, kw: Symbol, case_insensitive: bool) -> bool {
if self.eat_keyword(kw) {
return true;
}
if case_insensitive
&& let Some((ident, /* is_raw */ false)) = self.token.ident()
&& ident.as_str().to_lowercase() == kw.as_str().to_lowercase() {
self
.struct_span_err(ident.span, format!("keyword `{kw}` is written in a wrong case"))
.span_suggestion(
ident.span,
"write it in the correct case",
kw,
Applicability::MachineApplicable
).emit();
self.bump();
return true;
}
false
}
fn eat_keyword_noexpect(&mut self, kw: Symbol) -> bool {
if self.token.is_keyword(kw) {
self.bump();

View File

@ -0,0 +1,7 @@
// run-rustfix
#![allow(unused_imports)]
fn main() {}
use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case
use std::ptr::write; //~ ERROR keyword `use` is written in a wrong case

View File

@ -0,0 +1,7 @@
// run-rustfix
#![allow(unused_imports)]
fn main() {}
Use std::ptr::read; //~ ERROR keyword `use` is written in a wrong case
USE std::ptr::write; //~ ERROR keyword `use` is written in a wrong case

View File

@ -0,0 +1,14 @@
error: keyword `use` is written in a wrong case
--> $DIR/item-kw-case-mismatch.rs:6:1
|
LL | Use std::ptr::read;
| ^^^ help: write it in the correct case (notice the capitalization): `use`
error: keyword `use` is written in a wrong case
--> $DIR/item-kw-case-mismatch.rs:7:1
|
LL | USE std::ptr::write;
| ^^^ help: write it in the correct case: `use`
error: aborting due to 2 previous errors