mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-22 14:55:26 +00:00
Migrate "expected identifier" diagnostics to diagnostic structs
This commit is contained in:
parent
21b5194a3a
commit
7507ee29fc
@ -290,3 +290,19 @@ parser_inner_doc_comment_not_permitted = expected outer doc comment
|
||||
.suggestion = you might have meant to write a regular comment
|
||||
.label_does_not_annotate_this = the inner doc comment doesn't annotate this {$item}
|
||||
.sugg_change_inner_to_outer = to annotate the {$item}, change the doc comment from inner to outer style
|
||||
|
||||
parser_expected_identifier_found_reserved_identifier_str = expected identifier, found reserved identifier `{$token_str}`
|
||||
parser_expected_identifier_found_keyword_str = expected identifier, found keyword `{$token_str}`
|
||||
parser_expected_identifier_found_reserved_keyword_str = expected identifier, found reserved keyword `{$token_str}`
|
||||
parser_expected_identifier_found_doc_comment_str = expected identifier, found doc comment `{$token_str}`
|
||||
parser_expected_identifier_found_str = expected identifier, found `{$token_str}`
|
||||
|
||||
parser_expected_identifier_found_reserved_identifier = expected identifier, found reserved identifier
|
||||
parser_expected_identifier_found_keyword = expected identifier, found keyword
|
||||
parser_expected_identifier_found_reserved_keyword = expected identifier, found reserved keyword
|
||||
parser_expected_identifier_found_doc_comment = expected identifier, found doc comment
|
||||
parser_expected_identifier = expected identifier
|
||||
|
||||
parser_sugg_escape_to_use_as_identifier = escape `{$ident_name}` to use it as an identifier
|
||||
|
||||
parser_sugg_remove_comma = remove this comma
|
||||
|
@ -1,9 +1,11 @@
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_errors::{fluent, AddToDiagnostic, Applicability, EmissionGuarantee, IntoDiagnostic};
|
||||
use rustc_macros::{Diagnostic, Subdiagnostic};
|
||||
use rustc_session::errors::ExprParenthesesNeeded;
|
||||
use rustc_span::symbol::Ident;
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
use crate::parser::{TokenDescription, TokenDescriptionKind};
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(parser::maybe_report_ambiguous_plus)]
|
||||
pub(crate) struct AmbiguousPlus {
|
||||
@ -870,3 +872,94 @@ pub(crate) struct InvalidMetaItem {
|
||||
pub span: Span,
|
||||
pub token: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion_verbose(
|
||||
parser::sugg_escape_to_use_as_identifier,
|
||||
applicability = "maybe-incorrect",
|
||||
code = "r#"
|
||||
)]
|
||||
pub(crate) struct SuggEscapeToUseAsIdentifier {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
pub ident_name: String,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[suggestion(parser::sugg_remove_comma, applicability = "machine-applicable", code = "")]
|
||||
pub(crate) struct SuggRemoveComma {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum ExpectedIdentifierFound {
|
||||
#[label(parser::expected_identifier_found_reserved_identifier)]
|
||||
ReservedIdentifier(#[primary_span] Span),
|
||||
#[label(parser::expected_identifier_found_keyword)]
|
||||
Keyword(#[primary_span] Span),
|
||||
#[label(parser::expected_identifier_found_reserved_keyword)]
|
||||
ReservedKeyword(#[primary_span] Span),
|
||||
#[label(parser::expected_identifier_found_doc_comment)]
|
||||
DocComment(#[primary_span] Span),
|
||||
#[label(parser::expected_identifier)]
|
||||
Other(#[primary_span] Span),
|
||||
}
|
||||
|
||||
impl ExpectedIdentifierFound {
|
||||
pub fn new(token_descr_kind: Option<TokenDescriptionKind>, span: Span) -> Self {
|
||||
(match token_descr_kind {
|
||||
Some(TokenDescriptionKind::ReservedIdentifier) => {
|
||||
ExpectedIdentifierFound::ReservedIdentifier
|
||||
}
|
||||
Some(TokenDescriptionKind::Keyword) => ExpectedIdentifierFound::Keyword,
|
||||
Some(TokenDescriptionKind::ReservedKeyword) => ExpectedIdentifierFound::ReservedKeyword,
|
||||
Some(TokenDescriptionKind::DocComment) => ExpectedIdentifierFound::DocComment,
|
||||
None => ExpectedIdentifierFound::Other,
|
||||
})(span)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ExpectedIdentifier {
|
||||
pub span: Span,
|
||||
pub token_descr: TokenDescription,
|
||||
pub suggest_raw: Option<SuggEscapeToUseAsIdentifier>,
|
||||
pub suggest_remove_comma: Option<SuggRemoveComma>,
|
||||
}
|
||||
|
||||
impl<'a, G: EmissionGuarantee> IntoDiagnostic<'a, G> for ExpectedIdentifier {
|
||||
fn into_diagnostic(
|
||||
self,
|
||||
handler: &'a rustc_errors::Handler,
|
||||
) -> rustc_errors::DiagnosticBuilder<'a, G> {
|
||||
let mut diag = handler.struct_diagnostic(match self.token_descr.kind {
|
||||
Some(TokenDescriptionKind::ReservedIdentifier) => {
|
||||
fluent::parser::expected_identifier_found_reserved_identifier_str
|
||||
}
|
||||
Some(TokenDescriptionKind::Keyword) => {
|
||||
fluent::parser::expected_identifier_found_keyword_str
|
||||
}
|
||||
Some(TokenDescriptionKind::ReservedKeyword) => {
|
||||
fluent::parser::expected_identifier_found_reserved_keyword_str
|
||||
}
|
||||
Some(TokenDescriptionKind::DocComment) => {
|
||||
fluent::parser::expected_identifier_found_doc_comment_str
|
||||
}
|
||||
None => fluent::parser::expected_identifier_found_str,
|
||||
});
|
||||
diag.set_span(self.span);
|
||||
diag.set_arg("token_str", self.token_descr.name);
|
||||
|
||||
if let Some(sugg) = self.suggest_raw {
|
||||
sugg.add_to_diagnostic(&mut diag);
|
||||
}
|
||||
|
||||
ExpectedIdentifierFound::new(self.token_descr.kind, self.span).add_to_diagnostic(&mut diag);
|
||||
|
||||
if let Some(sugg) = self.suggest_remove_comma {
|
||||
sugg.add_to_diagnostic(&mut diag);
|
||||
}
|
||||
|
||||
diag
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,9 @@ use super::{
|
||||
TokenExpectType, TokenType,
|
||||
};
|
||||
use crate::errors::{
|
||||
AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, InInTypo, IncorrectAwait,
|
||||
IncorrectSemicolon, IncorrectUseOfAwait, UseEqInstead,
|
||||
AmbiguousPlus, BadQPathStage2, BadTypePlus, BadTypePlusSub, ExpectedIdentifier, InInTypo,
|
||||
IncorrectAwait, IncorrectSemicolon, IncorrectUseOfAwait, SuggEscapeToUseAsIdentifier,
|
||||
SuggRemoveComma, UseEqInstead,
|
||||
};
|
||||
|
||||
use crate::lexer::UnmatchedBrace;
|
||||
@ -23,7 +24,7 @@ use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::{
|
||||
fluent, Applicability, DiagnosticBuilder, DiagnosticMessage, Handler, MultiSpan, PResult,
|
||||
};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed};
|
||||
use rustc_errors::{pluralize, struct_span_err, Diagnostic, ErrorGuaranteed, IntoDiagnostic};
|
||||
use rustc_span::source_map::Spanned;
|
||||
use rustc_span::symbol::{kw, sym, Ident};
|
||||
use rustc_span::{Span, SpanSnippetError, DUMMY_SP};
|
||||
@ -285,10 +286,6 @@ impl<'a> Parser<'a> {
|
||||
}
|
||||
|
||||
pub(super) fn expected_ident_found(&self) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
|
||||
let mut err = self.struct_span_err(
|
||||
self.token.span,
|
||||
&format!("expected identifier, found {}", super::token_descr(&self.token)),
|
||||
);
|
||||
let valid_follow = &[
|
||||
TokenKind::Eq,
|
||||
TokenKind::Colon,
|
||||
@ -300,34 +297,33 @@ impl<'a> Parser<'a> {
|
||||
TokenKind::CloseDelim(Delimiter::Brace),
|
||||
TokenKind::CloseDelim(Delimiter::Parenthesis),
|
||||
];
|
||||
match self.token.ident() {
|
||||
let suggest_raw = match self.token.ident() {
|
||||
Some((ident, false))
|
||||
if ident.is_raw_guess()
|
||||
&& self.look_ahead(1, |t| valid_follow.contains(&t.kind)) =>
|
||||
{
|
||||
err.span_suggestion_verbose(
|
||||
ident.span.shrink_to_lo(),
|
||||
&format!("escape `{}` to use it as an identifier", ident.name),
|
||||
"r#",
|
||||
Applicability::MaybeIncorrect,
|
||||
);
|
||||
Some(SuggEscapeToUseAsIdentifier {
|
||||
span: ident.span.shrink_to_lo(),
|
||||
ident_name: ident.name.to_string(),
|
||||
})
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
if let Some(token_descr) = super::token_descr_opt(&self.token) {
|
||||
err.span_label(self.token.span, format!("expected identifier, found {}", token_descr));
|
||||
} else {
|
||||
err.span_label(self.token.span, "expected identifier");
|
||||
_ => None,
|
||||
};
|
||||
|
||||
let suggest_remove_comma =
|
||||
if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) {
|
||||
err.span_suggestion(
|
||||
self.token.span,
|
||||
"remove this comma",
|
||||
"",
|
||||
Applicability::MachineApplicable,
|
||||
);
|
||||
}
|
||||
}
|
||||
err
|
||||
Some(SuggRemoveComma { span: self.token.span })
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let err = ExpectedIdentifier {
|
||||
span: self.token.span,
|
||||
token_descr: super::token_descr_struct(&self.token),
|
||||
suggest_raw,
|
||||
suggest_remove_comma,
|
||||
};
|
||||
err.into_diagnostic(&self.sess.span_diagnostic)
|
||||
}
|
||||
|
||||
pub(super) fn expected_one_of_not_found(
|
||||
|
@ -410,22 +410,44 @@ pub enum FollowedByType {
|
||||
No,
|
||||
}
|
||||
|
||||
fn token_descr_opt(token: &Token) -> Option<&'static str> {
|
||||
Some(match token.kind {
|
||||
_ if token.is_special_ident() => "reserved identifier",
|
||||
_ if token.is_used_keyword() => "keyword",
|
||||
_ if token.is_unused_keyword() => "reserved keyword",
|
||||
token::DocComment(..) => "doc comment",
|
||||
_ => return None,
|
||||
})
|
||||
#[derive(Clone, Copy, PartialEq, Eq)]
|
||||
pub enum TokenDescriptionKind {
|
||||
ReservedIdentifier,
|
||||
Keyword,
|
||||
ReservedKeyword,
|
||||
DocComment,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq)]
|
||||
pub struct TokenDescription {
|
||||
pub kind: Option<TokenDescriptionKind>,
|
||||
pub name: String,
|
||||
}
|
||||
|
||||
pub(super) fn token_descr_struct(token: &Token) -> TokenDescription {
|
||||
let kind = match token.kind {
|
||||
_ if token.is_special_ident() => Some(TokenDescriptionKind::ReservedIdentifier),
|
||||
_ if token.is_used_keyword() => Some(TokenDescriptionKind::Keyword),
|
||||
_ if token.is_unused_keyword() => Some(TokenDescriptionKind::ReservedKeyword),
|
||||
token::DocComment(..) => Some(TokenDescriptionKind::DocComment),
|
||||
_ => None,
|
||||
};
|
||||
let name = pprust::token_to_string(token).to_string();
|
||||
|
||||
TokenDescription { kind, name }
|
||||
}
|
||||
|
||||
pub(super) fn token_descr(token: &Token) -> String {
|
||||
let token_str = pprust::token_to_string(token);
|
||||
match token_descr_opt(token) {
|
||||
Some(prefix) => format!("{} `{}`", prefix, token_str),
|
||||
_ => format!("`{}`", token_str),
|
||||
}
|
||||
let TokenDescription { kind, name } = token_descr_struct(token);
|
||||
|
||||
let kind = kind.map(|kind| match kind {
|
||||
TokenDescriptionKind::ReservedIdentifier => "reserved identifier",
|
||||
TokenDescriptionKind::Keyword => "keyword",
|
||||
TokenDescriptionKind::ReservedKeyword => "reserved keyword",
|
||||
TokenDescriptionKind::DocComment => "doc comment",
|
||||
});
|
||||
|
||||
if let Some(kind) = kind { format!("{} `{}`", kind, name) } else { format!("`{}`", name) }
|
||||
}
|
||||
|
||||
impl<'a> Parser<'a> {
|
||||
|
Loading…
Reference in New Issue
Block a user