diff options
Diffstat (limited to 'compiler/rustc_attr_parsing/src/attributes/confusables.rs')
| -rw-r--r-- | compiler/rustc_attr_parsing/src/attributes/confusables.rs | 65 |
1 files changed, 51 insertions, 14 deletions
diff --git a/compiler/rustc_attr_parsing/src/attributes/confusables.rs b/compiler/rustc_attr_parsing/src/attributes/confusables.rs index 2ced759fd88..6cff952fcf2 100644 --- a/compiler/rustc_attr_parsing/src/attributes/confusables.rs +++ b/compiler/rustc_attr_parsing/src/attributes/confusables.rs @@ -1,21 +1,58 @@ -//! Parsing and validation of builtin attributes +use rustc_attr_data_structures::AttributeKind; +use rustc_span::{Span, Symbol, sym}; +use thin_vec::ThinVec; -use rustc_ast::MetaItemInner; -use rustc_ast::attr::AttributeExt; -use rustc_span::Symbol; +use super::{AcceptMapping, AttributeParser}; +use crate::context::FinalizeContext; +use crate::session_diagnostics; -/// Read the content of a `rustc_confusables` attribute, and return the list of candidate names. -pub fn parse_confusables(attr: &impl AttributeExt) -> Option<Vec<Symbol>> { - let metas = attr.meta_item_list()?; +#[derive(Default)] +pub(crate) struct ConfusablesParser { + confusables: ThinVec<Symbol>, + first_span: Option<Span>, +} + +impl AttributeParser for ConfusablesParser { + const ATTRIBUTES: AcceptMapping<Self> = &[(&[sym::rustc_confusables], |this, cx, args| { + let Some(list) = args.list() else { + // FIXME(jdonszelmann): error when not a list? Bring validation code here. + // NOTE: currently subsequent attributes are silently ignored using + // tcx.get_attr(). + return; + }; + + if list.is_empty() { + cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span }); + } + + for param in list.mixed() { + let span = param.span(); - let mut candidates = Vec::new(); + let Some(lit) = param.lit() else { + cx.emit_err(session_diagnostics::IncorrectMetaItem { + span, + suggestion: Some(session_diagnostics::IncorrectMetaItemSuggestion { + lo: span.shrink_to_lo(), + hi: span.shrink_to_hi(), + }), + }); + continue; + }; - for meta in metas { - let MetaItemInner::Lit(meta_lit) = meta else { + this.confusables.push(lit.symbol); + } + + this.first_span.get_or_insert(cx.attr_span); + })]; + + fn finalize(self, _cx: &FinalizeContext<'_>) -> Option<AttributeKind> { + if self.confusables.is_empty() { return None; - }; - candidates.push(meta_lit.symbol); - } + } - Some(candidates) + Some(AttributeKind::Confusables { + symbols: self.confusables, + first_span: self.first_span.unwrap(), + }) + } } |
