rustdoc: use custom CfgMatchesLintEmitter to make check-cfg work
This commit is contained in:
parent
93f3db25c0
commit
3fd0265fbb
8 changed files with 95 additions and 19 deletions
|
|
@ -409,12 +409,12 @@ pub(crate) fn merge_attrs(
|
|||
} else {
|
||||
Attributes::from_hir(&both)
|
||||
},
|
||||
extract_cfg_from_attrs(both.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(both.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
|
||||
)
|
||||
} else {
|
||||
(
|
||||
Attributes::from_hir(old_attrs),
|
||||
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(old_attrs.iter(), cx.tcx, None, &cx.cache.hidden_cfg),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -210,6 +210,7 @@ fn generate_item_with_correct_attrs(
|
|||
Cow::Owned(attr) => attr,
|
||||
}),
|
||||
cx.tcx,
|
||||
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
|
||||
&cx.cache.hidden_cfg,
|
||||
);
|
||||
let attrs = Attributes::from_hir_iter(attrs.iter().map(|(attr, did)| (&**attr, *did)), false);
|
||||
|
|
|
|||
|
|
@ -12,8 +12,9 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet};
|
|||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId};
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{BodyId, Mutability};
|
||||
use rustc_hir::{BodyId, HirId, Mutability};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_lint_defs::{BuiltinLintDiag, Lint};
|
||||
use rustc_metadata::rendered_const;
|
||||
use rustc_middle::span_bug;
|
||||
use rustc_middle::ty::fast_reject::SimplifiedType;
|
||||
|
|
@ -477,7 +478,12 @@ impl Item {
|
|||
name,
|
||||
kind,
|
||||
Attributes::from_hir(hir_attrs),
|
||||
extract_cfg_from_attrs(hir_attrs.iter(), cx.tcx, &cx.cache.hidden_cfg),
|
||||
extract_cfg_from_attrs(
|
||||
hir_attrs.iter(),
|
||||
cx.tcx,
|
||||
def_id.as_local().map(|did| cx.tcx.local_def_id_to_hir_id(did)),
|
||||
&cx.cache.hidden_cfg,
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -1033,6 +1039,7 @@ pub(crate) fn hir_attr_lists<'a, I: IntoIterator<Item = &'a hir::Attribute>>(
|
|||
pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute> + Clone>(
|
||||
attrs: I,
|
||||
tcx: TyCtxt<'_>,
|
||||
hir_id: Option<HirId>,
|
||||
hidden_cfg: &FxHashSet<Cfg>,
|
||||
) -> Option<Arc<Cfg>> {
|
||||
let doc_cfg_active = tcx.features().doc_cfg();
|
||||
|
|
@ -1056,6 +1063,32 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
|
|||
.peekable();
|
||||
if doc_cfg.peek().is_some() && doc_cfg_active {
|
||||
let sess = tcx.sess;
|
||||
|
||||
struct RustdocCfgMatchesLintEmitter<'a>(TyCtxt<'a>, Option<HirId>);
|
||||
|
||||
impl<'a> rustc_attr_parsing::CfgMatchesLintEmitter for RustdocCfgMatchesLintEmitter<'a> {
|
||||
fn emit_span_lint(
|
||||
&self,
|
||||
sess: &Session,
|
||||
lint: &'static Lint,
|
||||
sp: rustc_span::Span,
|
||||
builtin_diag: BuiltinLintDiag,
|
||||
) {
|
||||
if let Some(hir_id) = self.1 {
|
||||
self.0.node_span_lint(lint, hir_id, sp, |diag| {
|
||||
rustc_lint::decorate_builtin_lint(
|
||||
sess,
|
||||
Some(self.0),
|
||||
builtin_diag,
|
||||
diag,
|
||||
)
|
||||
});
|
||||
} else {
|
||||
// No HIR id. Probably in another crate. Don't lint.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doc_cfg.fold(Cfg::True, |mut cfg, item| {
|
||||
if let Some(cfg_mi) =
|
||||
item.meta_item().and_then(|item| rustc_expand::config::parse_cfg(item, sess))
|
||||
|
|
@ -1064,7 +1097,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator<Item = &'a hir::Attribute>
|
|||
rustc_attr_parsing::cfg_matches(
|
||||
cfg_mi,
|
||||
tcx.sess,
|
||||
rustc_ast::CRATE_NODE_ID,
|
||||
RustdocCfgMatchesLintEmitter(tcx, hir_id),
|
||||
Some(tcx.features()),
|
||||
);
|
||||
match Cfg::parse(cfg_mi) {
|
||||
|
|
|
|||
|
|
@ -116,9 +116,12 @@ impl HirCollector<'_> {
|
|||
nested: F,
|
||||
) {
|
||||
let ast_attrs = self.tcx.hir_attrs(self.tcx.local_def_id_to_hir_id(def_id));
|
||||
if let Some(ref cfg) =
|
||||
extract_cfg_from_attrs(ast_attrs.iter(), self.tcx, &FxHashSet::default())
|
||||
&& !cfg.matches(&self.tcx.sess.psess)
|
||||
if let Some(ref cfg) = extract_cfg_from_attrs(
|
||||
ast_attrs.iter(),
|
||||
self.tcx,
|
||||
Some(self.tcx.local_def_id_to_hir_id(def_id)),
|
||||
&FxHashSet::default(),
|
||||
) && !cfg.matches(&self.tcx.sess.psess)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
|
|||
12
tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
Normal file
12
tests/rustdoc-ui/doc-cfg-check-cfg.cfg_empty.stderr
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg-check-cfg.rs:13:11
|
||||
|
|
||||
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
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
|
|
@ -1,16 +1,21 @@
|
|||
// Ensure that `doc(cfg())` respects `check-cfg`
|
||||
// Currently not properly working
|
||||
#![feature(doc_cfg)]
|
||||
#![deny(unexpected_cfgs)]
|
||||
|
||||
//@revisions: no_check cfg_empty cfg_foo
|
||||
//@ check-pass
|
||||
//@ no-auto-check-cfg
|
||||
|
||||
//@ revisions: no_check cfg_empty cfg_foo
|
||||
//@[cfg_empty] compile-flags: --check-cfg cfg()
|
||||
//@[cfg_foo] compile-flags: --check-cfg cfg(foo)
|
||||
|
||||
//@[no_check] check-pass
|
||||
//@[cfg_empty] check-pass
|
||||
//@[cfg_empty] known-bug: #138358
|
||||
//@[cfg_foo] check-pass
|
||||
#![feature(doc_cfg)]
|
||||
|
||||
#[doc(cfg(foo))]
|
||||
//[cfg_empty]~^ WARN unexpected `cfg` condition name: `foo`
|
||||
pub fn foo() {}
|
||||
|
||||
pub mod module {
|
||||
#[allow(unexpected_cfgs)]
|
||||
#[doc(cfg(bar))]
|
||||
pub fn bar() {}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,9 @@
|
|||
#[doc(cfg(), cfg(foo, bar))]
|
||||
//~^ ERROR
|
||||
//~^^ ERROR
|
||||
#[doc(cfg(foo), cfg(bar))] // ok!
|
||||
#[doc(cfg(foo), cfg(bar))]
|
||||
//~^ WARN unexpected `cfg` condition name: `foo`
|
||||
//~^^ WARN unexpected `cfg` condition name: `bar`
|
||||
#[doc(cfg())] //~ ERROR
|
||||
#[doc(cfg(foo, bar))] //~ ERROR
|
||||
pub fn foo() {}
|
||||
|
|
|
|||
|
|
@ -10,17 +10,37 @@ error: multiple `cfg` predicates are specified
|
|||
LL | #[doc(cfg(), cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
warning: unexpected `cfg` condition name: `foo`
|
||||
--> $DIR/doc-cfg.rs:6:11
|
||||
|
|
||||
LL | #[doc(cfg(foo), cfg(bar))]
|
||||
| ^^^
|
||||
|
|
||||
= help: expected names are: `FALSE` and `test` and 31 more
|
||||
= 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
|
||||
= note: `#[warn(unexpected_cfgs)]` on by default
|
||||
|
||||
warning: unexpected `cfg` condition name: `bar`
|
||||
--> $DIR/doc-cfg.rs:6:21
|
||||
|
|
||||
LL | #[doc(cfg(foo), cfg(bar))]
|
||||
| ^^^
|
||||
|
|
||||
= help: to expect this configuration use `--check-cfg=cfg(bar)`
|
||||
= note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
|
||||
|
||||
error: `cfg` predicate is not specified
|
||||
--> $DIR/doc-cfg.rs:7:7
|
||||
--> $DIR/doc-cfg.rs:9:7
|
||||
|
|
||||
LL | #[doc(cfg())]
|
||||
| ^^^^^ help: expected syntax is: `cfg(/* predicate */)`
|
||||
|
||||
error: multiple `cfg` predicates are specified
|
||||
--> $DIR/doc-cfg.rs:8:16
|
||||
--> $DIR/doc-cfg.rs:10:16
|
||||
|
|
||||
LL | #[doc(cfg(foo, bar))]
|
||||
| ^^^
|
||||
|
||||
error: aborting due to 4 previous errors
|
||||
error: aborting due to 4 previous errors; 2 warnings emitted
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue