Only highlight identifier in scraped examples, not arguments
This commit is contained in:
parent
7e81b0a317
commit
d58c9dfdb9
3 changed files with 44 additions and 49 deletions
|
@ -2717,45 +2717,20 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
|
||||||
// The output code is limited to that byte range.
|
// The output code is limited to that byte range.
|
||||||
let contents_subset = &contents[(byte_min as usize)..(byte_max as usize)];
|
let contents_subset = &contents[(byte_min as usize)..(byte_max as usize)];
|
||||||
|
|
||||||
// Given a call-site range, return the set of sub-ranges that exclude leading whitespace
|
|
||||||
// when the range spans multiple lines.
|
|
||||||
let strip_leading_whitespace = |(lo, hi): (u32, u32)| -> Vec<(u32, u32)> {
|
|
||||||
let contents_range = &contents_subset[(lo as usize)..(hi as usize)];
|
|
||||||
let mut ignoring_whitespace = false;
|
|
||||||
let mut ranges = Vec::new();
|
|
||||||
let mut cur_lo = 0;
|
|
||||||
for (idx, chr) in contents_range.char_indices() {
|
|
||||||
let idx = idx as u32;
|
|
||||||
if ignoring_whitespace {
|
|
||||||
if !chr.is_whitespace() {
|
|
||||||
ignoring_whitespace = false;
|
|
||||||
cur_lo = idx;
|
|
||||||
}
|
|
||||||
} else if chr == '\n' {
|
|
||||||
ranges.push((lo + cur_lo, lo + idx));
|
|
||||||
cur_lo = idx;
|
|
||||||
ignoring_whitespace = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
ranges.push((lo + cur_lo, hi));
|
|
||||||
ranges
|
|
||||||
};
|
|
||||||
|
|
||||||
// The call locations need to be updated to reflect that the size of the program has changed.
|
// The call locations need to be updated to reflect that the size of the program has changed.
|
||||||
// Specifically, the ranges are all subtracted by `byte_min` since that's the new zero point.
|
// Specifically, the ranges are all subtracted by `byte_min` since that's the new zero point.
|
||||||
let (mut byte_ranges, line_ranges): (Vec<_>, Vec<_>) = call_data
|
let (mut byte_ranges, line_ranges): (Vec<_>, Vec<_>) = call_data
|
||||||
.locations
|
.locations
|
||||||
.iter()
|
.iter()
|
||||||
.map(|loc| {
|
.map(|loc| {
|
||||||
let (byte_lo, byte_hi) = loc.call_expr.byte_span;
|
let (byte_lo, byte_hi) = loc.call_ident.byte_span;
|
||||||
let (line_lo, line_hi) = loc.call_expr.line_span;
|
let (line_lo, line_hi) = loc.call_expr.line_span;
|
||||||
let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
|
let byte_range = (byte_lo - byte_min, byte_hi - byte_min);
|
||||||
let byte_ranges = strip_leading_whitespace(byte_range);
|
|
||||||
|
|
||||||
let line_range = (line_lo - line_min, line_hi - line_min);
|
let line_range = (line_lo - line_min, line_hi - line_min);
|
||||||
let (line_url, line_title) = link_to_loc(call_data, loc);
|
let (line_url, line_title) = link_to_loc(call_data, loc);
|
||||||
|
|
||||||
(byte_ranges, (line_range, line_url, line_title))
|
(byte_range, (line_range, line_url, line_title))
|
||||||
})
|
})
|
||||||
.unzip();
|
.unzip();
|
||||||
|
|
||||||
|
@ -2810,8 +2785,8 @@ fn render_call_locations(w: &mut Buffer, cx: &Context<'_>, item: &clean::Item) {
|
||||||
let root_path = vec!["../"; cx.current.len() - 1].join("");
|
let root_path = vec!["../"; cx.current.len() - 1].join("");
|
||||||
|
|
||||||
let mut decoration_info = FxHashMap::default();
|
let mut decoration_info = FxHashMap::default();
|
||||||
decoration_info.insert("highlight focus", byte_ranges.remove(0));
|
decoration_info.insert("highlight focus", vec![byte_ranges.remove(0)]);
|
||||||
decoration_info.insert("highlight", byte_ranges.into_iter().flatten().collect());
|
decoration_info.insert("highlight", byte_ranges);
|
||||||
|
|
||||||
sources::print_src(
|
sources::print_src(
|
||||||
w,
|
w,
|
||||||
|
|
|
@ -85,17 +85,20 @@ impl SyntaxRange {
|
||||||
#[derive(Encodable, Decodable, Debug, Clone)]
|
#[derive(Encodable, Decodable, Debug, Clone)]
|
||||||
crate struct CallLocation {
|
crate struct CallLocation {
|
||||||
crate call_expr: SyntaxRange,
|
crate call_expr: SyntaxRange,
|
||||||
|
crate call_ident: SyntaxRange,
|
||||||
crate enclosing_item: SyntaxRange,
|
crate enclosing_item: SyntaxRange,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl CallLocation {
|
impl CallLocation {
|
||||||
fn new(
|
fn new(
|
||||||
expr_span: rustc_span::Span,
|
expr_span: rustc_span::Span,
|
||||||
|
ident_span: rustc_span::Span,
|
||||||
enclosing_item_span: rustc_span::Span,
|
enclosing_item_span: rustc_span::Span,
|
||||||
source_file: &SourceFile,
|
source_file: &SourceFile,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
CallLocation {
|
CallLocation {
|
||||||
call_expr: SyntaxRange::new(expr_span, source_file),
|
call_expr: SyntaxRange::new(expr_span, source_file),
|
||||||
|
call_ident: SyntaxRange::new(ident_span, source_file),
|
||||||
enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
|
enclosing_item: SyntaxRange::new(enclosing_item_span, source_file),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -146,24 +149,39 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get type of function if expression is a function call
|
// Get type of function if expression is a function call
|
||||||
let (ty, span) = match ex.kind {
|
let (ty, call_span, ident_span) = match ex.kind {
|
||||||
hir::ExprKind::Call(f, _) => {
|
hir::ExprKind::Call(f, _) => {
|
||||||
let types = tcx.typeck(ex.hir_id.owner);
|
let types = tcx.typeck(ex.hir_id.owner);
|
||||||
|
|
||||||
if let Some(ty) = types.node_type_opt(f.hir_id) {
|
if let Some(ty) = types.node_type_opt(f.hir_id) {
|
||||||
(ty, ex.span)
|
(ty, ex.span, f.span)
|
||||||
} else {
|
} else {
|
||||||
trace!("node_type_opt({}) = None", f.hir_id);
|
trace!("node_type_opt({}) = None", f.hir_id);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::ExprKind::MethodCall(_, _, span) => {
|
hir::ExprKind::MethodCall(_, args, call_span) => {
|
||||||
let types = tcx.typeck(ex.hir_id.owner);
|
let types = tcx.typeck(ex.hir_id.owner);
|
||||||
let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
|
let Some(def_id) = types.type_dependent_def_id(ex.hir_id) else {
|
||||||
trace!("type_dependent_def_id({}) = None", ex.hir_id);
|
trace!("type_dependent_def_id({}) = None", ex.hir_id);
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
(tcx.type_of(def_id), span)
|
|
||||||
|
// The MethodCall node doesn't directly contain a span for the
|
||||||
|
// method identifier, so we have to compute it by trimming the full
|
||||||
|
// span based on the arguments.
|
||||||
|
let ident_span = match args.get(1) {
|
||||||
|
// If there is an argument, e.g. "f(x)", then
|
||||||
|
// get the span "f(" and delete the lparen.
|
||||||
|
Some(arg) => {
|
||||||
|
let with_paren = call_span.until(arg.span);
|
||||||
|
with_paren.with_hi(with_paren.hi() - BytePos(1))
|
||||||
|
}
|
||||||
|
// Otherwise, just delete both parens directly.
|
||||||
|
None => call_span.with_hi(call_span.hi() - BytePos(2)),
|
||||||
|
};
|
||||||
|
|
||||||
|
(tcx.type_of(def_id), call_span, ident_span)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
return;
|
return;
|
||||||
|
@ -172,8 +190,8 @@ where
|
||||||
|
|
||||||
// If this span comes from a macro expansion, then the source code may not actually show
|
// 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.
|
// a use of the given item, so it would be a poor example. Hence, we skip all uses in macros.
|
||||||
if span.from_expansion() {
|
if call_span.from_expansion() {
|
||||||
trace!("Rejecting expr from macro: {:?}", span);
|
trace!("Rejecting expr from macro: {:?}", call_span);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,26 +201,29 @@ where
|
||||||
.hir()
|
.hir()
|
||||||
.span_with_body(tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(ex.hir_id)));
|
.span_with_body(tcx.hir().local_def_id_to_hir_id(tcx.hir().get_parent_item(ex.hir_id)));
|
||||||
if enclosing_item_span.from_expansion() {
|
if enclosing_item_span.from_expansion() {
|
||||||
trace!("Rejecting expr ({:?}) from macro item: {:?}", span, enclosing_item_span);
|
trace!("Rejecting expr ({:?}) from macro item: {:?}", call_span, enclosing_item_span);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
assert!(
|
assert!(
|
||||||
enclosing_item_span.contains(span),
|
enclosing_item_span.contains(call_span),
|
||||||
"Attempted to scrape call at [{:?}] whose enclosing item [{:?}] doesn't contain the span of the call.",
|
"Attempted to scrape call at [{call_span:?}] whose enclosing item [{enclosing_item_span:?}] doesn't contain the span of the call.",
|
||||||
span,
|
);
|
||||||
enclosing_item_span
|
|
||||||
|
assert!(
|
||||||
|
call_span.contains(ident_span),
|
||||||
|
"Attempted to scrape call at [{call_span:?}] whose identifier [{ident_span:?}] was not contained in the span of the call."
|
||||||
);
|
);
|
||||||
|
|
||||||
// Save call site if the function resolves to a concrete definition
|
// Save call site if the function resolves to a concrete definition
|
||||||
if let ty::FnDef(def_id, _) = ty.kind() {
|
if let ty::FnDef(def_id, _) = ty.kind() {
|
||||||
if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
|
if self.target_crates.iter().all(|krate| *krate != def_id.krate) {
|
||||||
trace!("Rejecting expr from crate not being documented: {:?}", span);
|
trace!("Rejecting expr from crate not being documented: {call_span:?}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let source_map = tcx.sess.source_map();
|
let source_map = tcx.sess.source_map();
|
||||||
let file = source_map.lookup_char_pos(span.lo()).file;
|
let file = source_map.lookup_char_pos(call_span.lo()).file;
|
||||||
let file_path = match file.name.clone() {
|
let file_path = match file.name.clone() {
|
||||||
FileName::Real(real_filename) => real_filename.into_local_path(),
|
FileName::Real(real_filename) => real_filename.into_local_path(),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -212,20 +233,20 @@ where
|
||||||
let abs_path = fs::canonicalize(file_path.clone()).unwrap();
|
let abs_path = fs::canonicalize(file_path.clone()).unwrap();
|
||||||
let cx = &self.cx;
|
let cx = &self.cx;
|
||||||
let mk_call_data = || {
|
let mk_call_data = || {
|
||||||
let clean_span = crate::clean::types::Span::new(span);
|
let clean_span = crate::clean::types::Span::new(call_span);
|
||||||
let url = cx.href_from_span(clean_span, false).unwrap();
|
let url = cx.href_from_span(clean_span, false).unwrap();
|
||||||
let display_name = file_path.display().to_string();
|
let display_name = file_path.display().to_string();
|
||||||
let edition = span.edition();
|
let edition = call_span.edition();
|
||||||
CallData { locations: Vec::new(), url, display_name, edition }
|
CallData { locations: Vec::new(), url, display_name, edition }
|
||||||
};
|
};
|
||||||
|
|
||||||
let fn_key = tcx.def_path_hash(*def_id);
|
let fn_key = tcx.def_path_hash(*def_id);
|
||||||
let fn_entries = self.calls.entry(fn_key).or_default();
|
let fn_entries = self.calls.entry(fn_key).or_default();
|
||||||
|
|
||||||
trace!("Including expr: {:?}", span);
|
trace!("Including expr: {:?}", call_span);
|
||||||
let enclosing_item_span =
|
let enclosing_item_span =
|
||||||
source_map.span_extend_to_prev_char(enclosing_item_span, '\n', false);
|
source_map.span_extend_to_prev_char(enclosing_item_span, '\n', false);
|
||||||
let location = CallLocation::new(span, enclosing_item_span, &file);
|
let location = CallLocation::new(call_span, ident_span, enclosing_item_span, &file);
|
||||||
fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
|
fn_entries.entry(abs_path).or_insert_with(mk_call_data).locations.push(location);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
|
// @has foobar/fn.ok.html '//*[@class="docblock scraped-example-list"]' 'ex2'
|
||||||
// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
|
// @has foobar/fn.ok.html '//*[@class="more-scraped-examples"]' 'ex1'
|
||||||
// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '1'
|
// @has foobar/fn.ok.html '//*[@class="highlight focus"]' ''
|
||||||
// @has foobar/fn.ok.html '//*[@class="highlight"]' '2'
|
// @has foobar/fn.ok.html '//*[@class="highlight"]' ''
|
||||||
// @has foobar/fn.ok.html '//*[@class="highlight focus"]' '0'
|
|
||||||
|
|
||||||
pub fn ok(_x: i32) {}
|
pub fn ok(_x: i32) {}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue