diff options
| author | Xiretza <xiretza@xiretza.xyz> | 2022-10-20 20:28:24 +0200 |
|---|---|---|
| committer | Xiretza <xiretza@xiretza.xyz> | 2022-10-26 15:04:09 +0200 |
| commit | 368c4a35b9acd7c66400855b9d2d4dfff016220b (patch) | |
| tree | 73d32cca74e6f04b806bcafad5a00787d0570fc6 | |
| parent | 629a414d7ba4caa3ca28b0a46c478e2ecb4c0059 (diff) | |
| download | rust-368c4a35b9acd7c66400855b9d2d4dfff016220b.tar.gz rust-368c4a35b9acd7c66400855b9d2d4dfff016220b.zip | |
Add style= parameter to suggestion attributes
5 files changed, 214 insertions, 18 deletions
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs index 374c795d0a6..aaeb0e1aba9 100644 --- a/compiler/rustc_macros/src/diagnostics/utils.rs +++ b/compiler/rustc_macros/src/diagnostics/utils.rs @@ -472,7 +472,7 @@ pub(super) fn build_suggestion_code( } /// Possible styles for suggestion subdiagnostics. -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq)] pub(super) enum SuggestionKind { /// `#[suggestion]` Normal, @@ -489,10 +489,10 @@ impl FromStr for SuggestionKind { fn from_str(s: &str) -> Result<Self, Self::Err> { match s { - "" => Ok(SuggestionKind::Normal), - "_short" => Ok(SuggestionKind::Short), - "_hidden" => Ok(SuggestionKind::Hidden), - "_verbose" => Ok(SuggestionKind::Verbose), + "normal" => Ok(SuggestionKind::Normal), + "short" => Ok(SuggestionKind::Short), + "hidden" => Ok(SuggestionKind::Hidden), + "verbose" => Ok(SuggestionKind::Verbose), _ => Err(()), } } @@ -515,6 +515,16 @@ impl SuggestionKind { } } } + + fn from_suffix(s: &str) -> Option<Self> { + match s { + "" => Some(SuggestionKind::Normal), + "_short" => Some(SuggestionKind::Short), + "_hidden" => Some(SuggestionKind::Hidden), + "_verbose" => Some(SuggestionKind::Verbose), + _ => None, + } + } } /// Types of subdiagnostics that can be created using attributes @@ -565,6 +575,8 @@ impl SubdiagnosticKind { let name = name.as_str(); let meta = attr.parse_meta()?; + + let mut opt_suggestion_kind = None; let mut kind = match name { "label" => SubdiagnosticKind::Label, "note" => SubdiagnosticKind::Note, @@ -572,18 +584,31 @@ impl SubdiagnosticKind { "warning" => SubdiagnosticKind::Warn, _ => { if let Some(suggestion_kind) = - name.strip_prefix("suggestion").and_then(|s| s.parse().ok()) + name.strip_prefix("suggestion").and_then(SuggestionKind::from_suffix) { + if suggestion_kind != SuggestionKind::Normal { + // Plain `#[suggestion]` can have a `style = "..."` attribute later, so don't set it here + opt_suggestion_kind.set_once(suggestion_kind, attr.path.span().unwrap()); + } + SubdiagnosticKind::Suggestion { - suggestion_kind, + suggestion_kind: SuggestionKind::Normal, applicability: None, code_field: new_code_ident(), code_init: TokenStream::new(), } } else if let Some(suggestion_kind) = - name.strip_prefix("multipart_suggestion").and_then(|s| s.parse().ok()) + name.strip_prefix("multipart_suggestion").and_then(SuggestionKind::from_suffix) { - SubdiagnosticKind::MultipartSuggestion { suggestion_kind, applicability: None } + if suggestion_kind != SuggestionKind::Normal { + // Plain `#[multipart_suggestion]` can have a `style = "..."` attribute later, so don't set it here + opt_suggestion_kind.set_once(suggestion_kind, attr.path.span().unwrap()); + } + + SubdiagnosticKind::MultipartSuggestion { + suggestion_kind: SuggestionKind::Normal, + applicability: None, + } } else { throw_invalid_attr!(attr, &meta); } @@ -682,16 +707,37 @@ impl SubdiagnosticKind { }); applicability.set_once(value, span); } + ( + "style", + SubdiagnosticKind::Suggestion { .. } + | SubdiagnosticKind::MultipartSuggestion { .. }, + ) => { + let Some(value) = string_value else { + invalid_nested_attr(attr, &nested_attr).emit(); + continue; + }; + + let value = value.value().parse().unwrap_or_else(|()| { + span_err(value.span().unwrap(), "invalid suggestion style") + .help("valid styles are `normal`, `short`, `hidden` and `verbose`") + .emit(); + SuggestionKind::Normal + }); + + opt_suggestion_kind.set_once(value, span); + } // Invalid nested attribute (_, SubdiagnosticKind::Suggestion { .. }) => { invalid_nested_attr(attr, &nested_attr) - .help("only `code` and `applicability` are valid nested attributes") + .help( + "only `style`, `code` and `applicability` are valid nested attributes", + ) .emit(); } (_, SubdiagnosticKind::MultipartSuggestion { .. }) => { invalid_nested_attr(attr, &nested_attr) - .help("only `applicability` is a valid nested attributes") + .help("only `style` and `applicability` are valid nested attributes") .emit() } _ => { @@ -701,7 +747,16 @@ impl SubdiagnosticKind { } match kind { - SubdiagnosticKind::Suggestion { ref code_field, ref mut code_init, .. } => { + SubdiagnosticKind::Suggestion { + ref code_field, + ref mut code_init, + ref mut suggestion_kind, + .. + } => { + if let Some(kind) = opt_suggestion_kind.value() { + *suggestion_kind = kind; + } + *code_init = if let Some(init) = code.value() { init } else { @@ -709,11 +764,15 @@ impl SubdiagnosticKind { quote! { let #code_field = std::iter::empty(); } }; } + SubdiagnosticKind::MultipartSuggestion { ref mut suggestion_kind, .. } => { + if let Some(kind) = opt_suggestion_kind.value() { + *suggestion_kind = kind; + } + } SubdiagnosticKind::Label | SubdiagnosticKind::Note | SubdiagnosticKind::Help - | SubdiagnosticKind::Warn - | SubdiagnosticKind::MultipartSuggestion { .. } => {} + | SubdiagnosticKind::Warn => {} } Ok(Some((kind, slug))) diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs index ca77e483d6f..6cd76582795 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs @@ -796,3 +796,10 @@ struct SuggestionsInvalidLiteral { //~^ ERROR `code = "..."`/`code(...)` must contain only string literals sub: Span, } + +#[derive(Diagnostic)] +#[diag(compiletest_example)] +struct SuggestionStyleGood { + #[suggestion(code = "", style = "hidden")] + sub: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr index 859c272b6ba..5a0948e4dcb 100644 --- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr @@ -272,7 +272,7 @@ error: `#[suggestion(nonsense = ...)]` is not a valid attribute LL | #[suggestion(nonsense = "bar")] | ^^^^^^^^^^^^^^^^ | - = help: only `code` and `applicability` are valid nested attributes + = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` --> $DIR/diagnostic-derive.rs:231:5 @@ -286,7 +286,7 @@ error: `#[suggestion(msg = ...)]` is not a valid attribute LL | #[suggestion(msg = "bar")] | ^^^^^^^^^^^ | - = help: only `code` and `applicability` are valid nested attributes + = help: only `style`, `code` and `applicability` are valid nested attributes error: suggestion without `code = "..."` --> $DIR/diagnostic-derive.rs:240:5 diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs index efec85eb52c..9a1a57e2eaf 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.rs @@ -706,3 +706,81 @@ struct BQ { span: Span, r#type: String, } + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "")] +struct SuggestionStyleDefault { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = "short")] +struct SuggestionStyleShort { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = "hidden")] +struct SuggestionStyleHidden { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = "verbose")] +struct SuggestionStyleVerbose { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = "hidden", style = "normal")] +//~^ ERROR specified multiple times +//~| NOTE previously specified here +struct SuggestionStyleTwice { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion_hidden(parser_add_paren, code = "", style = "normal")] +//~^ ERROR specified multiple times +//~| NOTE previously specified here +struct SuggestionStyleTwiceExplicit { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = "foo")] +//~^ ERROR invalid suggestion style +struct SuggestionStyleInvalid1 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style = 42)] +//~^ ERROR `#[suggestion(style = ...)]` is not a valid attribute +struct SuggestionStyleInvalid2 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style)] +//~^ ERROR `#[suggestion(style)]` is not a valid attribute +struct SuggestionStyleInvalid3 { + #[primary_span] + sub: Span, +} + +#[derive(Subdiagnostic)] +#[suggestion(parser_add_paren, code = "", style("foo"))] +//~^ ERROR `#[suggestion(style(...))]` is not a valid attribute +struct SuggestionStyleInvalid4 { + #[primary_span] + sub: Span, +} diff --git a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr index a85a8711eac..d5e136fa40c 100644 --- a/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr +++ b/src/test/ui-fulldeps/session-diagnostic/subdiagnostic-derive.stderr @@ -320,7 +320,7 @@ error: `#[multipart_suggestion(code = ...)]` is not a valid attribute LL | #[multipart_suggestion(parser_add_paren, code = "...", applicability = "machine-applicable")] | ^^^^^^^^^^^^ | - = help: only `applicability` is a valid nested attributes + = help: only `style` and `applicability` are valid nested attributes error: multipart suggestion without any `#[suggestion_part(...)]` fields --> $DIR/subdiagnostic-derive.rs:536:1 @@ -445,6 +445,58 @@ error: `code = "..."`/`code(...)` must contain only string literals LL | #[suggestion_part(code = 3)] | ^^^^^^^^ +error: specified multiple times + --> $DIR/subdiagnostic-derive.rs:739:61 + | +LL | #[suggestion(parser_add_paren, code = "", style = "hidden", style = "normal")] + | ^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive.rs:739:43 + | +LL | #[suggestion(parser_add_paren, code = "", style = "hidden", style = "normal")] + | ^^^^^^^^^^^^^^^^ + +error: specified multiple times + --> $DIR/subdiagnostic-derive.rs:748:50 + | +LL | #[suggestion_hidden(parser_add_paren, code = "", style = "normal")] + | ^^^^^^^^^^^^^^^^ + | +note: previously specified here + --> $DIR/subdiagnostic-derive.rs:748:3 + | +LL | #[suggestion_hidden(parser_add_paren, code = "", style = "normal")] + | ^^^^^^^^^^^^^^^^^ + +error: invalid suggestion style + --> $DIR/subdiagnostic-derive.rs:757:51 + | +LL | #[suggestion(parser_add_paren, code = "", style = "foo")] + | ^^^^^ + | + = help: valid styles are `normal`, `short`, `hidden` and `verbose` + +error: `#[suggestion(style = ...)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:765:43 + | +LL | #[suggestion(parser_add_paren, code = "", style = 42)] + | ^^^^^^^^^^ + +error: `#[suggestion(style)]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:773:43 + | +LL | #[suggestion(parser_add_paren, code = "", style)] + | ^^^^^ + | + = help: a diagnostic slug must be the first argument to the attribute + +error: `#[suggestion(style(...))]` is not a valid attribute + --> $DIR/subdiagnostic-derive.rs:781:43 + | +LL | #[suggestion(parser_add_paren, code = "", style("foo"))] + | ^^^^^^^^^^^^ + error: cannot find attribute `foo` in this scope --> $DIR/subdiagnostic-derive.rs:63:3 | @@ -505,6 +557,6 @@ error[E0425]: cannot find value `slug` in module `rustc_errors::fluent` LL | #[label(slug)] | ^^^^ not found in `rustc_errors::fluent` -error: aborting due to 72 previous errors +error: aborting due to 78 previous errors For more information about this error, try `rustc --explain E0425`. |
