Update to new API, allowing to remove check_doc_cfg.rs file from librustdoc
This commit is contained in:
parent
40907f522d
commit
64aaeacd71
13 changed files with 59 additions and 135 deletions
|
|
@ -2,7 +2,6 @@ use rustc_ast::{LitKind, MetaItem, MetaItemInner, MetaItemKind, MetaItemLit, Nod
|
|||
use rustc_ast_pretty::pprust;
|
||||
use rustc_feature::{Features, GatedCfg, find_gated_cfg};
|
||||
use rustc_hir::RustcVersion;
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{BuiltinLintDiag, Lint};
|
||||
use rustc_session::parse::feature_err;
|
||||
|
|
|
|||
|
|
@ -294,7 +294,7 @@ impl DocParser {
|
|||
cx.expected_identifier(sub_item.path().span());
|
||||
continue;
|
||||
};
|
||||
if let Ok(CfgEntry::NameValue { name, name_span, value, .. }) =
|
||||
if let Ok(CfgEntry::NameValue { name, value, .. }) =
|
||||
super::cfg::parse_name_value(
|
||||
name,
|
||||
sub_item.path().span(),
|
||||
|
|
@ -303,7 +303,14 @@ impl DocParser {
|
|||
cx,
|
||||
)
|
||||
{
|
||||
cfg_hide_show.values.push(CfgInfo { name, name_span, value })
|
||||
cfg_hide_show.values.push(CfgInfo {
|
||||
name,
|
||||
name_span: sub_item.path().span(),
|
||||
// If `value` is `Some`, `a.name_value()` will always return
|
||||
// `Some` as well.
|
||||
value: value
|
||||
.map(|v| (v, a.name_value().unwrap().value_span)),
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
|
|
|
|||
|
|
@ -218,14 +218,7 @@ impl CfgEntry {
|
|||
(
|
||||
Self::NameValue { name: name1, value: value1, .. },
|
||||
Self::NameValue { name: name2, value: value2, .. },
|
||||
) => {
|
||||
name1 == name2
|
||||
&& match (value1, value2) {
|
||||
(Some((a, _)), Some((b, _))) => a == b,
|
||||
(None, None) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
) => name1 == name2 && value1 == value2,
|
||||
(Self::Version(a, _), Self::Version(b, _)) => a == b,
|
||||
_ => false,
|
||||
}
|
||||
|
|
@ -257,7 +250,7 @@ impl fmt::Display for CfgEntry {
|
|||
match value {
|
||||
// We use `as_str` and debug display to have characters escaped and `"`
|
||||
// characters surrounding the string.
|
||||
Some((value, _)) => write!(f, "{name} = {:?}", value.as_str()),
|
||||
Some(value) => write!(f, "{name} = {:?}", value.as_str()),
|
||||
None => write!(f, "{name}"),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,6 +13,9 @@ fn main() {
|
|||
println!("cargo:rustc-cfg=netbsd10");
|
||||
}
|
||||
|
||||
// Needed for `#![doc(auto_cfg(hide(no_global_oom_handling)))]` attribute.
|
||||
println!("cargo::rustc-check-cfg=cfg(no_global_oom_handling)");
|
||||
|
||||
println!("cargo:rustc-check-cfg=cfg(restricted_std)");
|
||||
if target_os == "linux"
|
||||
|| target_os == "android"
|
||||
|
|
|
|||
|
|
@ -140,12 +140,7 @@ impl Cfg {
|
|||
if exclude.contains(&NameValueCfg::new(name)) {
|
||||
Ok(None)
|
||||
} else {
|
||||
Ok(Some(Cfg(CfgEntry::NameValue {
|
||||
name,
|
||||
value: None,
|
||||
name_span: DUMMY_SP,
|
||||
span: DUMMY_SP,
|
||||
})))
|
||||
Ok(Some(Cfg(CfgEntry::NameValue { name, value: None, span: DUMMY_SP })))
|
||||
}
|
||||
}
|
||||
MetaItemKind::NameValue(ref lit) => match lit.kind {
|
||||
|
|
@ -155,8 +150,7 @@ impl Cfg {
|
|||
} else {
|
||||
Ok(Some(Cfg(CfgEntry::NameValue {
|
||||
name,
|
||||
value: Some((value, DUMMY_SP)),
|
||||
name_span: DUMMY_SP,
|
||||
value: Some(value),
|
||||
span: DUMMY_SP,
|
||||
})))
|
||||
}
|
||||
|
|
@ -226,9 +220,7 @@ impl Cfg {
|
|||
CfgEntry::Any(sub_cfgs, _) => {
|
||||
sub_cfgs.iter().any(|sub_cfg| cfg_matches(sub_cfg, psess))
|
||||
}
|
||||
CfgEntry::NameValue { name, value, .. } => {
|
||||
psess.config.contains(&(*name, value.clone().map(|(s, _)| s)))
|
||||
}
|
||||
CfgEntry::NameValue { name, value, .. } => psess.config.contains(&(*name, *value)),
|
||||
CfgEntry::Version(..) => {
|
||||
// FIXME: should be handled.
|
||||
false
|
||||
|
|
@ -497,7 +489,7 @@ impl Display<'_> {
|
|||
sub_cfgs
|
||||
.iter()
|
||||
.map(|sub_cfg| {
|
||||
if let CfgEntry::NameValue { value: Some((feat, _)), .. } = sub_cfg
|
||||
if let CfgEntry::NameValue { value: Some(feat), .. } = sub_cfg
|
||||
&& short_longhand
|
||||
{
|
||||
Either::Left(self.code_wrappers().wrap(feat))
|
||||
|
|
@ -557,7 +549,7 @@ impl fmt::Display for Display<'_> {
|
|||
(sym::unix, None) => "Unix",
|
||||
(sym::windows, None) => "Windows",
|
||||
(sym::debug_assertions, None) => "debug-assertions enabled",
|
||||
(sym::target_os, Some((os, _))) => match os.as_str() {
|
||||
(sym::target_os, Some(os)) => match os.as_str() {
|
||||
"android" => "Android",
|
||||
"cygwin" => "Cygwin",
|
||||
"dragonfly" => "DragonFly BSD",
|
||||
|
|
@ -582,7 +574,7 @@ impl fmt::Display for Display<'_> {
|
|||
"visionos" => "visionOS",
|
||||
_ => "",
|
||||
},
|
||||
(sym::target_arch, Some((arch, _))) => match arch.as_str() {
|
||||
(sym::target_arch, Some(arch)) => match arch.as_str() {
|
||||
"aarch64" => "AArch64",
|
||||
"arm" => "ARM",
|
||||
"loongarch32" => "LoongArch LA32",
|
||||
|
|
@ -605,14 +597,14 @@ impl fmt::Display for Display<'_> {
|
|||
"x86_64" => "x86-64",
|
||||
_ => "",
|
||||
},
|
||||
(sym::target_vendor, Some((vendor, _))) => match vendor.as_str() {
|
||||
(sym::target_vendor, Some(vendor)) => match vendor.as_str() {
|
||||
"apple" => "Apple",
|
||||
"pc" => "PC",
|
||||
"sun" => "Sun",
|
||||
"fortanix" => "Fortanix",
|
||||
_ => "",
|
||||
},
|
||||
(sym::target_env, Some((env, _))) => match env.as_str() {
|
||||
(sym::target_env, Some(env)) => match env.as_str() {
|
||||
"gnu" => "GNU",
|
||||
"msvc" => "MSVC",
|
||||
"musl" => "musl",
|
||||
|
|
@ -621,20 +613,20 @@ impl fmt::Display for Display<'_> {
|
|||
"sgx" => "SGX",
|
||||
_ => "",
|
||||
},
|
||||
(sym::target_endian, Some((endian, _))) => {
|
||||
(sym::target_endian, Some(endian)) => {
|
||||
return write!(fmt, "{endian}-endian");
|
||||
}
|
||||
(sym::target_pointer_width, Some((bits, _))) => {
|
||||
(sym::target_pointer_width, Some(bits)) => {
|
||||
return write!(fmt, "{bits}-bit");
|
||||
}
|
||||
(sym::target_feature, Some((feat, _))) => match self.1 {
|
||||
(sym::target_feature, Some(feat)) => match self.1 {
|
||||
Format::LongHtml => {
|
||||
return write!(fmt, "target feature <code>{feat}</code>");
|
||||
}
|
||||
Format::LongPlain => return write!(fmt, "target feature `{feat}`"),
|
||||
Format::ShortHtml => return write!(fmt, "<code>{feat}</code>"),
|
||||
},
|
||||
(sym::feature, Some((feat, _))) => match self.1 {
|
||||
(sym::feature, Some(feat)) => match self.1 {
|
||||
Format::LongHtml => {
|
||||
return write!(fmt, "crate feature <code>{feat}</code>");
|
||||
}
|
||||
|
|
@ -647,9 +639,7 @@ impl fmt::Display for Display<'_> {
|
|||
fmt.write_str(human_readable)
|
||||
} else {
|
||||
let value = value
|
||||
.map(|(v, _)| {
|
||||
fmt::from_fn(move |f| write!(f, "={}", self.1.escape(v.as_str())))
|
||||
})
|
||||
.map(|v| fmt::from_fn(move |f| write!(f, "={}", self.1.escape(v.as_str()))))
|
||||
.maybe_display();
|
||||
self.code_wrappers()
|
||||
.wrap(format_args!("{}{value}", self.1.escape(name.as_str())))
|
||||
|
|
@ -684,9 +674,7 @@ impl NameValueCfg {
|
|||
impl<'a> From<&'a CfgEntry> for NameValueCfg {
|
||||
fn from(cfg: &'a CfgEntry) -> Self {
|
||||
match cfg {
|
||||
CfgEntry::NameValue { name, value, .. } => {
|
||||
NameValueCfg { name: *name, value: (*value).map(|(v, _)| v) }
|
||||
}
|
||||
CfgEntry::NameValue { name, value, .. } => NameValueCfg { name: *name, value: *value },
|
||||
_ => NameValueCfg { name: sym::empty, value: None },
|
||||
}
|
||||
}
|
||||
|
|
@ -886,8 +874,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
|
|||
for (feature, _) in features {
|
||||
cfg_info.current_cfg &= Cfg(CfgEntry::NameValue {
|
||||
name: sym::target_feature,
|
||||
value: Some((*feature, DUMMY_SP)),
|
||||
name_span: DUMMY_SP,
|
||||
value: Some(*feature),
|
||||
span: DUMMY_SP,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,12 +12,7 @@ fn word_cfg(name: &str) -> Cfg {
|
|||
}
|
||||
|
||||
fn word_cfg_e(name: &str) -> CfgEntry {
|
||||
CfgEntry::NameValue {
|
||||
name: Symbol::intern(name),
|
||||
name_span: DUMMY_SP,
|
||||
value: None,
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
CfgEntry::NameValue { name: Symbol::intern(name), value: None, span: DUMMY_SP }
|
||||
}
|
||||
|
||||
fn name_value_cfg(name: &str, value: &str) -> Cfg {
|
||||
|
|
@ -27,8 +22,8 @@ fn name_value_cfg(name: &str, value: &str) -> Cfg {
|
|||
fn name_value_cfg_e(name: &str, value: &str) -> CfgEntry {
|
||||
CfgEntry::NameValue {
|
||||
name: Symbol::intern(name),
|
||||
name_span: DUMMY_SP,
|
||||
value: Some((Symbol::intern(value), DUMMY_SP)),
|
||||
|
||||
value: Some(Symbol::intern(value)),
|
||||
span: DUMMY_SP,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,7 +32,6 @@
|
|||
extern crate rustc_abi;
|
||||
extern crate rustc_ast;
|
||||
extern crate rustc_ast_pretty;
|
||||
extern crate rustc_attr_parsing;
|
||||
extern crate rustc_data_structures;
|
||||
extern crate rustc_driver;
|
||||
extern crate rustc_errors;
|
||||
|
|
|
|||
|
|
@ -1,72 +0,0 @@
|
|||
use rustc_attr_parsing::{ShouldEmit, eval_config_entry};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::{Attribute, HirId};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
|
||||
use super::Pass;
|
||||
use crate::clean::{Attributes, Crate, Item};
|
||||
use crate::core::DocContext;
|
||||
use crate::visit::DocVisitor;
|
||||
|
||||
pub(crate) const CHECK_DOC_CFG: Pass = Pass {
|
||||
name: "check-doc-cfg",
|
||||
run: Some(check_doc_cfg),
|
||||
description: "checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs",
|
||||
};
|
||||
|
||||
pub(crate) fn check_doc_cfg(krate: Crate, cx: &mut DocContext<'_>) -> Crate {
|
||||
let mut checker = DocCfgChecker { cx };
|
||||
checker.visit_crate(&krate);
|
||||
krate
|
||||
}
|
||||
|
||||
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, HirId);
|
||||
|
||||
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
|
||||
fn emit_span_lint(
|
||||
&self,
|
||||
sess: &rustc_session::Session,
|
||||
lint: &'static rustc_lint::Lint,
|
||||
sp: rustc_span::Span,
|
||||
builtin_diag: rustc_lint_defs::BuiltinLintDiag,
|
||||
) {
|
||||
self.0.node_span_lint(lint, self.1, sp, |diag| {
|
||||
rustc_lint::decorate_builtin_lint(sess, Some(self.0), builtin_diag, diag)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
struct DocCfgChecker<'a, 'tcx> {
|
||||
cx: &'a mut DocContext<'tcx>,
|
||||
}
|
||||
|
||||
impl DocCfgChecker<'_, '_> {
|
||||
fn check_attrs(&mut self, attrs: &Attributes, did: LocalDefId) {
|
||||
for attr in &attrs.other_attrs {
|
||||
let Attribute::Parsed(AttributeKind::Doc(d)) = attr else { continue };
|
||||
|
||||
for doc_cfg in &d.cfg {
|
||||
let _ = eval_config_entry(
|
||||
&self.cx.tcx.sess,
|
||||
doc_cfg,
|
||||
&RustdocCfgMatchesLintEmitter(
|
||||
self.cx.tcx,
|
||||
self.cx.tcx.local_def_id_to_hir_id(did),
|
||||
),
|
||||
ShouldEmit::ErrorsAndLints,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DocVisitor<'_> for DocCfgChecker<'_, '_> {
|
||||
fn visit_item(&mut self, item: &'_ Item) {
|
||||
if let Some(Some(local_did)) = item.def_id().map(|did| did.as_local()) {
|
||||
self.check_attrs(&item.attrs, local_did);
|
||||
}
|
||||
|
||||
self.visit_item_recur(item);
|
||||
}
|
||||
}
|
||||
|
|
@ -32,9 +32,6 @@ pub(crate) use self::collect_intra_doc_links::COLLECT_INTRA_DOC_LINKS;
|
|||
mod check_doc_test_visibility;
|
||||
pub(crate) use self::check_doc_test_visibility::CHECK_DOC_TEST_VISIBILITY;
|
||||
|
||||
mod check_doc_cfg;
|
||||
pub(crate) use self::check_doc_cfg::CHECK_DOC_CFG;
|
||||
|
||||
mod collect_trait_impls;
|
||||
pub(crate) use self::collect_trait_impls::COLLECT_TRAIT_IMPLS;
|
||||
|
||||
|
|
@ -75,7 +72,6 @@ pub(crate) enum Condition {
|
|||
|
||||
/// The full list of passes.
|
||||
pub(crate) const PASSES: &[Pass] = &[
|
||||
CHECK_DOC_CFG,
|
||||
CHECK_DOC_TEST_VISIBILITY,
|
||||
PROPAGATE_DOC_CFG,
|
||||
STRIP_ALIASED_NON_LOCAL,
|
||||
|
|
@ -93,7 +89,6 @@ pub(crate) const PASSES: &[Pass] = &[
|
|||
pub(crate) const DEFAULT_PASSES: &[ConditionalPass] = &[
|
||||
ConditionalPass::always(COLLECT_TRAIT_IMPLS),
|
||||
ConditionalPass::always(CHECK_DOC_TEST_VISIBILITY),
|
||||
ConditionalPass::always(CHECK_DOC_CFG),
|
||||
ConditionalPass::always(STRIP_ALIASED_NON_LOCAL),
|
||||
ConditionalPass::always(PROPAGATE_DOC_CFG),
|
||||
ConditionalPass::new(STRIP_HIDDEN, WhenNotDocumentHidden),
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
// Shouldn't lint
|
||||
#[doc(auto_cfg(hide(windows)))]
|
||||
#[doc(auto_cfg(hide(feature = "windows")))]
|
||||
//~^ WARN unexpected `cfg` condition name: `feature`
|
||||
#[doc(auto_cfg(hide(foo)))]
|
||||
//~^ WARN unexpected `cfg` condition name: `foo`
|
||||
pub fn foo() {}
|
||||
|
|
|
|||
|
|
@ -56,5 +56,23 @@ error: expected boolean for `#[doc(auto_cfg = ...)]`
|
|||
LL | #[doc(auto_cfg = "a")]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 6 previous errors; 2 warnings emitted
|
||||
warning: unexpected `cfg` condition name: `feature`
|
||||
--> $DIR/doc-cfg-2.rs:14:21
|
||||
|
|
||||
LL | #[doc(auto_cfg(hide(feature = "windows")))]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(feature, values("windows"))`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-2.rs:16:21
|
||||
|
|
||||
LL | #[doc(auto_cfg(hide(foo)))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
error: aborting due to 6 previous errors; 4 warnings emitted
|
||||
|
||||
|
|
|
|||
|
|
@ -1,8 +1,8 @@
|
|||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:12:12
|
||||
--> $DIR/doc-cfg-check-cfg.rs:15:11
|
||||
|
|
||||
LL | #![doc(cfg(foo))]
|
||||
| ^^^
|
||||
LL | #[doc(cfg(foo))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
|
@ -18,10 +18,10 @@ LL | #[doc(cfg(foo))]
|
|||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:15:11
|
||||
--> $DIR/doc-cfg-check-cfg.rs:12:12
|
||||
|
|
||||
LL | #[doc(cfg(foo))]
|
||||
| ^^^
|
||||
LL | #![doc(cfg(foo))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(foo)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
|
|
|||
|
|
@ -1,5 +1,4 @@
|
|||
Available passes for running rustdoc:
|
||||
check-doc-cfg - checks `#[doc(cfg(...))]` for stability feature and unexpected cfgs
|
||||
check_doc_test_visibility - run various visibility-related lints on doctests
|
||||
propagate-doc-cfg - propagates `#[doc(cfg(...))]` to child items
|
||||
strip-aliased-non-local - strips all non-local private aliased items from the output
|
||||
|
|
@ -15,7 +14,6 @@ calculate-doc-coverage - counts the number of items with and without documentati
|
|||
Default passes for rustdoc:
|
||||
collect-trait-impls
|
||||
check_doc_test_visibility
|
||||
check-doc-cfg
|
||||
strip-aliased-non-local
|
||||
propagate-doc-cfg
|
||||
strip-hidden (when not --document-hidden-items)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue