Fix suggestion for the cfg! macro

Signed-off-by: Jonathan Brouwer <jonathantbrouwer@gmail.com>
This commit is contained in:
Jonathan Brouwer
2025-11-04 17:29:16 +01:00
parent e5efc33672
commit f6cdd7eab5
6 changed files with 46 additions and 21 deletions
@@ -2,7 +2,7 @@
use rustc_ast::tokenstream::DelimSpan;
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token};
use rustc_errors::{Applicability, PResult};
use rustc_feature::{AttributeTemplate, Features, template};
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate, Features, template};
use rustc_hir::attrs::CfgEntry;
use rustc_hir::{AttrPath, RustcVersion};
use rustc_parse::parser::{ForceCollect, Parser};
@@ -324,8 +324,8 @@ pub fn parse_cfg_attr(
}) {
Ok(r) => return Some(r),
Err(e) => {
let suggestions =
CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr);
let suggestions = CFG_ATTR_TEMPLATE
.suggestions(AttrSuggestionStyle::Attribute(cfg_attr.style), sym::cfg_attr);
e.with_span_suggestions(
cfg_attr.span,
"must be of the form",
@@ -356,7 +356,8 @@ pub fn parse_cfg_attr(
path: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
description: ParsedDescription::Attribute,
reason,
suggestions: CFG_ATTR_TEMPLATE.suggestions(Some(cfg_attr.style), sym::cfg_attr),
suggestions: CFG_ATTR_TEMPLATE
.suggestions(AttrSuggestionStyle::Attribute(cfg_attr.style), sym::cfg_attr),
});
}
}
+10 -4
View File
@@ -6,7 +6,7 @@
use private::Sealed;
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
use rustc_errors::{Diag, Diagnostic, Level};
use rustc_feature::AttributeTemplate;
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
@@ -638,9 +638,15 @@ pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
}
pub(crate) fn suggestions(&self) -> Vec<String> {
// If the outer and inner spans are equal, we are parsing an attribute from `cfg_attr`,
// So don't display an attribute style in the suggestions
let style = (self.attr_span != self.inner_span).then_some(self.attr_style);
let style = match self.parsed_description {
// If the outer and inner spans are equal, we are parsing an embedded attribute
ParsedDescription::Attribute if self.attr_span == self.inner_span => {
AttrSuggestionStyle::EmbeddedAttribute
}
ParsedDescription::Attribute => AttrSuggestionStyle::Attribute(self.attr_style),
ParsedDescription::Macro => AttrSuggestionStyle::Macro,
};
self.template.suggestions(style, &self.attr_path)
}
}
+24 -7
View File
@@ -132,28 +132,45 @@ pub struct AttributeTemplate {
pub docs: Option<&'static str>,
}
pub enum AttrSuggestionStyle {
/// The suggestion is styled for a normal attribute.
/// The `AttrStyle` determines whether this is an inner or outer attribute.
Attribute(AttrStyle),
/// The suggestion is styled for an attribute embedded into another attribute.
/// For example, attributes inside `#[cfg_attr(true, attr(...)]`.
EmbeddedAttribute,
/// The suggestion is styled for macros that are parsed with attribute parsers.
/// For example, the `cfg!(predicate)` macro.
Macro,
}
impl AttributeTemplate {
pub fn suggestions(
&self,
style: Option<AttrStyle>,
style: AttrSuggestionStyle,
name: impl std::fmt::Display,
) -> Vec<String> {
let mut suggestions = vec![];
let (start, end) = match style {
Some(AttrStyle::Outer) => ("#[", "]"),
Some(AttrStyle::Inner) => ("#![", "]"),
None => ("", ""),
let (start, macro_call, end) = match style {
AttrSuggestionStyle::Attribute(AttrStyle::Outer) => ("#[", "", "]"),
AttrSuggestionStyle::Attribute(AttrStyle::Inner) => ("#![", "", "]"),
AttrSuggestionStyle::Macro => ("", "!", ""),
AttrSuggestionStyle::EmbeddedAttribute => ("", "", ""),
};
let mut suggestions = vec![];
if self.word {
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
suggestions.push(format!("{start}{name}{end}"));
}
if let Some(descr) = self.list {
for descr in descr {
suggestions.push(format!("{start}{name}({descr}){end}"));
suggestions.push(format!("{start}{name}{macro_call}({descr}){end}"));
}
}
suggestions.extend(self.one_of.iter().map(|&word| format!("{start}{name}({word}){end}")));
if let Some(descr) = self.name_value_str {
debug_assert!(macro_call.is_empty(), "Macro suggestions use list style");
for descr in descr {
suggestions.push(format!("{start}{name} = \"{descr}\"{end}"));
}
+4 -3
View File
@@ -135,9 +135,10 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
pub use accepted::ACCEPTED_LANG_FEATURES;
pub use builtin_attrs::{
AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, encode_cross_crate,
find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute, is_valid_for_get_attr,
AttrSuggestionStyle, AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate,
AttributeType, BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg,
encode_cross_crate, find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute,
is_valid_for_get_attr,
};
pub use removed::REMOVED_LANG_FEATURES;
pub use unstable::{
+2 -2
View File
@@ -11,7 +11,7 @@ LL | cfg!(123);
| ^^^^^---^
| | |
| | expected a valid identifier here
| help: must be of the form: `cfg(predicate)`
| help: must be of the form: `cfg!(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
@@ -22,7 +22,7 @@ LL | cfg!(foo = 123);
| ^^^^^^^^^^^---^
| | |
| | expected a string literal here
| help: must be of the form: `cfg(predicate)`
| help: must be of the form: `cfg!(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>
+1 -1
View File
@@ -5,7 +5,7 @@ LL | if cfg!(not()) { }
| ^^^^^^^^--^
| | |
| | expected a single argument here
| help: must be of the form: `cfg(predicate)`
| help: must be of the form: `cfg!(predicate)`
|
= note: for more information, visit <https://doc.rust-lang.org/reference/conditional-compilation.html#the-cfg-attribute>