use rustc_hir::{
self as hir,
intravisit::{self, Visitor},
- HirId,
};
use rustc_interface::interface;
use rustc_macros::{Decodable, Encodable};
target_crates,
})),
(Some(_), false) | (None, true) => {
- diag.err(&format!("must use --scrape-examples-output-path and --scrape-examples-target-crate together"));
+ diag.err("must use --scrape-examples-output-path and --scrape-examples-target-crate together");
Err(1)
}
(None, false) => Ok(None),
impl CallLocation {
fn new(
- tcx: TyCtxt<'_>,
expr_span: rustc_span::Span,
- expr_id: HirId,
+ enclosing_item_span: rustc_span::Span,
source_file: &SourceFile,
) -> Self {
- let enclosing_item_span =
- tcx.hir().span_with_body(tcx.hir().get_parent_item(expr_id)).source_callsite();
- assert!(enclosing_item_span.contains(expr_span));
-
CallLocation {
call_expr: SyntaxRange::new(expr_span, source_file),
enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
hir::ExprKind::Call(f, _) => {
let types = tcx.typeck(ex.hir_id.owner);
- match types.node_type_opt(f.hir_id) {
- Some(ty) => (ty, ex.span),
- None => {
- return;
- }
+ if let Some(ty) = types.node_type_opt(f.hir_id) {
+ (ty, ex.span)
+ } else {
+ trace!("node_type_opt({}) = None", f.hir_id);
+ return;
}
}
hir::ExprKind::MethodCall(_, _, _, span) => {
let types = tcx.typeck(ex.hir_id.owner);
- let def_id = types.type_dependent_def_id(ex.hir_id).unwrap();
+ let def_id = if let Some(def_id) = types.type_dependent_def_id(ex.hir_id) {
+ def_id
+ } else {
+ trace!("type_dependent_def_id({}) = None", ex.hir_id);
+ return;
+ };
(tcx.type_of(def_id), span)
}
_ => {
// If this span comes from a macro expansion, then the source code may not actually show
// a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
if span.from_expansion() {
+ trace!("Rejecting expr from macro: {:?}", span);
+ return;
+ }
+
+ // If the enclosing item has a span coming from a proc macro, then we also don't want to include
+ // the example.
+ let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(ex.hir_id));
+ if enclosing_item_span.from_expansion() {
+ trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span);
return;
}
+ assert!(
+ enclosing_item_span.contains(span),
+ "Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.",
+ span,
+ enclosing_item_span
+ );
+
// Save call site if the function resolves to a concrete definition
if let ty::FnDef(def_id, _) = ty.kind() {
- // Ignore functions not from the crate being documented
if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
+ trace!("Rejecting expr from crate not being documented: {:?}", span);
return;
}
let fn_key = tcx.def_path_hash(*def_id);
let fn_entries = self.calls.entry(fn_key).or_default();
- let location = CallLocation::new(tcx, span, ex.hir_id, &file);
+ trace!("Including expr: {:?}", span);
+ let location = CallLocation::new(span, enclosing_item_span, &file);
fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
}
}