about summary refs log tree commit diff
path: root/src/librustdoc/scrape_examples.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/librustdoc/scrape_examples.rs')
-rw-r--r--src/librustdoc/scrape_examples.rs62
1 files changed, 41 insertions, 21 deletions
diff --git a/src/librustdoc/scrape_examples.rs b/src/librustdoc/scrape_examples.rs
index 16a40ed1cb3..3887647ca0a 100644
--- a/src/librustdoc/scrape_examples.rs
+++ b/src/librustdoc/scrape_examples.rs
@@ -1,5 +1,4 @@
-//! This module analyzes crates to find examples of uses for items in the
-//! current crate being documented.
+//! This module analyzes crates to find call sites that can serve as examples in the documentation.
 
 use crate::clean;
 use crate::config;
@@ -11,20 +10,55 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir::{
     self as hir,
     intravisit::{self, Visitor},
+    HirId,
 };
 use rustc_interface::interface;
 use rustc_middle::hir::map::Map;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_span::{def_id::DefId, FileName};
+use rustc_span::{def_id::DefId, BytePos, FileName, SourceFile};
 use serde::{Deserialize, Serialize};
 use std::fs;
 use std::path::PathBuf;
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
+crate struct SyntaxRange {
+    crate byte_span: (u32, u32),
+    crate line_span: (usize, usize),
+}
+
+impl SyntaxRange {
+    fn new(span: rustc_span::Span, file: &SourceFile) -> Self {
+        let get_pos = |bytepos: BytePos| file.original_relative_byte_pos(bytepos).0;
+        let get_line = |bytepos: BytePos| file.lookup_line(bytepos).unwrap();
+
+        SyntaxRange {
+            byte_span: (get_pos(span.lo()), get_pos(span.hi())),
+            line_span: (get_line(span.lo()), get_line(span.hi())),
+        }
+    }
+}
+
+#[derive(Serialize, Deserialize, Debug, Clone)]
 crate struct CallLocation {
-    crate call_span: (usize, usize),
-    crate enclosing_item_span: (usize, usize),
-    crate enclosing_item_lines: (usize, usize),
+    crate call_expr: SyntaxRange,
+    crate enclosing_item: SyntaxRange,
+}
+
+impl CallLocation {
+    fn new(
+        tcx: TyCtxt<'_>,
+        expr_span: rustc_span::Span,
+        expr_id: HirId,
+        source_file: &rustc_span::SourceFile,
+    ) -> Self {
+        let enclosing_item_span = tcx.hir().span_with_body(tcx.hir().get_parent_item(expr_id));
+        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),
+        }
+    }
 }
 
 #[derive(Serialize, Deserialize, Debug, Clone)]
@@ -96,24 +130,10 @@ where
                 _ => None,
             };
 
-            let get_pos =
-                |bytepos: rustc_span::BytePos| file.original_relative_byte_pos(bytepos).0 as usize;
-            let get_range = |span: rustc_span::Span| (get_pos(span.lo()), get_pos(span.hi()));
-            let get_line = |bytepos: rustc_span::BytePos| file.lookup_line(bytepos).unwrap();
-            let get_lines = |span: rustc_span::Span| (get_line(span.lo()), get_line(span.hi()));
-
             if let Some(file_path) = file_path {
                 let abs_path = fs::canonicalize(file_path.clone()).unwrap();
                 let cx = &self.cx;
-                let enclosing_item_span =
-                    self.tcx.hir().span_with_body(self.tcx.hir().get_parent_item(ex.hir_id));
-                assert!(enclosing_item_span.contains(span));
-
-                let location = CallLocation {
-                    call_span: get_range(span),
-                    enclosing_item_span: get_range(enclosing_item_span),
-                    enclosing_item_lines: get_lines(enclosing_item_span),
-                };
+                let location = CallLocation::new(self.tcx, span, ex.hir_id, &file);
 
                 entries
                     .entry(abs_path)