Skip to content

Commit 4b3f82a

Browse files
committed
Add updated support for example-analyzer
Move rendering of examples into Finalize design Cleanup, rename found -> scraped Softer yellow Clean up dead code Document scrape_examples More simplification and documentation Remove extra css Test
1 parent 0eabf25 commit 4b3f82a

File tree

12 files changed

+609
-21
lines changed

12 files changed

+609
-21
lines changed

src/librustdoc/clean/inline.rs

+1
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,7 @@ fn build_external_function(cx: &mut DocContext<'_>, did: DefId) -> clean::Functi
235235
decl,
236236
generics,
237237
header: hir::FnHeader { unsafety: sig.unsafety(), abi: sig.abi(), constness, asyncness },
238+
call_locations: None,
238239
}
239240
}
240241

src/librustdoc/clean/mod.rs

+25-16
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,10 @@ impl<'a> Clean<Function> for (&'a hir::FnSig<'a>, &'a hir::Generics<'a>, hir::Bo
801801
fn clean(&self, cx: &mut DocContext<'_>) -> Function {
802802
let (generics, decl) =
803803
enter_impl_trait(cx, |cx| (self.1.clean(cx), (&*self.0.decl, self.2).clean(cx)));
804-
Function { decl, generics, header: self.0.header }
804+
let mut function = Function { decl, generics, header: self.0.header, call_locations: None };
805+
let def_id = self.2.hir_id.owner.to_def_id();
806+
function.load_call_locations(def_id, cx);
807+
function
805808
}
806809
}
807810

@@ -933,12 +936,14 @@ impl Clean<Item> for hir::TraitItem<'_> {
933936
let (generics, decl) = enter_impl_trait(cx, |cx| {
934937
(self.generics.clean(cx), (&*sig.decl, &names[..]).clean(cx))
935938
});
936-
let mut t = Function { header: sig.header, decl, generics };
939+
let mut t =
940+
Function { header: sig.header, decl, generics, call_locations: None };
937941
if t.header.constness == hir::Constness::Const
938942
&& is_unstable_const_fn(cx.tcx, local_did).is_some()
939943
{
940944
t.header.constness = hir::Constness::NotConst;
941945
}
946+
t.load_call_locations(self.def_id.to_def_id(), cx);
942947
TyMethodItem(t)
943948
}
944949
hir::TraitItemKind::Type(ref bounds, ref default) => {
@@ -1057,21 +1062,21 @@ impl Clean<Item> for ty::AssocItem {
10571062
ty::ImplContainer(_) => Some(self.defaultness),
10581063
ty::TraitContainer(_) => None,
10591064
};
1060-
MethodItem(
1061-
Function {
1062-
generics,
1063-
decl,
1064-
header: hir::FnHeader {
1065-
unsafety: sig.unsafety(),
1066-
abi: sig.abi(),
1067-
constness,
1068-
asyncness,
1069-
},
1065+
let mut function = Function {
1066+
generics,
1067+
decl,
1068+
header: hir::FnHeader {
1069+
unsafety: sig.unsafety(),
1070+
abi: sig.abi(),
1071+
constness,
1072+
asyncness,
10701073
},
1071-
defaultness,
1072-
)
1074+
call_locations: None,
1075+
};
1076+
function.load_call_locations(self.def_id, cx);
1077+
MethodItem(function, defaultness)
10731078
} else {
1074-
TyMethodItem(Function {
1079+
let mut function = Function {
10751080
generics,
10761081
decl,
10771082
header: hir::FnHeader {
@@ -1080,7 +1085,10 @@ impl Clean<Item> for ty::AssocItem {
10801085
constness: hir::Constness::NotConst,
10811086
asyncness: hir::IsAsync::NotAsync,
10821087
},
1083-
})
1088+
call_locations: None,
1089+
};
1090+
function.load_call_locations(self.def_id, cx);
1091+
TyMethodItem(function)
10841092
}
10851093
}
10861094
ty::AssocKind::Type => {
@@ -2098,6 +2106,7 @@ impl Clean<Item> for (&hir::ForeignItem<'_>, Option<Symbol>) {
20982106
constness: hir::Constness::NotConst,
20992107
asyncness: hir::IsAsync::NotAsync,
21002108
},
2109+
call_locations: None,
21012110
})
21022111
}
21032112
hir::ForeignItemKind::Static(ref ty, mutability) => {

src/librustdoc/clean/types.rs

+12
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ use crate::formats::cache::Cache;
4242
use crate::formats::item_type::ItemType;
4343
use crate::html::render::cache::ExternalLocation;
4444
use crate::html::render::Context;
45+
use crate::scrape_examples::FnCallLocations;
4546

4647
use self::FnRetTy::*;
4748
use self::ItemKind::*;
@@ -1254,6 +1255,17 @@ crate struct Function {
12541255
crate decl: FnDecl,
12551256
crate generics: Generics,
12561257
crate header: hir::FnHeader,
1258+
crate call_locations: Option<FnCallLocations>,
1259+
}
1260+
1261+
impl Function {
1262+
crate fn load_call_locations(&mut self, def_id: hir::def_id::DefId, cx: &DocContext<'_>) {
1263+
if let Some(call_locations) = cx.render_options.call_locations.as_ref() {
1264+
let key = cx.tcx.def_path(def_id).to_string_no_crate_verbose();
1265+
self.call_locations = call_locations.get(&key).cloned();
1266+
debug!("call_locations: {} -- {:?}", key, self.call_locations);
1267+
}
1268+
}
12571269
}
12581270

12591271
#[derive(Clone, PartialEq, Eq, Debug, Hash)]

src/librustdoc/config.rs

+11
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ use crate::html::render::StylePath;
2525
use crate::html::static_files;
2626
use crate::opts;
2727
use crate::passes::{self, Condition, DefaultPassOption};
28+
use crate::scrape_examples::AllCallLocations;
2829
use crate::theme;
2930

3031
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
@@ -158,6 +159,8 @@ crate struct Options {
158159
crate json_unused_externs: bool,
159160
/// Whether to skip capturing stdout and stderr of tests.
160161
crate nocapture: bool,
162+
163+
crate scrape_examples: Vec<String>,
161164
}
162165

163166
impl fmt::Debug for Options {
@@ -280,6 +283,8 @@ crate struct RenderOptions {
280283
crate emit: Vec<EmitType>,
281284
/// If `true`, HTML source pages will generate links for items to their definition.
282285
crate generate_link_to_definition: bool,
286+
crate call_locations: Option<AllCallLocations>,
287+
crate repository_url: Option<String>,
283288
}
284289

285290
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
@@ -671,6 +676,9 @@ impl Options {
671676
return Err(1);
672677
}
673678

679+
let repository_url = matches.opt_str("repository-url");
680+
let scrape_examples = matches.opt_strs("scrape-examples");
681+
674682
let (lint_opts, describe_lints, lint_cap) = get_cmd_lint_options(matches, error_format);
675683

676684
Ok(Options {
@@ -737,10 +745,13 @@ impl Options {
737745
),
738746
emit,
739747
generate_link_to_definition,
748+
call_locations: None,
749+
repository_url,
740750
},
741751
crate_name,
742752
output_format,
743753
json_unused_externs,
754+
scrape_examples,
744755
})
745756
}
746757

src/librustdoc/html/render/context.rs

+8-1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ crate struct SharedContext<'tcx> {
124124
crate span_correspondance_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
125125
/// The [`Cache`] used during rendering.
126126
crate cache: Cache,
127+
pub(super) repository_url: Option<String>,
127128
}
128129

129130
impl SharedContext<'_> {
@@ -140,7 +141,11 @@ impl SharedContext<'_> {
140141
/// Returns the `collapsed_doc_value` of the given item if this is the main crate, otherwise
141142
/// returns the `doc_value`.
142143
crate fn maybe_collapsed_doc_value<'a>(&self, item: &'a clean::Item) -> Option<String> {
143-
if self.collapsed { item.collapsed_doc_value() } else { item.doc_value() }
144+
if self.collapsed {
145+
item.collapsed_doc_value()
146+
} else {
147+
item.doc_value()
148+
}
144149
}
145150

146151
crate fn edition(&self) -> Edition {
@@ -389,6 +394,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
389394
generate_redirect_map,
390395
show_type_layout,
391396
generate_link_to_definition,
397+
repository_url,
392398
..
393399
} = options;
394400

@@ -480,6 +486,7 @@ impl<'tcx> FormatRenderer<'tcx> for Context<'tcx> {
480486
templates,
481487
span_correspondance_map: matches,
482488
cache,
489+
repository_url,
483490
};
484491

485492
// Add the default themes to the `Vec` of stylepaths

src/librustdoc/html/render/mod.rs

+95
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ crate use span_map::{collect_spans_and_sources, LinkFromSrc};
3939
use std::collections::VecDeque;
4040
use std::default::Default;
4141
use std::fmt;
42+
use std::fs;
4243
use std::path::PathBuf;
4344
use std::str;
4445
use std::string::ToString;
@@ -68,6 +69,8 @@ use crate::html::format::{
6869
print_generic_bounds, print_where_clause, Buffer, HrefError, PrintWithSpace,
6970
};
7071
use crate::html::markdown::{HeadingOffset, Markdown, MarkdownHtml, MarkdownSummaryLine};
72+
use crate::html::sources;
73+
use crate::scrape_examples::FnCallLocations;
7174

7275
/// A pair of name and its optional document.
7376
crate type NameDoc = (String, Option<String>);
@@ -584,6 +587,13 @@ fn document_full_inner(
584587
render_markdown(w, cx, &s, item.links(cx), heading_offset);
585588
}
586589
}
590+
591+
match &*item.kind {
592+
clean::ItemKind::FunctionItem(f) | clean::ItemKind::MethodItem(f, _) => {
593+
render_call_locations(w, cx, &f.call_locations);
594+
}
595+
_ => {}
596+
}
587597
}
588598

589599
/// Add extra information about an item such as:
@@ -2440,3 +2450,88 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
24402450
}
24412451
out
24422452
}
2453+
2454+
fn render_call_locations(
2455+
w: &mut Buffer,
2456+
cx: &Context<'_>,
2457+
call_locations: &Option<FnCallLocations>,
2458+
) {
2459+
let call_locations = match call_locations.as_ref() {
2460+
Some(call_locations) => call_locations,
2461+
None => {
2462+
return;
2463+
}
2464+
};
2465+
2466+
let filtered_locations: Vec<_> = call_locations
2467+
.iter()
2468+
.filter_map(|(file, locs)| {
2469+
// TODO(wcrichto): file I/O should be cached
2470+
let mut contents = match fs::read_to_string(&file) {
2471+
Ok(contents) => contents,
2472+
Err(e) => {
2473+
eprintln!("Failed to read file {}", e);
2474+
return None;
2475+
}
2476+
};
2477+
2478+
// Remove the utf-8 BOM if any
2479+
if contents.starts_with('\u{feff}') {
2480+
contents.drain(..3);
2481+
}
2482+
2483+
Some((file, contents, locs))
2484+
})
2485+
.collect();
2486+
2487+
let n_examples = filtered_locations.len();
2488+
if n_examples == 0 {
2489+
return;
2490+
}
2491+
2492+
let id = cx.id_map.borrow_mut().derive("scraped-examples");
2493+
write!(
2494+
w,
2495+
r##"<div class="docblock scraped-example-list">
2496+
<h1 id="scraped-examples" class="small-section-header">
2497+
<a href="#{}">Uses found in <code>examples/</code></a>
2498+
</h1>"##,
2499+
id
2500+
);
2501+
2502+
let write_example = |w: &mut Buffer, (file, contents, locs): (&String, String, _)| {
2503+
let ex_title = match cx.shared.repository_url.as_ref() {
2504+
Some(url) => format!(
2505+
r#"<a href="{url}/{file}" target="_blank">{file}</a>"#,
2506+
file = file,
2507+
url = url
2508+
),
2509+
None => file.clone(),
2510+
};
2511+
let edition = cx.shared.edition();
2512+
write!(
2513+
w,
2514+
r#"<div class="scraped-example" data-code="{code}" data-locs="{locations}">
2515+
<strong>{title}</strong>
2516+
<div class="code-wrapper">"#,
2517+
code = contents.replace("\"", "&quot;"),
2518+
locations = serde_json::to_string(&locs).unwrap(),
2519+
title = ex_title,
2520+
);
2521+
write!(w, r#"<span class="prev">&pr;</span> <span class="next">&sc;</span>"#);
2522+
write!(w, r#"<span class="expand">&varr;</span>"#);
2523+
sources::print_src(w, &contents, edition);
2524+
write!(w, "</div></div>");
2525+
};
2526+
2527+
let mut it = filtered_locations.into_iter();
2528+
write_example(w, it.next().unwrap());
2529+
2530+
if n_examples > 1 {
2531+
write!(w, r#"<div class="more-scraped-examples hidden">"#);
2532+
it.for_each(|ex| write_example(w, ex));
2533+
write!(w, "</div>");
2534+
}
2535+
2536+
write!(w, "</div>");
2537+
}

src/librustdoc/html/sources.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,7 @@ where
243243

244244
/// Wrapper struct to render the source code of a file. This will do things like
245245
/// adding line numbers to the left-hand side.
246-
fn print_src(
246+
crate fn print_src(
247247
buf: &mut Buffer,
248248
s: &str,
249249
edition: Edition,

0 commit comments

Comments
 (0)