mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Remove SpanPos
in favor of ErrorPos
This commit is contained in:
parent
ec884ec1d8
commit
fd8160f374
52
src/diag.rs
52
src/diag.rs
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
|
use std::ops::Range;
|
||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::str::Utf8Error;
|
use std::str::Utf8Error;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
@ -9,6 +10,7 @@ use std::string::FromUtf8Error;
|
|||||||
use comemo::Tracked;
|
use comemo::Tracked;
|
||||||
|
|
||||||
use crate::syntax::{Span, Spanned};
|
use crate::syntax::{Span, Spanned};
|
||||||
|
use crate::util::EcoString;
|
||||||
use crate::World;
|
use crate::World;
|
||||||
|
|
||||||
/// Early-return with a [`SourceError`].
|
/// Early-return with a [`SourceError`].
|
||||||
@ -39,32 +41,64 @@ macro_rules! error {
|
|||||||
pub type SourceResult<T> = Result<T, Box<Vec<SourceError>>>;
|
pub type SourceResult<T> = Result<T, Box<Vec<SourceError>>>;
|
||||||
|
|
||||||
/// An error in a source file.
|
/// An error in a source file.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq, Hash)]
|
||||||
pub struct SourceError {
|
pub struct SourceError {
|
||||||
/// The erroneous node in the source code.
|
/// The span of the erroneous node in the source code.
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
|
/// The position in the node where the error should be annotated.
|
||||||
|
pub pos: ErrorPos,
|
||||||
/// A diagnostic message describing the problem.
|
/// A diagnostic message describing the problem.
|
||||||
pub message: String,
|
pub message: EcoString,
|
||||||
/// The trace of function calls leading to the error.
|
/// The trace of function calls leading to the error.
|
||||||
pub trace: Vec<Spanned<Tracepoint>>,
|
pub trace: Vec<Spanned<Tracepoint>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SourceError {
|
impl SourceError {
|
||||||
/// Create a new, bare error.
|
/// Create a new, bare error.
|
||||||
pub fn new(span: Span, message: impl Into<String>) -> Self {
|
pub fn new(span: Span, message: impl Into<EcoString>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
span,
|
span,
|
||||||
|
pos: ErrorPos::Full,
|
||||||
trace: vec![],
|
trace: vec![],
|
||||||
message: message.into(),
|
message: message.into(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adjust the position in the node where the error should be annotated.
|
||||||
|
pub fn with_pos(mut self, pos: ErrorPos) -> Self {
|
||||||
|
self.pos = pos;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The range in the source file identified by
|
||||||
|
/// [`self.span.source()`](Span::source) where the error should be
|
||||||
|
/// annotated.
|
||||||
|
pub fn range(&self, world: &dyn World) -> Range<usize> {
|
||||||
|
let full = world.source(self.span.source()).range(self.span);
|
||||||
|
match self.pos {
|
||||||
|
ErrorPos::Full => full,
|
||||||
|
ErrorPos::Start => full.start .. full.start,
|
||||||
|
ErrorPos::End => full.end .. full.end,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Where in a node an error should be annotated,
|
||||||
|
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
|
||||||
|
pub enum ErrorPos {
|
||||||
|
/// Over the full width of the node.
|
||||||
|
Full,
|
||||||
|
/// At the start of the node.
|
||||||
|
Start,
|
||||||
|
/// At the end of the node.
|
||||||
|
End,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A part of an error's [trace](SourceError::trace).
|
/// A part of an error's [trace](SourceError::trace).
|
||||||
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd)]
|
#[derive(Debug, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||||
pub enum Tracepoint {
|
pub enum Tracepoint {
|
||||||
/// A function call.
|
/// A function call.
|
||||||
Call(Option<String>),
|
Call(Option<EcoString>),
|
||||||
/// A module import.
|
/// A module import.
|
||||||
Import,
|
Import,
|
||||||
}
|
}
|
||||||
@ -135,7 +169,7 @@ pub trait At<T> {
|
|||||||
|
|
||||||
impl<T, S> At<T> for Result<T, S>
|
impl<T, S> At<T> for Result<T, S>
|
||||||
where
|
where
|
||||||
S: Into<String>,
|
S: Into<EcoString>,
|
||||||
{
|
{
|
||||||
fn at(self, span: Span) -> SourceResult<T> {
|
fn at(self, span: Span) -> SourceResult<T> {
|
||||||
self.map_err(|message| Box::new(vec![error!(span, message)]))
|
self.map_err(|message| Box::new(vec![error!(span, message)]))
|
||||||
@ -204,9 +238,9 @@ impl From<FromUtf8Error> for FileError {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<FileError> for String {
|
impl From<FileError> for EcoString {
|
||||||
fn from(error: FileError) -> Self {
|
fn from(error: FileError) -> Self {
|
||||||
error.to_string()
|
format_eco!("{error}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -695,7 +695,7 @@ impl Eval for FuncCall {
|
|||||||
Value::Array(array) => array.get(args.into_index()?).at(self.span())?.clone(),
|
Value::Array(array) => array.get(args.into_index()?).at(self.span())?.clone(),
|
||||||
Value::Dict(dict) => dict.get(&args.into_key()?).at(self.span())?.clone(),
|
Value::Dict(dict) => dict.get(&args.into_key()?).at(self.span())?.clone(),
|
||||||
Value::Func(func) => {
|
Value::Func(func) => {
|
||||||
let point = || Tracepoint::Call(func.name().map(ToString::to_string));
|
let point = || Tracepoint::Call(func.name().map(Into::into));
|
||||||
func.call(vm, args).trace(vm.world, point, self.span())?
|
func.call(vm, args).trace(vm.world, point, self.span())?
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -713,8 +713,8 @@ impl Eval for MethodCall {
|
|||||||
|
|
||||||
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
fn eval(&self, vm: &mut Vm) -> SourceResult<Self::Output> {
|
||||||
let span = self.span();
|
let span = self.span();
|
||||||
let method = self.method();
|
let method = self.method().take();
|
||||||
let point = || Tracepoint::Call(Some(method.to_string()));
|
let point = || Tracepoint::Call(Some(method.clone()));
|
||||||
|
|
||||||
Ok(if methods::is_mutating(&method) {
|
Ok(if methods::is_mutating(&method) {
|
||||||
let args = self.args().eval(vm)?;
|
let args = self.args().eval(vm)?;
|
||||||
|
@ -323,7 +323,7 @@ fn print_diagnostics(
|
|||||||
|
|
||||||
for error in errors {
|
for error in errors {
|
||||||
// The main diagnostic.
|
// The main diagnostic.
|
||||||
let range = world.source(error.span.source()).range(error.span);
|
let range = error.range(world);
|
||||||
let diag = Diagnostic::error()
|
let diag = Diagnostic::error()
|
||||||
.with_message(error.message)
|
.with_message(error.message)
|
||||||
.with_labels(vec![Label::primary(error.span.source(), range)]);
|
.with_labels(vec![Label::primary(error.span.source(), range)]);
|
||||||
|
@ -11,8 +11,9 @@ pub use tokens::*;
|
|||||||
|
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
use crate::diag::ErrorPos;
|
||||||
use crate::syntax::ast::{Assoc, BinOp, UnOp};
|
use crate::syntax::ast::{Assoc, BinOp, UnOp};
|
||||||
use crate::syntax::{NodeKind, SpanPos, SyntaxNode};
|
use crate::syntax::{NodeKind, SyntaxNode};
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// Parse a source file.
|
/// Parse a source file.
|
||||||
@ -811,7 +812,7 @@ fn item(p: &mut Parser, keyed: bool) -> ParseResult<NodeKind> {
|
|||||||
msg.push_str(", found ");
|
msg.push_str(", found ");
|
||||||
msg.push_str(kind.name());
|
msg.push_str(kind.name());
|
||||||
}
|
}
|
||||||
let error = NodeKind::Error(SpanPos::Full, msg);
|
let error = NodeKind::Error(ErrorPos::Full, msg);
|
||||||
marker.end(p, error);
|
marker.end(p, error);
|
||||||
p.eat();
|
p.eat();
|
||||||
marker.perform(p, NodeKind::Named, expr).ok();
|
marker.perform(p, NodeKind::Named, expr).ok();
|
||||||
|
@ -3,7 +3,8 @@ use std::mem;
|
|||||||
use std::ops::Range;
|
use std::ops::Range;
|
||||||
|
|
||||||
use super::{TokenMode, Tokens};
|
use super::{TokenMode, Tokens};
|
||||||
use crate::syntax::{InnerNode, NodeData, NodeKind, SpanPos, SyntaxNode};
|
use crate::diag::ErrorPos;
|
||||||
|
use crate::syntax::{InnerNode, NodeData, NodeKind, SyntaxNode};
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// A convenient token-based parser.
|
/// A convenient token-based parser.
|
||||||
@ -398,7 +399,7 @@ impl Parser<'_> {
|
|||||||
pub fn unexpected(&mut self) {
|
pub fn unexpected(&mut self) {
|
||||||
if let Some(found) = self.peek() {
|
if let Some(found) = self.peek() {
|
||||||
let msg = format_eco!("unexpected {}", found.name());
|
let msg = format_eco!("unexpected {}", found.name());
|
||||||
let error = NodeKind::Error(SpanPos::Full, msg);
|
let error = NodeKind::Error(ErrorPos::Full, msg);
|
||||||
self.perform(error, Self::eat);
|
self.perform(error, Self::eat);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +413,7 @@ impl Parser<'_> {
|
|||||||
/// Insert an error message that `what` was expected at the marker position.
|
/// Insert an error message that `what` was expected at the marker position.
|
||||||
pub fn expected_at(&mut self, marker: Marker, what: &str) {
|
pub fn expected_at(&mut self, marker: Marker, what: &str) {
|
||||||
let msg = format_eco!("expected {}", what);
|
let msg = format_eco!("expected {}", what);
|
||||||
let error = NodeKind::Error(SpanPos::Full, msg);
|
let error = NodeKind::Error(ErrorPos::Full, msg);
|
||||||
self.children.insert(marker.0, NodeData::new(error, 0).into());
|
self.children.insert(marker.0, NodeData::new(error, 0).into());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -422,7 +423,7 @@ impl Parser<'_> {
|
|||||||
match self.peek() {
|
match self.peek() {
|
||||||
Some(found) => {
|
Some(found) => {
|
||||||
let msg = format_eco!("expected {}, found {}", thing, found.name());
|
let msg = format_eco!("expected {}, found {}", thing, found.name());
|
||||||
let error = NodeKind::Error(SpanPos::Full, msg);
|
let error = NodeKind::Error(ErrorPos::Full, msg);
|
||||||
self.perform(error, Self::eat);
|
self.perform(error, Self::eat);
|
||||||
}
|
}
|
||||||
None => self.expected(thing),
|
None => self.expected(thing),
|
||||||
@ -494,7 +495,7 @@ impl Marker {
|
|||||||
msg.push_str(", found ");
|
msg.push_str(", found ");
|
||||||
msg.push_str(child.kind().name());
|
msg.push_str(child.kind().name());
|
||||||
}
|
}
|
||||||
let error = NodeKind::Error(SpanPos::Full, msg);
|
let error = NodeKind::Error(ErrorPos::Full, msg);
|
||||||
let inner = mem::take(child);
|
let inner = mem::take(child);
|
||||||
*child = InnerNode::with_child(error, inner).into();
|
*child = InnerNode::with_child(error, inner).into();
|
||||||
}
|
}
|
||||||
|
@ -4,9 +4,10 @@ use unicode_xid::UnicodeXID;
|
|||||||
use unscanny::Scanner;
|
use unscanny::Scanner;
|
||||||
|
|
||||||
use super::resolve::{resolve_hex, resolve_raw, resolve_string};
|
use super::resolve::{resolve_hex, resolve_raw, resolve_string};
|
||||||
|
use crate::diag::ErrorPos;
|
||||||
use crate::geom::{AngleUnit, LengthUnit};
|
use crate::geom::{AngleUnit, LengthUnit};
|
||||||
use crate::syntax::ast::{RawNode, Unit};
|
use crate::syntax::ast::{RawNode, Unit};
|
||||||
use crate::syntax::{NodeKind, SpanPos};
|
use crate::syntax::NodeKind;
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// An iterator over the tokens of a string of source code.
|
/// An iterator over the tokens of a string of source code.
|
||||||
@ -109,7 +110,7 @@ impl<'s> Iterator for Tokens<'s> {
|
|||||||
'/' if self.s.eat_if('/') => self.line_comment(),
|
'/' if self.s.eat_if('/') => self.line_comment(),
|
||||||
'/' if self.s.eat_if('*') => self.block_comment(),
|
'/' if self.s.eat_if('*') => self.block_comment(),
|
||||||
'*' if self.s.eat_if('/') => {
|
'*' if self.s.eat_if('/') => {
|
||||||
NodeKind::Error(SpanPos::Full, "unexpected end of block comment".into())
|
NodeKind::Error(ErrorPos::Full, "unexpected end of block comment".into())
|
||||||
}
|
}
|
||||||
c if c.is_whitespace() => self.whitespace(c),
|
c if c.is_whitespace() => self.whitespace(c),
|
||||||
|
|
||||||
@ -279,13 +280,13 @@ impl<'s> Tokens<'s> {
|
|||||||
NodeKind::Escape(c)
|
NodeKind::Escape(c)
|
||||||
} else {
|
} else {
|
||||||
NodeKind::Error(
|
NodeKind::Error(
|
||||||
SpanPos::Full,
|
ErrorPos::Full,
|
||||||
"invalid unicode escape sequence".into(),
|
"invalid unicode escape sequence".into(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.terminated = false;
|
self.terminated = false;
|
||||||
NodeKind::Error(SpanPos::End, "expected closing brace".into())
|
NodeKind::Error(ErrorPos::End, "expected closing brace".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -388,7 +389,7 @@ impl<'s> Tokens<'s> {
|
|||||||
let remaining = backticks - found;
|
let remaining = backticks - found;
|
||||||
let noun = if remaining == 1 { "backtick" } else { "backticks" };
|
let noun = if remaining == 1 { "backtick" } else { "backticks" };
|
||||||
NodeKind::Error(
|
NodeKind::Error(
|
||||||
SpanPos::End,
|
ErrorPos::End,
|
||||||
if found == 0 {
|
if found == 0 {
|
||||||
format_eco!("expected {} {}", remaining, noun)
|
format_eco!("expected {} {}", remaining, noun)
|
||||||
} else {
|
} else {
|
||||||
@ -416,11 +417,11 @@ impl<'s> Tokens<'s> {
|
|||||||
if !label.is_empty() {
|
if !label.is_empty() {
|
||||||
NodeKind::Label(label.into())
|
NodeKind::Label(label.into())
|
||||||
} else {
|
} else {
|
||||||
NodeKind::Error(SpanPos::Full, "label cannot be empty".into())
|
NodeKind::Error(ErrorPos::Full, "label cannot be empty".into())
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
self.terminated = false;
|
self.terminated = false;
|
||||||
NodeKind::Error(SpanPos::End, "expected closing angle bracket".into())
|
NodeKind::Error(ErrorPos::End, "expected closing angle bracket".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -519,7 +520,7 @@ impl<'s> Tokens<'s> {
|
|||||||
'"' => self.string(),
|
'"' => self.string(),
|
||||||
|
|
||||||
// Invalid token.
|
// Invalid token.
|
||||||
_ => NodeKind::Error(SpanPos::Full, "not valid here".into()),
|
_ => NodeKind::Error(ErrorPos::Full, "not valid here".into()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -578,10 +579,10 @@ impl<'s> Tokens<'s> {
|
|||||||
"em" => NodeKind::Numeric(f, Unit::Em),
|
"em" => NodeKind::Numeric(f, Unit::Em),
|
||||||
"fr" => NodeKind::Numeric(f, Unit::Fr),
|
"fr" => NodeKind::Numeric(f, Unit::Fr),
|
||||||
"%" => NodeKind::Numeric(f, Unit::Percent),
|
"%" => NodeKind::Numeric(f, Unit::Percent),
|
||||||
_ => NodeKind::Error(SpanPos::Full, "invalid number suffix".into()),
|
_ => NodeKind::Error(ErrorPos::Full, "invalid number suffix".into()),
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
NodeKind::Error(SpanPos::Full, "invalid number".into())
|
NodeKind::Error(ErrorPos::Full, "invalid number".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -601,7 +602,7 @@ impl<'s> Tokens<'s> {
|
|||||||
NodeKind::Str(string)
|
NodeKind::Str(string)
|
||||||
} else {
|
} else {
|
||||||
self.terminated = false;
|
self.terminated = false;
|
||||||
NodeKind::Error(SpanPos::End, "expected quote".into())
|
NodeKind::Error(ErrorPos::End, "expected quote".into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -713,9 +714,9 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::parse::tests::check;
|
use crate::parse::tests::check;
|
||||||
|
|
||||||
|
use ErrorPos::*;
|
||||||
use NodeKind::*;
|
use NodeKind::*;
|
||||||
use Option::None;
|
use Option::None;
|
||||||
use SpanPos::*;
|
|
||||||
use TokenMode::{Code, Markup};
|
use TokenMode::{Code, Markup};
|
||||||
|
|
||||||
fn Space(newlines: usize) -> NodeKind {
|
fn Space(newlines: usize) -> NodeKind {
|
||||||
@ -742,7 +743,7 @@ mod tests {
|
|||||||
NodeKind::Ident(ident.into())
|
NodeKind::Ident(ident.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn Error(pos: SpanPos, message: &str) -> NodeKind {
|
fn Error(pos: ErrorPos, message: &str) -> NodeKind {
|
||||||
NodeKind::Error(pos, message.into())
|
NodeKind::Error(pos, message.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,7 +2,7 @@ use std::hash::{Hash, Hasher};
|
|||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use super::ast::{RawNode, Unit};
|
use super::ast::{RawNode, Unit};
|
||||||
use super::SpanPos;
|
use crate::diag::ErrorPos;
|
||||||
use crate::util::EcoString;
|
use crate::util::EcoString;
|
||||||
|
|
||||||
/// All syntactical building blocks that can be part of a Typst document.
|
/// All syntactical building blocks that can be part of a Typst document.
|
||||||
@ -271,7 +271,7 @@ pub enum NodeKind {
|
|||||||
ReturnExpr,
|
ReturnExpr,
|
||||||
|
|
||||||
/// An invalid sequence of characters.
|
/// An invalid sequence of characters.
|
||||||
Error(SpanPos, EcoString),
|
Error(ErrorPos, EcoString),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeKind {
|
impl NodeKind {
|
||||||
|
@ -73,7 +73,7 @@ impl SyntaxNode {
|
|||||||
|
|
||||||
match self.kind() {
|
match self.kind() {
|
||||||
NodeKind::Error(pos, message) => {
|
NodeKind::Error(pos, message) => {
|
||||||
vec![SourceError::new(self.span().with_pos(*pos), message)]
|
vec![SourceError::new(self.span(), message.clone()).with_pos(*pos)]
|
||||||
}
|
}
|
||||||
_ => self
|
_ => self
|
||||||
.children()
|
.children()
|
||||||
@ -535,14 +535,7 @@ impl NodeData {
|
|||||||
|
|
||||||
/// If the span points into this node, convert it to a byte range.
|
/// If the span points into this node, convert it to a byte range.
|
||||||
pub fn range(&self, span: Span, offset: usize) -> Option<Range<usize>> {
|
pub fn range(&self, span: Span, offset: usize) -> Option<Range<usize>> {
|
||||||
(span.with_pos(SpanPos::Full) == self.span).then(|| {
|
(self.span == span).then(|| offset .. offset + self.len())
|
||||||
let end = offset + self.len();
|
|
||||||
match span.pos() {
|
|
||||||
SpanPos::Full => offset .. end,
|
|
||||||
SpanPos::Start => offset .. offset,
|
|
||||||
SpanPos::End => end .. end,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -63,10 +63,10 @@ pub struct Span(NonZeroU64);
|
|||||||
|
|
||||||
impl Span {
|
impl Span {
|
||||||
// Data layout:
|
// Data layout:
|
||||||
// | 2 bits span pos | 16 bits source id | 46 bits number |
|
// | 16 bits source id | 48 bits number |
|
||||||
|
|
||||||
// Number of bits for and minimum and maximum numbers assignable to spans.
|
// Number of bits for and minimum and maximum numbers assignable to spans.
|
||||||
const BITS: usize = 46;
|
const BITS: usize = 48;
|
||||||
const DETACHED: u64 = 1;
|
const DETACHED: u64 = 1;
|
||||||
|
|
||||||
/// The full range of numbers available to spans.
|
/// The full range of numbers available to spans.
|
||||||
@ -90,12 +90,6 @@ impl Span {
|
|||||||
Self(to_non_zero(Self::DETACHED))
|
Self(to_non_zero(Self::DETACHED))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return this span, but with updated position.
|
|
||||||
pub const fn with_pos(self, pos: SpanPos) -> Self {
|
|
||||||
let bits = (self.0.get() & ((1 << 62) - 1)) | ((pos as u64) << 62);
|
|
||||||
Self(to_non_zero(bits))
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The id of the source file the span points into.
|
/// The id of the source file the span points into.
|
||||||
pub const fn source(self) -> SourceId {
|
pub const fn source(self) -> SourceId {
|
||||||
SourceId::from_u16((self.0.get() >> Self::BITS) as u16)
|
SourceId::from_u16((self.0.get() >> Self::BITS) as u16)
|
||||||
@ -105,16 +99,6 @@ impl Span {
|
|||||||
pub const fn number(self) -> u64 {
|
pub const fn number(self) -> u64 {
|
||||||
self.0.get() & ((1 << Self::BITS) - 1)
|
self.0.get() & ((1 << Self::BITS) - 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where in the node the span points to.
|
|
||||||
pub const fn pos(self) -> SpanPos {
|
|
||||||
match self.0.get() >> 62 {
|
|
||||||
0 => SpanPos::Full,
|
|
||||||
1 => SpanPos::Start,
|
|
||||||
2 => SpanPos::End,
|
|
||||||
_ => panic!("span pos encoding is invalid"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert to a non zero u64.
|
/// Convert to a non zero u64.
|
||||||
@ -125,17 +109,6 @@ const fn to_non_zero(v: u64) -> NonZeroU64 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Where in a node a span points.
|
|
||||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
|
||||||
pub enum SpanPos {
|
|
||||||
/// Over the full width of the node.
|
|
||||||
Full = 0,
|
|
||||||
/// At the start of the node.
|
|
||||||
Start = 1,
|
|
||||||
/// At the end of the node.
|
|
||||||
End = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Result of numbering a node within an interval.
|
/// Result of numbering a node within an interval.
|
||||||
pub type NumberingResult = Result<(), Unnumberable>;
|
pub type NumberingResult = Result<(), Unnumberable>;
|
||||||
|
|
||||||
@ -153,14 +126,13 @@ impl std::error::Error for Unnumberable {}
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::{SourceId, Span, SpanPos};
|
use super::{SourceId, Span};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_span_encoding() {
|
fn test_span_encoding() {
|
||||||
let id = SourceId::from_u16(5);
|
let id = SourceId::from_u16(5);
|
||||||
let span = Span::new(id, 10).with_pos(SpanPos::End);
|
let span = Span::new(id, 10);
|
||||||
assert_eq!(span.source(), id);
|
assert_eq!(span.source(), id);
|
||||||
assert_eq!(span.number(), 10);
|
assert_eq!(span.number(), 10);
|
||||||
assert_eq!(span.pos(), SpanPos::End);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -433,10 +433,7 @@ fn test_part(
|
|||||||
let mut errors: Vec<_> = errors
|
let mut errors: Vec<_> = errors
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.filter(|error| error.span.source() == id)
|
.filter(|error| error.span.source() == id)
|
||||||
.map(|error| {
|
.map(|error| (error.range(world), error.message.to_string()))
|
||||||
let range = world.source(error.span.source()).range(error.span);
|
|
||||||
(range, error.message.to_string())
|
|
||||||
})
|
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
errors.sort_by_key(|error| error.0.start);
|
errors.sort_by_key(|error| error.0.start);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user