|
1 | | -use rustc_hir::attrs::WindowsSubsystemKind; |
| 1 | +use rustc_hir::attrs::{CrateType, WindowsSubsystemKind}; |
| 2 | +use rustc_hir::lints::AttributeLintKind; |
| 3 | +use rustc_session::lint::builtin::UNKNOWN_CRATE_TYPES; |
| 4 | +use rustc_span::Symbol; |
| 5 | +use rustc_span::edit_distance::find_best_match_for_name; |
2 | 6 |
|
3 | 7 | use super::prelude::*; |
4 | 8 |
|
@@ -26,6 +30,60 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser { |
26 | 30 | } |
27 | 31 | } |
28 | 32 |
|
| 33 | +pub(crate) struct CrateTypeParser; |
| 34 | + |
| 35 | +impl<S: Stage> CombineAttributeParser<S> for CrateTypeParser { |
| 36 | + const PATH: &[Symbol] = &[sym::crate_type]; |
| 37 | + type Item = CrateType; |
| 38 | + const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::CrateType(items); |
| 39 | + |
| 40 | + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); |
| 41 | + |
| 42 | + const TEMPLATE: AttributeTemplate = template!(NameValueStr: "crate type"); |
| 43 | + |
| 44 | + fn extend( |
| 45 | + cx: &mut AcceptContext<'_, '_, S>, |
| 46 | + args: &ArgParser, |
| 47 | + ) -> impl IntoIterator<Item = Self::Item> { |
| 48 | + // We don't error on malformed `#![crate_type]` when not applied to a crate |
| 49 | + let report_errors = cx.shared.target == Target::Crate; |
| 50 | + |
| 51 | + let ArgParser::NameValue(n) = args else { |
| 52 | + if report_errors { |
| 53 | + cx.expected_name_value(cx.attr_span, None); |
| 54 | + } |
| 55 | + return None; |
| 56 | + }; |
| 57 | + |
| 58 | + let Some(crate_type) = n.value_as_str() else { |
| 59 | + if report_errors { |
| 60 | + cx.expected_string_literal(n.value_span, Some(n.value_as_lit())); |
| 61 | + } |
| 62 | + return None; |
| 63 | + }; |
| 64 | + let Ok(crate_type) = crate_type.try_into() else { |
| 65 | + if report_errors { |
| 66 | + let candidate = find_best_match_for_name( |
| 67 | + &CrateType::all_stable().iter().map(|(name, _)| *name).collect::<Vec<_>>(), |
| 68 | + crate_type, |
| 69 | + None, |
| 70 | + ); |
| 71 | + cx.emit_lint( |
| 72 | + UNKNOWN_CRATE_TYPES, |
| 73 | + AttributeLintKind::CrateTypeUnknown { |
| 74 | + span: n.value_span, |
| 75 | + suggested: candidate, |
| 76 | + }, |
| 77 | + n.value_span, |
| 78 | + ); |
| 79 | + } |
| 80 | + return None; |
| 81 | + }; |
| 82 | + |
| 83 | + Some(crate_type) |
| 84 | + } |
| 85 | +} |
| 86 | + |
29 | 87 | pub(crate) struct RecursionLimitParser; |
30 | 88 |
|
31 | 89 | impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser { |
|
0 commit comments