mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Prevent duplicate named arguments and dictionary keys
This commit is contained in:
parent
938b0af889
commit
cd62792c0a
@ -12,6 +12,7 @@ pub use resolve::*;
|
|||||||
pub use scanner::*;
|
pub use scanner::*;
|
||||||
pub use tokens::*;
|
pub use tokens::*;
|
||||||
|
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use crate::syntax::ast::{Associativity, BinOp, UnOp};
|
use crate::syntax::ast::{Associativity, BinOp, UnOp};
|
||||||
@ -648,9 +649,20 @@ fn array(p: &mut Parser, marker: Marker) {
|
|||||||
/// Convert a collection into a dictionary, producing errors for anything other
|
/// Convert a collection into a dictionary, producing errors for anything other
|
||||||
/// than named pairs.
|
/// than named pairs.
|
||||||
fn dict(p: &mut Parser, marker: Marker) {
|
fn dict(p: &mut Parser, marker: Marker) {
|
||||||
|
let mut used = HashSet::new();
|
||||||
marker.filter_children(p, |x| match x.kind() {
|
marker.filter_children(p, |x| match x.kind() {
|
||||||
kind if kind.is_paren() => Ok(()),
|
kind if kind.is_paren() => Ok(()),
|
||||||
NodeKind::Named | NodeKind::Comma | NodeKind::Colon | NodeKind::Spread => Ok(()),
|
NodeKind::Named => {
|
||||||
|
if let Some(NodeKind::Ident(ident)) =
|
||||||
|
x.children().first().map(|child| child.kind())
|
||||||
|
{
|
||||||
|
if !used.insert(ident.clone()) {
|
||||||
|
return Err("pair has duplicate key");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
NodeKind::Comma | NodeKind::Colon | NodeKind::Spread => Ok(()),
|
||||||
_ => Err("expected named pair, found expression"),
|
_ => Err("expected named pair, found expression"),
|
||||||
});
|
});
|
||||||
marker.end(p, NodeKind::DictExpr);
|
marker.end(p, NodeKind::DictExpr);
|
||||||
@ -729,9 +741,24 @@ fn args(p: &mut Parser, direct: bool, brackets: bool) -> ParseResult {
|
|||||||
|
|
||||||
p.perform(NodeKind::CallArgs, |p| {
|
p.perform(NodeKind::CallArgs, |p| {
|
||||||
if p.at(&NodeKind::LeftParen) {
|
if p.at(&NodeKind::LeftParen) {
|
||||||
|
let marker = p.marker();
|
||||||
p.start_group(Group::Paren);
|
p.start_group(Group::Paren);
|
||||||
collection(p);
|
collection(p);
|
||||||
p.end_group();
|
p.end_group();
|
||||||
|
|
||||||
|
let mut used = HashSet::new();
|
||||||
|
marker.filter_children(p, |x| {
|
||||||
|
if x.kind() == &NodeKind::Named {
|
||||||
|
if let Some(NodeKind::Ident(ident)) =
|
||||||
|
x.children().first().map(|child| child.kind())
|
||||||
|
{
|
||||||
|
if !used.insert(ident.clone()) {
|
||||||
|
return Err("duplicate argument");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
while brackets && p.peek_direct() == Some(&NodeKind::LeftBracket) {
|
while brackets && p.peek_direct() == Some(&NodeKind::LeftBracket) {
|
||||||
|
@ -452,9 +452,9 @@ impl Marker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Wrap all children that do not fulfill the predicate in error nodes.
|
/// Wrap all children that do not fulfill the predicate in error nodes.
|
||||||
pub fn filter_children<F>(self, p: &mut Parser, f: F)
|
pub fn filter_children<F>(self, p: &mut Parser, mut f: F)
|
||||||
where
|
where
|
||||||
F: Fn(&Green) -> Result<(), &'static str>,
|
F: FnMut(&Green) -> Result<(), &'static str>,
|
||||||
{
|
{
|
||||||
for child in &mut p.children[self.0 ..] {
|
for child in &mut p.children[self.0 ..] {
|
||||||
// Don't expose errors.
|
// Don't expose errors.
|
||||||
|
@ -44,6 +44,10 @@
|
|||||||
test(adder(2)(5), 7)
|
test(adder(2)(5), 7)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 28-47 duplicate argument
|
||||||
|
#set text(family: "Arial", family: "Helvetica")
|
||||||
|
|
||||||
---
|
---
|
||||||
// Error: 2-6 expected callable or collection, found boolean
|
// Error: 2-6 expected callable or collection, found boolean
|
||||||
{true()}
|
{true()}
|
||||||
|
@ -35,6 +35,10 @@
|
|||||||
dict("b") += 1
|
dict("b") += 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
---
|
||||||
|
// Error: 24-32 pair has duplicate key
|
||||||
|
{(first: 1, second: 2, first: 3)}
|
||||||
|
|
||||||
---
|
---
|
||||||
// Simple expression after already being identified as a dictionary.
|
// Simple expression after already being identified as a dictionary.
|
||||||
// Error: 9-10 expected named pair, found expression
|
// Error: 9-10 expected named pair, found expression
|
||||||
|
Loading…
x
Reference in New Issue
Block a user