Wider callsite span (#3466)
This commit is contained in:
parent
23756f9e8b
commit
56ecd6c806
@ -56,7 +56,7 @@ impl Access for ast::FuncCall<'_> {
|
||||
if is_accessor_method(&method) {
|
||||
let span = self.span();
|
||||
let world = vm.world();
|
||||
let args = self.args().eval(vm)?;
|
||||
let args = self.args().eval(vm)?.spanned(span);
|
||||
let value = access.target().access(vm)?;
|
||||
let result = call_method_access(value, &method, args, span);
|
||||
let point = || Tracepoint::Call(Some(method.get().clone()));
|
||||
|
@ -12,7 +12,7 @@ use crate::introspection::{Introspector, Locator};
|
||||
use crate::math::{Accent, AccentElem, LrElem};
|
||||
use crate::symbols::Symbol;
|
||||
use crate::syntax::ast::{self, AstNode};
|
||||
use crate::syntax::{Spanned, SyntaxNode};
|
||||
use crate::syntax::{Span, Spanned, SyntaxNode};
|
||||
use crate::text::TextElem;
|
||||
use crate::util::LazyHash;
|
||||
use crate::World;
|
||||
@ -40,7 +40,7 @@ impl Eval for ast::FuncCall<'_> {
|
||||
let field_span = field.span();
|
||||
|
||||
let target = if is_mutating_method(&field) {
|
||||
let mut args = args.eval(vm)?;
|
||||
let mut args = args.eval(vm)?.spanned(span);
|
||||
let target = target.access(vm)?;
|
||||
|
||||
// Only arrays and dictionaries have mutable methods.
|
||||
@ -59,7 +59,7 @@ impl Eval for ast::FuncCall<'_> {
|
||||
access.target().eval(vm)?
|
||||
};
|
||||
|
||||
let mut args = args.eval(vm)?;
|
||||
let mut args = args.eval(vm)?.spanned(span);
|
||||
|
||||
// Handle plugins.
|
||||
if let Value::Plugin(plugin) = &target {
|
||||
@ -126,7 +126,7 @@ impl Eval for ast::FuncCall<'_> {
|
||||
bail!(error);
|
||||
}
|
||||
} else {
|
||||
(callee.eval(vm)?, args.eval(vm)?)
|
||||
(callee.eval(vm)?, args.eval(vm)?.spanned(span))
|
||||
};
|
||||
|
||||
// Handle math special cases for non-functions:
|
||||
@ -222,7 +222,9 @@ impl Eval for ast::Args<'_> {
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Args { span: self.span(), items })
|
||||
// We do *not* use the `self.span()` here because we want the callsite
|
||||
// span to be one level higher (the whole function call).
|
||||
Ok(Args { span: Span::detached(), items })
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -23,7 +23,7 @@ impl Eval for ast::SetRule<'_> {
|
||||
})
|
||||
})
|
||||
.at(target.span())?;
|
||||
let args = self.args().eval(vm)?;
|
||||
let args = self.args().eval(vm)?.spanned(self.span());
|
||||
Ok(target.set(&mut vm.engine, args)?.spanned(self.span()))
|
||||
}
|
||||
}
|
||||
|
@ -42,7 +42,8 @@ use crate::syntax::{Span, Spanned};
|
||||
#[derive(Clone, Hash)]
|
||||
#[allow(clippy::derived_hash_with_manual_eq)]
|
||||
pub struct Args {
|
||||
/// The span of the whole argument list.
|
||||
/// The callsite span for the function. This is not the span of the argument
|
||||
/// list itself, but of the whole function call.
|
||||
pub span: Span,
|
||||
/// The positional and named arguments.
|
||||
pub items: EcoVec<Arg>,
|
||||
@ -62,6 +63,14 @@ impl Args {
|
||||
Self { span, items }
|
||||
}
|
||||
|
||||
/// Attach a span to these arguments if they don't already have one.
|
||||
pub fn spanned(mut self, span: Span) -> Self {
|
||||
if self.span.is_detached() {
|
||||
self.span = span;
|
||||
}
|
||||
self
|
||||
}
|
||||
|
||||
/// Returns the number of remaining positional arguments.
|
||||
pub fn remaining(&self) -> usize {
|
||||
self.items.iter().filter(|slot| slot.name.is_none()).count()
|
||||
@ -345,8 +354,8 @@ pub trait IntoArgs {
|
||||
}
|
||||
|
||||
impl IntoArgs for Args {
|
||||
fn into_args(self, _: Span) -> Args {
|
||||
self
|
||||
fn into_args(self, fallback: Span) -> Args {
|
||||
self.spanned(fallback)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -114,11 +114,9 @@ pub fn pow(
|
||||
};
|
||||
|
||||
let result = match (base, exponent.v) {
|
||||
(Num::Int(a), Num::Int(b)) if b >= 0 => a
|
||||
.checked_pow(b as u32)
|
||||
.map(Num::Int)
|
||||
.ok_or("the result is too large")
|
||||
.at(span)?,
|
||||
(Num::Int(a), Num::Int(b)) if b >= 0 => {
|
||||
a.checked_pow(b as u32).map(Num::Int).ok_or_else(too_large).at(span)?
|
||||
}
|
||||
(a, b) => Num::Float(if a.float() == std::f64::consts::E {
|
||||
b.float().exp()
|
||||
} else if a.float() == 2.0 {
|
||||
@ -469,7 +467,7 @@ pub fn fact(
|
||||
/// The number whose factorial to calculate. Must be non-negative.
|
||||
number: u64,
|
||||
) -> StrResult<i64> {
|
||||
Ok(fact_impl(1, number).ok_or("the result is too large")?)
|
||||
Ok(fact_impl(1, number).ok_or_else(too_large)?)
|
||||
}
|
||||
|
||||
/// Calculates a permutation.
|
||||
@ -493,7 +491,7 @@ pub fn perm(
|
||||
return Ok(0);
|
||||
}
|
||||
|
||||
Ok(fact_impl(base - numbers + 1, base).ok_or("the result is too large")?)
|
||||
Ok(fact_impl(base - numbers + 1, base).ok_or_else(too_large)?)
|
||||
}
|
||||
|
||||
/// Calculates the product of a range of numbers. Used to calculate
|
||||
@ -528,7 +526,7 @@ pub fn binom(
|
||||
/// The lower coefficient. Must be non-negative.
|
||||
k: u64,
|
||||
) -> StrResult<i64> {
|
||||
Ok(binom_impl(n, k).ok_or("the result is too large")?)
|
||||
Ok(binom_impl(n, k).ok_or_else(too_large)?)
|
||||
}
|
||||
|
||||
/// Calculates a binomial coefficient, with `n` the upper coefficient and `k`
|
||||
@ -594,7 +592,7 @@ pub fn lcm(
|
||||
Ok(a.checked_div(gcd(a, b))
|
||||
.and_then(|gcd| gcd.checked_mul(b))
|
||||
.map(|v| v.abs())
|
||||
.ok_or("the return value is too large")?)
|
||||
.ok_or_else(too_large)?)
|
||||
}
|
||||
|
||||
/// Rounds a number down to the nearest integer.
|
||||
@ -974,3 +972,9 @@ cast! {
|
||||
v: f64 => Self::Float(v),
|
||||
v: Angle => Self::Angle(v),
|
||||
}
|
||||
|
||||
/// The error message when the result is too large to be represented.
|
||||
#[cold]
|
||||
fn too_large() -> &'static str {
|
||||
"the result is too large"
|
||||
}
|
||||
|
@ -31,7 +31,7 @@
|
||||
#test(f(a: _ => 5), 6)
|
||||
|
||||
---
|
||||
// Error: 18-20 missing argument: pattern parameter
|
||||
// Error: 17-20 missing argument: pattern parameter
|
||||
#let f(a: 10) = a() + 1
|
||||
#f(a: _ => 5)
|
||||
|
||||
|
@ -118,7 +118,7 @@
|
||||
let types(x, y) = "[" + str(type(x)) + ", " + str(type(y)) + "]"
|
||||
test(types(14%, 12pt), "[ratio, length]")
|
||||
|
||||
// Error: 13-21 missing argument: y
|
||||
// Error: 8-21 missing argument: y
|
||||
test(types("nope"), "[string, none]")
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,10 @@
|
||||
// Test that errors in show rules are delayed: There can be multiple at once.
|
||||
|
||||
---
|
||||
// Error: 26-34 panicked with: "hey1"
|
||||
// Error: 21-34 panicked with: "hey1"
|
||||
#show heading: _ => panic("hey1")
|
||||
|
||||
// Error: 25-33 panicked with: "hey2"
|
||||
// Error: 20-33 panicked with: "hey2"
|
||||
#show strong: _ => panic("hey2")
|
||||
|
||||
= Hello
|
||||
|
@ -128,6 +128,6 @@
|
||||
#{
|
||||
let f(..a, b, c, d) = none
|
||||
|
||||
// Error: 4-10 missing argument: d
|
||||
// Error: 3-10 missing argument: d
|
||||
f(1, 2)
|
||||
}
|
||||
|
@ -211,7 +211,7 @@
|
||||
#1.bit-rshift(-1)
|
||||
|
||||
---
|
||||
// Error: 10-16 zero to the power of zero is undefined
|
||||
// Error: 2-16 zero to the power of zero is undefined
|
||||
#calc.pow(0, 0)
|
||||
|
||||
---
|
||||
@ -219,7 +219,7 @@
|
||||
#calc.pow(2, 10000000000000000)
|
||||
|
||||
---
|
||||
// Error: 10-25 the result is too large
|
||||
// Error: 2-25 the result is too large
|
||||
#calc.pow(2, 2147483647)
|
||||
|
||||
---
|
||||
@ -227,7 +227,7 @@
|
||||
#calc.pow(2, calc.pow(2.0, 10000.0))
|
||||
|
||||
---
|
||||
// Error: 10-19 the result is not a real number
|
||||
// Error: 2-19 the result is not a real number
|
||||
#calc.pow(-1, 0.5)
|
||||
|
||||
---
|
||||
@ -259,7 +259,7 @@
|
||||
#calc.log(1, base: 0)
|
||||
|
||||
---
|
||||
// Error: 10-24 the result is not a real number
|
||||
// Error: 2-24 the result is not a real number
|
||||
#calc.log(10, base: -1)
|
||||
|
||||
---
|
||||
@ -268,7 +268,7 @@
|
||||
#test(calc.fact(5), 120)
|
||||
|
||||
---
|
||||
// Error: 11-15 the result is too large
|
||||
// Error: 2-15 the result is too large
|
||||
#calc.fact(21)
|
||||
|
||||
---
|
||||
@ -279,7 +279,7 @@
|
||||
#test(calc.perm(5, 6), 0)
|
||||
|
||||
---
|
||||
// Error: 11-19 the result is too large
|
||||
// Error: 2-19 the result is too large
|
||||
#calc.perm(21, 21)
|
||||
|
||||
---
|
||||
@ -311,11 +311,11 @@
|
||||
#test(calc.lcm(8, 0), 0)
|
||||
|
||||
---
|
||||
// Error: 10-41 the return value is too large
|
||||
// Error: 2-41 the result is too large
|
||||
#calc.lcm(15486487489457, 4874879896543)
|
||||
|
||||
---
|
||||
// Error: 10-12 expected at least one value
|
||||
// Error: 2-12 expected at least one value
|
||||
#calc.min()
|
||||
|
||||
---
|
||||
@ -339,7 +339,7 @@
|
||||
#test(range(10, 0, step: -3), (10, 7, 4, 1))
|
||||
|
||||
---
|
||||
// Error: 7-9 missing argument: end
|
||||
// Error: 2-9 missing argument: end
|
||||
#range()
|
||||
|
||||
---
|
||||
|
@ -35,7 +35,7 @@
|
||||
// Mix in hue-based space.
|
||||
#test(rgb(color.mix(red, blue, space: color.hsl)), rgb("#c408ff"))
|
||||
#test(rgb(color.mix((red, 50%), (blue, 100%), space: color.hsl)), rgb("#5100f8"))
|
||||
// Error: 15-51 cannot mix more than two colors in a hue-based space
|
||||
// Error: 6-51 cannot mix more than two colors in a hue-based space
|
||||
#rgb(color.mix(red, blue, white, space: color.hsl))
|
||||
|
||||
---
|
||||
@ -127,11 +127,11 @@
|
||||
#rgb("lol")
|
||||
|
||||
---
|
||||
// Error: 5-7 missing argument: red component
|
||||
// Error: 2-7 missing argument: red component
|
||||
#rgb()
|
||||
|
||||
---
|
||||
// Error: 5-11 missing argument: blue component
|
||||
// Error: 2-11 missing argument: blue component
|
||||
#rgb(0, 1)
|
||||
|
||||
---
|
||||
@ -181,7 +181,7 @@
|
||||
#envelope.fly
|
||||
|
||||
---
|
||||
// Error: 8-10 expected at least one variant
|
||||
// Error: 2-10 expected at least one variant
|
||||
#symbol()
|
||||
|
||||
---
|
||||
@ -223,7 +223,7 @@
|
||||
#str.from-unicode(-1)
|
||||
|
||||
---
|
||||
// Error: 18-28 0x110000 is not a valid codepoint
|
||||
// Error: 2-28 0x110000 is not a valid codepoint
|
||||
#str.from-unicode(0x110000) // 0x10ffff is the highest valid code point
|
||||
|
||||
---
|
||||
@ -284,15 +284,15 @@
|
||||
#test(datetime.today(offset: 2).display(), "1970-01-01")
|
||||
|
||||
---
|
||||
// Error: 10-12 at least one of date or time must be fully specified
|
||||
// Error: 2-12 at least one of date or time must be fully specified
|
||||
#datetime()
|
||||
|
||||
---
|
||||
// Error: 10-42 time is invalid
|
||||
// Error: 2-42 time is invalid
|
||||
#datetime(hour: 25, minute: 0, second: 0)
|
||||
|
||||
---
|
||||
// Error: 10-41 date is invalid
|
||||
// Error: 2-41 date is invalid
|
||||
#datetime(year: 2000, month: 2, day: 30)
|
||||
|
||||
---
|
||||
|
@ -12,27 +12,27 @@
|
||||
|
||||
---
|
||||
// Test panic.
|
||||
// Error: 7-9 panicked
|
||||
// Error: 2-9 panicked
|
||||
#panic()
|
||||
|
||||
---
|
||||
// Test panic.
|
||||
// Error: 7-12 panicked with: 123
|
||||
// Error: 2-12 panicked with: 123
|
||||
#panic(123)
|
||||
|
||||
---
|
||||
// Test panic.
|
||||
// Error: 7-24 panicked with: "this is wrong"
|
||||
// Error: 2-24 panicked with: "this is wrong"
|
||||
#panic("this is wrong")
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 8-16 assertion failed
|
||||
// Error: 2-16 assertion failed
|
||||
#assert(1 == 2)
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 8-51 assertion failed: two is smaller than one
|
||||
// Error: 2-51 assertion failed: two is smaller than one
|
||||
#assert(2 < 1, message: "two is smaller than one")
|
||||
|
||||
---
|
||||
@ -42,22 +42,22 @@
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 11-19 equality assertion failed: value 10 was not equal to 11
|
||||
// Error: 2-19 equality assertion failed: value 10 was not equal to 11
|
||||
#assert.eq(10, 11)
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 11-55 equality assertion failed: 10 and 12 are not equal
|
||||
// Error: 2-55 equality assertion failed: 10 and 12 are not equal
|
||||
#assert.eq(10, 12, message: "10 and 12 are not equal")
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 11-19 inequality assertion failed: value 11 was equal to 11
|
||||
// Error: 2-19 inequality assertion failed: value 11 was equal to 11
|
||||
#assert.ne(11, 11)
|
||||
|
||||
---
|
||||
// Test failing assertions.
|
||||
// Error: 11-57 inequality assertion failed: must be different from 11
|
||||
// Error: 2-57 inequality assertion failed: must be different from 11
|
||||
#assert.ne(11, 11, message: "must be different from 11")
|
||||
|
||||
---
|
||||
|
@ -42,5 +42,5 @@ A #h(1fr) B
|
||||
|
||||
---
|
||||
// Missing spacing.
|
||||
// Error: 11-13 missing argument: amount
|
||||
// Error: 10-13 missing argument: amount
|
||||
Totally #h() ignored
|
||||
|
@ -21,7 +21,7 @@ $ binom(circle, square) $
|
||||
$ binom(n, k_1, k_2, k_3) $
|
||||
|
||||
---
|
||||
// Error: 8-13 missing argument: lower
|
||||
// Error: 3-13 missing argument: lower
|
||||
$ binom(x^2) $
|
||||
|
||||
---
|
||||
|
@ -27,7 +27,7 @@ Hello
|
||||
#set document(title: [Hello])
|
||||
|
||||
---
|
||||
// Error: 10-12 can only be used in set rules
|
||||
// Error: 2-12 can only be used in set rules
|
||||
#document()
|
||||
|
||||
---
|
||||
|
@ -28,5 +28,5 @@
|
||||
}
|
||||
|
||||
---
|
||||
// Error: 7-9 missing argument: words
|
||||
// Error: 2-9 missing argument: words
|
||||
#lorem()
|
||||
|
@ -66,7 +66,7 @@ A #box(image("/files/tiger.jpg", height: 1cm, width: 80%)) B
|
||||
#image.decode(`<svg xmlns="http://www.w3.org/2000/svg" height="140" width="500"><ellipse cx="200" cy="80" rx="100" ry="50" style="fill:yellow;stroke:purple;stroke-width:2" /></svg>`.text, format: "svg")
|
||||
|
||||
---
|
||||
// Error: 14-168 failed to parse SVG (missing root node)
|
||||
// Error: 2-168 failed to parse SVG (missing root node)
|
||||
#image.decode(`<svg height="140" width="500"><ellipse cx="200" cy="80" rx="100" ry="50" style="fill:yellow;stroke:purple;stroke-width:2" /></svg>`.text, format: "svg")
|
||||
|
||||
---
|
||||
@ -78,5 +78,5 @@ A #box(image("/files/tiger.jpg", height: 1cm, width: 80%)) B
|
||||
#image.decode(read("/files/tiger.jpg", encoding: none), format: "jpg", width: 80%)
|
||||
|
||||
---
|
||||
// Error: 14-83 failed to decode image (Format error decoding Png: Invalid PNG signature.)
|
||||
// Error: 2-83 failed to decode image (Format error decoding Png: Invalid PNG signature.)
|
||||
#image.decode(read("/files/tiger.jpg", encoding: none), format: "png", width: 80%)
|
||||
|
@ -14,6 +14,6 @@
|
||||
)
|
||||
|
||||
---
|
||||
// Error: 22-52 pattern tile size must be non-zero
|
||||
// Hint: 22-52 try setting the size manually
|
||||
// Error: 15-52 pattern tile size must be non-zero
|
||||
// Hint: 15-52 try setting the size manually
|
||||
#line(stroke: pattern(path((0pt, 0pt), (1em, 0pt))))
|
||||
|
Loading…
x
Reference in New Issue
Block a user