Remove LightSpan and use Span directly
This commit is contained in:
parent
5cf300d695
commit
dfe4fec783
5 changed files with 44 additions and 98 deletions
|
@ -14,20 +14,16 @@ use std::iter::Peekable;
|
||||||
use rustc_lexer::{LiteralKind, TokenKind};
|
use rustc_lexer::{LiteralKind, TokenKind};
|
||||||
use rustc_span::edition::Edition;
|
use rustc_span::edition::Edition;
|
||||||
use rustc_span::symbol::Symbol;
|
use rustc_span::symbol::Symbol;
|
||||||
|
use rustc_span::{BytePos, Span, DUMMY_SP};
|
||||||
|
|
||||||
use super::format::{self, Buffer};
|
use super::format::{self, Buffer};
|
||||||
use super::render::{LightSpan, LinkFromSrc};
|
use super::render::LinkFromSrc;
|
||||||
|
|
||||||
/// This type is needed in case we want to render links on items to allow to go to their definition.
|
/// This type is needed in case we want to render links on items to allow to go to their definition.
|
||||||
crate struct ContextInfo<'a, 'b, 'c> {
|
crate struct ContextInfo<'a, 'b, 'c> {
|
||||||
crate context: &'a Context<'b>,
|
crate context: &'a Context<'b>,
|
||||||
/// This represents the "lo" bytes of the current file we're rendering. To get a [`Span`] from
|
/// This span contains the current file we're going through.
|
||||||
/// it, you just need to add add your current byte position in the string and its length (to get
|
crate file_span: Span,
|
||||||
/// the "hi" part).
|
|
||||||
///
|
|
||||||
/// This is used to create a [`LightSpan`] which is then used as an index in the `span_map` in
|
|
||||||
/// order to retrieve the definition's [`Span`] (which is used to generate the URL).
|
|
||||||
crate file_span_lo: u32,
|
|
||||||
/// This field is used to know "how far" from the top of the directory we are to link to either
|
/// This field is used to know "how far" from the top of the directory we are to link to either
|
||||||
/// documentation pages or other source pages.
|
/// documentation pages or other source pages.
|
||||||
crate root_path: &'c str,
|
crate root_path: &'c str,
|
||||||
|
@ -86,7 +82,6 @@ fn write_header(out: &mut Buffer, class: Option<&str>, extra_content: Option<Buf
|
||||||
/// item definition.
|
/// item definition.
|
||||||
///
|
///
|
||||||
/// More explanations about spans and how we use them here are provided in the
|
/// More explanations about spans and how we use them here are provided in the
|
||||||
/// [`LightSpan::new_in_file`] function documentation about how it works.
|
|
||||||
fn write_code(
|
fn write_code(
|
||||||
out: &mut Buffer,
|
out: &mut Buffer,
|
||||||
src: &str,
|
src: &str,
|
||||||
|
@ -95,7 +90,7 @@ fn write_code(
|
||||||
) {
|
) {
|
||||||
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
// This replace allows to fix how the code source with DOS backline characters is displayed.
|
||||||
let src = src.replace("\r\n", "\n");
|
let src = src.replace("\r\n", "\n");
|
||||||
Classifier::new(&src, edition, context_info.as_ref().map(|c| c.file_span_lo).unwrap_or(0))
|
Classifier::new(&src, edition, context_info.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP))
|
||||||
.highlight(&mut |highlight| {
|
.highlight(&mut |highlight| {
|
||||||
match highlight {
|
match highlight {
|
||||||
Highlight::Token { text, class } => string(out, Escape(text), class, &context_info),
|
Highlight::Token { text, class } => string(out, Escape(text), class, &context_info),
|
||||||
|
@ -118,14 +113,14 @@ enum Class {
|
||||||
KeyWord,
|
KeyWord,
|
||||||
// Keywords that do pointer/reference stuff.
|
// Keywords that do pointer/reference stuff.
|
||||||
RefKeyWord,
|
RefKeyWord,
|
||||||
Self_(LightSpan),
|
Self_(Span),
|
||||||
Op,
|
Op,
|
||||||
Macro,
|
Macro,
|
||||||
MacroNonTerminal,
|
MacroNonTerminal,
|
||||||
String,
|
String,
|
||||||
Number,
|
Number,
|
||||||
Bool,
|
Bool,
|
||||||
Ident(LightSpan),
|
Ident(Span),
|
||||||
Lifetime,
|
Lifetime,
|
||||||
PreludeTy,
|
PreludeTy,
|
||||||
PreludeVal,
|
PreludeVal,
|
||||||
|
@ -158,7 +153,7 @@ impl Class {
|
||||||
|
|
||||||
/// In case this is an item which can be converted into a link to a definition, it'll contain
|
/// In case this is an item which can be converted into a link to a definition, it'll contain
|
||||||
/// a "span" (a tuple representing `(lo, hi)` equivalent of `Span`).
|
/// a "span" (a tuple representing `(lo, hi)` equivalent of `Span`).
|
||||||
fn get_span(self) -> Option<LightSpan> {
|
fn get_span(self) -> Option<Span> {
|
||||||
match self {
|
match self {
|
||||||
Self::Ident(sp) | Self::Self_(sp) => Some(sp),
|
Self::Ident(sp) | Self::Self_(sp) => Some(sp),
|
||||||
_ => None,
|
_ => None,
|
||||||
|
@ -213,15 +208,14 @@ struct Classifier<'a> {
|
||||||
in_macro_nonterminal: bool,
|
in_macro_nonterminal: bool,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
byte_pos: u32,
|
byte_pos: u32,
|
||||||
file_span_lo: u32,
|
file_span: Span,
|
||||||
src: &'a str,
|
src: &'a str,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Classifier<'a> {
|
impl<'a> Classifier<'a> {
|
||||||
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
|
/// Takes as argument the source code to HTML-ify, the rust edition to use and the source code
|
||||||
/// file "lo" byte which we be used later on by the `span_correspondance_map`. More explanations
|
/// file span which will be used later on by the `span_correspondance_map`.
|
||||||
/// are provided in the [`LightSpan::new_in_file`] function documentation about how it works.
|
fn new(src: &str, edition: Edition, file_span: Span) -> Classifier<'_> {
|
||||||
fn new(src: &str, edition: Edition, file_span_lo: u32) -> Classifier<'_> {
|
|
||||||
let tokens = TokenIter { src }.peekable();
|
let tokens = TokenIter { src }.peekable();
|
||||||
Classifier {
|
Classifier {
|
||||||
tokens,
|
tokens,
|
||||||
|
@ -230,15 +224,16 @@ impl<'a> Classifier<'a> {
|
||||||
in_macro_nonterminal: false,
|
in_macro_nonterminal: false,
|
||||||
edition,
|
edition,
|
||||||
byte_pos: 0,
|
byte_pos: 0,
|
||||||
file_span_lo,
|
file_span,
|
||||||
src,
|
src,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convenient wrapper around [`LightSpan::new_in_file`] to prevent passing the `file_span_lo`
|
/// Convenient wrapper to create a [`Span`] from a position in the file.
|
||||||
/// argument every time.
|
fn new_span(&self, lo: u32, text: &str) -> Span {
|
||||||
fn new_light_span(&self, lo: u32, hi: u32) -> LightSpan {
|
let hi = lo + text.len() as u32;
|
||||||
LightSpan::new_in_file(self.file_span_lo, lo, hi)
|
let file_lo = self.file_span.lo();
|
||||||
|
self.file_span.with_lo(file_lo + BytePos(lo)).with_hi(file_lo + BytePos(hi))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Concatenate colons and idents as one when possible.
|
/// Concatenate colons and idents as one when possible.
|
||||||
|
@ -487,15 +482,13 @@ impl<'a> Classifier<'a> {
|
||||||
self.in_macro_nonterminal = false;
|
self.in_macro_nonterminal = false;
|
||||||
Class::MacroNonTerminal
|
Class::MacroNonTerminal
|
||||||
}
|
}
|
||||||
"self" | "Self" => {
|
"self" | "Self" => Class::Self_(self.new_span(before, text)),
|
||||||
Class::Self_(self.new_light_span(before, before + text.len() as u32))
|
_ => Class::Ident(self.new_span(before, text)),
|
||||||
}
|
|
||||||
_ => Class::Ident(self.new_light_span(before, before + text.len() as u32)),
|
|
||||||
},
|
},
|
||||||
Some(c) => c,
|
Some(c) => c,
|
||||||
},
|
},
|
||||||
TokenKind::RawIdent | TokenKind::UnknownPrefix => {
|
TokenKind::RawIdent | TokenKind::UnknownPrefix => {
|
||||||
Class::Ident(self.new_light_span(before, before + text.len() as u32))
|
Class::Ident(self.new_span(before, text))
|
||||||
}
|
}
|
||||||
TokenKind::Lifetime { .. } => Class::Lifetime,
|
TokenKind::Lifetime { .. } => Class::Lifetime,
|
||||||
};
|
};
|
||||||
|
@ -560,7 +553,7 @@ fn string<T: Display>(
|
||||||
"self" | "Self" => write!(
|
"self" | "Self" => write!(
|
||||||
&mut path,
|
&mut path,
|
||||||
"<span class=\"{}\">{}</span>",
|
"<span class=\"{}\">{}</span>",
|
||||||
Class::Self_(LightSpan::dummy()).as_html(),
|
Class::Self_(DUMMY_SP).as_html(),
|
||||||
t
|
t
|
||||||
),
|
),
|
||||||
"crate" | "super" => {
|
"crate" | "super" => {
|
||||||
|
|
|
@ -18,8 +18,8 @@ use super::cache::{build_index, ExternalLocation};
|
||||||
use super::print_item::{full_path, item_path, print_item};
|
use super::print_item::{full_path, item_path, print_item};
|
||||||
use super::write_shared::write_shared;
|
use super::write_shared::write_shared;
|
||||||
use super::{
|
use super::{
|
||||||
collect_spans_and_sources, print_sidebar, settings, AllTypes, LightSpan, LinkFromSrc, NameDoc,
|
collect_spans_and_sources, print_sidebar, settings, AllTypes, LinkFromSrc, NameDoc, StylePath,
|
||||||
StylePath, BASIC_KEYWORDS,
|
BASIC_KEYWORDS,
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::clean;
|
use crate::clean;
|
||||||
|
@ -131,7 +131,7 @@ crate struct SharedContext<'tcx> {
|
||||||
|
|
||||||
/// Correspondance map used to link types used in the source code pages to allow to click on
|
/// Correspondance map used to link types used in the source code pages to allow to click on
|
||||||
/// links to jump to the type's definition.
|
/// links to jump to the type's definition.
|
||||||
crate span_correspondance_map: FxHashMap<LightSpan, LinkFromSrc>,
|
crate span_correspondance_map: FxHashMap<rustc_span::Span, LinkFromSrc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SharedContext<'_> {
|
impl SharedContext<'_> {
|
||||||
|
|
|
@ -34,7 +34,7 @@ mod span_map;
|
||||||
mod write_shared;
|
mod write_shared;
|
||||||
|
|
||||||
crate use context::*;
|
crate use context::*;
|
||||||
crate use span_map::{collect_spans_and_sources, LightSpan, LinkFromSrc};
|
crate use span_map::{collect_spans_and_sources, LinkFromSrc};
|
||||||
|
|
||||||
use std::collections::VecDeque;
|
use std::collections::VecDeque;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
|
|
@ -24,43 +24,6 @@ crate enum LinkFromSrc {
|
||||||
External(DefId),
|
External(DefId),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This struct is used only as index in the `span_map`, not as [`Span`]! `Span`s contain
|
|
||||||
/// some extra information (the syntax context) we don't need. **Do not convert this type back to
|
|
||||||
/// `Span`!!!**
|
|
||||||
#[derive(Clone, Copy, Hash, PartialEq, Eq, Debug)]
|
|
||||||
crate struct LightSpan {
|
|
||||||
crate lo: u32,
|
|
||||||
crate hi: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl LightSpan {
|
|
||||||
/// Before explaining what this method does, some global explanations on rust's `Span`:
|
|
||||||
///
|
|
||||||
/// Each source code file is stored in the source map in the compiler and has a
|
|
||||||
/// `lo` and a `hi` (lowest and highest bytes in this source map which can be seen as one huge
|
|
||||||
/// string to simplify things). So in this case, this represents the starting byte of the
|
|
||||||
/// current file. It'll be used later on to retrieve the "definition span" from the
|
|
||||||
/// `span_correspondance_map` (which is inside `context`).
|
|
||||||
///
|
|
||||||
/// This when we transform the "span" we have from reading the input into a "span" which can be
|
|
||||||
/// used as index to the `span_correspondance_map` to get the definition of this item.
|
|
||||||
///
|
|
||||||
/// So in here, `file_span_lo` is representing the "lo" byte in the global source map, and to
|
|
||||||
/// make our "span" works in there, we simply add `file_span_lo` to our values.
|
|
||||||
crate fn new_in_file(file_span_lo: u32, lo: u32, hi: u32) -> Self {
|
|
||||||
Self { lo: lo + file_span_lo, hi: hi + file_span_lo }
|
|
||||||
}
|
|
||||||
|
|
||||||
crate fn dummy() -> Self {
|
|
||||||
Self { lo: 0, hi: 0 }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extra the `lo` and `hi` from the [`Span`] and discard the unused syntax context.
|
|
||||||
fn new_from_span(sp: Span) -> Self {
|
|
||||||
Self { lo: sp.lo().0, hi: sp.hi().0 }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// This function will do at most two things:
|
/// This function will do at most two things:
|
||||||
///
|
///
|
||||||
/// 1. Generate a `span` correspondance map which links an item `span` to its definition `span`.
|
/// 1. Generate a `span` correspondance map which links an item `span` to its definition `span`.
|
||||||
|
@ -77,7 +40,7 @@ crate fn collect_spans_and_sources(
|
||||||
src_root: &Path,
|
src_root: &Path,
|
||||||
include_sources: bool,
|
include_sources: bool,
|
||||||
generate_link_to_definition: bool,
|
generate_link_to_definition: bool,
|
||||||
) -> (clean::Crate, FxHashMap<PathBuf, String>, FxHashMap<LightSpan, LinkFromSrc>) {
|
) -> (clean::Crate, FxHashMap<PathBuf, String>, FxHashMap<Span, LinkFromSrc>) {
|
||||||
let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
|
let mut visitor = SpanMapVisitor { tcx, matches: FxHashMap::default() };
|
||||||
|
|
||||||
if include_sources {
|
if include_sources {
|
||||||
|
@ -93,7 +56,7 @@ crate fn collect_spans_and_sources(
|
||||||
|
|
||||||
struct SpanMapVisitor<'tcx> {
|
struct SpanMapVisitor<'tcx> {
|
||||||
crate tcx: TyCtxt<'tcx>,
|
crate tcx: TyCtxt<'tcx>,
|
||||||
crate matches: FxHashMap<LightSpan, LinkFromSrc>,
|
crate matches: FxHashMap<Span, LinkFromSrc>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'tcx> SpanMapVisitor<'tcx> {
|
impl<'tcx> SpanMapVisitor<'tcx> {
|
||||||
|
@ -115,18 +78,12 @@ impl<'tcx> SpanMapVisitor<'tcx> {
|
||||||
};
|
};
|
||||||
if let Some(span) = self.tcx.hir().res_span(path.res) {
|
if let Some(span) = self.tcx.hir().res_span(path.res) {
|
||||||
self.matches.insert(
|
self.matches.insert(
|
||||||
path_span
|
path_span.unwrap_or_else(|| path.span),
|
||||||
.map(LightSpan::new_from_span)
|
|
||||||
.unwrap_or_else(|| LightSpan::new_from_span(path.span)),
|
|
||||||
LinkFromSrc::Local(clean::Span::new(span)),
|
LinkFromSrc::Local(clean::Span::new(span)),
|
||||||
);
|
);
|
||||||
} else if let Some(def_id) = info {
|
} else if let Some(def_id) = info {
|
||||||
self.matches.insert(
|
self.matches
|
||||||
path_span
|
.insert(path_span.unwrap_or_else(|| path.span), LinkFromSrc::External(def_id));
|
||||||
.map(LightSpan::new_from_span)
|
|
||||||
.unwrap_or_else(|| LightSpan::new_from_span(path.span)),
|
|
||||||
LinkFromSrc::External(def_id),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,10 +120,8 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
||||||
if let Some(node) = self.tcx.hir().find(id) {
|
if let Some(node) = self.tcx.hir().find(id) {
|
||||||
match node {
|
match node {
|
||||||
Node::Item(item) => {
|
Node::Item(item) => {
|
||||||
self.matches.insert(
|
self.matches
|
||||||
LightSpan::new_from_span(item.ident.span),
|
.insert(item.ident.span, LinkFromSrc::Local(clean::Span::new(m.inner)));
|
||||||
LinkFromSrc::Local(clean::Span::new(m.inner)),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -188,7 +143,7 @@ impl Visitor<'tcx> for SpanMapVisitor<'tcx> {
|
||||||
});
|
});
|
||||||
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
|
if let Some(def_id) = typeck_results.type_dependent_def_id(expr.hir_id) {
|
||||||
self.matches.insert(
|
self.matches.insert(
|
||||||
LightSpan::new_from_span(method_span),
|
method_span,
|
||||||
match hir.span_if_local(def_id) {
|
match hir.span_if_local(def_id) {
|
||||||
Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
|
Some(span) => LinkFromSrc::Local(clean::Span::new(span)),
|
||||||
None => LinkFromSrc::External(def_id),
|
None => LinkFromSrc::External(def_id),
|
||||||
|
|
|
@ -111,13 +111,14 @@ impl DocFolder for SourceCollector<'_, '_> {
|
||||||
if self.cx.include_sources && is_real_and_local(span, sess) {
|
if self.cx.include_sources && is_real_and_local(span, sess) {
|
||||||
let filename = span.filename(sess);
|
let filename = span.filename(sess);
|
||||||
let span = span.inner();
|
let span = span.inner();
|
||||||
let start_pos = sess.source_map().lookup_source_file(span.lo()).start_pos;
|
let pos = sess.source_map().lookup_source_file(span.lo());
|
||||||
|
let file_span = span.with_lo(pos.start_pos).with_hi(pos.end_pos);
|
||||||
// If it turns out that we couldn't read this file, then we probably
|
// If it turns out that we couldn't read this file, then we probably
|
||||||
// can't read any of the files (generating html output from json or
|
// can't read any of the files (generating html output from json or
|
||||||
// something like that), so just don't include sources for the
|
// something like that), so just don't include sources for the
|
||||||
// entire crate. The other option is maintaining this mapping on a
|
// entire crate. The other option is maintaining this mapping on a
|
||||||
// per-file basis, but that's probably not worth it...
|
// per-file basis, but that's probably not worth it...
|
||||||
self.cx.include_sources = match self.emit_source(&filename, start_pos.0) {
|
self.cx.include_sources = match self.emit_source(&filename, file_span) {
|
||||||
Ok(()) => true,
|
Ok(()) => true,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
self.cx.shared.tcx.sess.span_err(
|
self.cx.shared.tcx.sess.span_err(
|
||||||
|
@ -140,7 +141,11 @@ impl DocFolder for SourceCollector<'_, '_> {
|
||||||
|
|
||||||
impl SourceCollector<'_, 'tcx> {
|
impl SourceCollector<'_, 'tcx> {
|
||||||
/// Renders the given filename into its corresponding HTML source file.
|
/// Renders the given filename into its corresponding HTML source file.
|
||||||
fn emit_source(&mut self, filename: &FileName, file_span_lo: u32) -> Result<(), Error> {
|
fn emit_source(
|
||||||
|
&mut self,
|
||||||
|
filename: &FileName,
|
||||||
|
file_span: rustc_span::Span,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let p = match *filename {
|
let p = match *filename {
|
||||||
FileName::Real(ref file) => {
|
FileName::Real(ref file) => {
|
||||||
if let Some(local_path) = file.local_path() {
|
if let Some(local_path) = file.local_path() {
|
||||||
|
@ -200,14 +205,7 @@ impl SourceCollector<'_, 'tcx> {
|
||||||
&page,
|
&page,
|
||||||
"",
|
"",
|
||||||
|buf: &mut _| {
|
|buf: &mut _| {
|
||||||
print_src(
|
print_src(buf, contents, self.cx.shared.edition(), file_span, &self.cx, &root_path)
|
||||||
buf,
|
|
||||||
contents,
|
|
||||||
self.cx.shared.edition(),
|
|
||||||
file_span_lo,
|
|
||||||
&self.cx,
|
|
||||||
&root_path,
|
|
||||||
)
|
|
||||||
},
|
},
|
||||||
&self.cx.shared.style_files,
|
&self.cx.shared.style_files,
|
||||||
);
|
);
|
||||||
|
@ -250,7 +248,7 @@ fn print_src(
|
||||||
buf: &mut Buffer,
|
buf: &mut Buffer,
|
||||||
s: &str,
|
s: &str,
|
||||||
edition: Edition,
|
edition: Edition,
|
||||||
file_span_lo: u32,
|
file_span: rustc_span::Span,
|
||||||
context: &Context<'_>,
|
context: &Context<'_>,
|
||||||
root_path: &str,
|
root_path: &str,
|
||||||
) {
|
) {
|
||||||
|
@ -275,6 +273,6 @@ fn print_src(
|
||||||
None,
|
None,
|
||||||
edition,
|
edition,
|
||||||
Some(line_numbers),
|
Some(line_numbers),
|
||||||
Some(highlight::ContextInfo { context, file_span_lo, root_path }),
|
Some(highlight::ContextInfo { context, file_span, root_path }),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue