difftreelog
refactor virtual file handling
in: master
4 files changed
crates/jrsonnet-parser/Cargo.tomldiffbeforeafterboth--- a/crates/jrsonnet-parser/Cargo.toml
+++ b/crates/jrsonnet-parser/Cargo.toml
@@ -11,6 +11,7 @@
[dependencies]
jrsonnet-interner = { path = "../jrsonnet-interner", version = "0.4.2" }
+static_assertions = "1.1.0"
peg = "0.8.0"
crates/jrsonnet-parser/src/expr.rsdiffbeforeafterboth1use std::{2 fmt::{Debug, Display},3 ops::Deref,4 path::{Path, PathBuf},5 rc::Rc,6};78use gcmodule::Trace;9use jrsonnet_interner::IStr;10#[cfg(feature = "serde")]11use serde::{Deserialize, Serialize};1213#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]14#[derive(Debug, PartialEq, Trace)]15pub enum FieldName {16 /// {fixed: 2}17 Fixed(IStr),18 /// {["dyn"+"amic"]: 3}19 Dyn(LocExpr),20}2122#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]23#[derive(Debug, Clone, Copy, PartialEq, Trace)]24pub enum Visibility {25 /// :26 Normal,27 /// ::28 Hidden,29 /// :::30 Unhide,31}3233impl Visibility {34 pub fn is_visible(&self) -> bool {35 matches!(self, Self::Normal | Self::Unhide)36 }37}3839#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]40#[derive(Clone, Debug, PartialEq, Trace)]41pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4243#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]44#[derive(Debug, PartialEq, Trace)]45pub struct FieldMember {46 pub name: FieldName,47 pub plus: bool,48 pub params: Option<ParamsDesc>,49 pub visibility: Visibility,50 pub value: LocExpr,51}5253#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]54#[derive(Debug, PartialEq, Trace)]55pub enum Member {56 Field(FieldMember),57 BindStmt(BindSpec),58 AssertStmt(AssertStmt),59}6061#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]62#[derive(Debug, Clone, Copy, PartialEq, Trace)]63pub enum UnaryOpType {64 Plus,65 Minus,66 BitNot,67 Not,68}6970impl Display for UnaryOpType {71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {72 use UnaryOpType::*;73 write!(74 f,75 "{}",76 match self {77 Plus => "+",78 Minus => "-",79 BitNot => "~",80 Not => "!",81 }82 )83 }84}8586#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]87#[derive(Debug, Clone, Copy, PartialEq, Trace)]88pub enum BinaryOpType {89 Mul,90 Div,9192 /// Implemented as intrinsic, put here for completeness93 Mod,9495 Add,96 Sub,9798 Lhs,99 Rhs,100101 Lt,102 Gt,103 Lte,104 Gte,105106 BitAnd,107 BitOr,108 BitXor,109110 Eq,111 Neq,112113 And,114 Or,115116 // Equialent to std.objectHasEx(a, b, true)117 In,118}119120impl Display for BinaryOpType {121 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {122 use BinaryOpType::*;123 write!(124 f,125 "{}",126 match self {127 Mul => "*",128 Div => "/",129 Mod => "%",130 Add => "+",131 Sub => "-",132 Lhs => "<<",133 Rhs => ">>",134 Lt => "<",135 Gt => ">",136 Lte => "<=",137 Gte => ">=",138 BitAnd => "&",139 BitOr => "|",140 BitXor => "^",141 Eq => "==",142 Neq => "!=",143 And => "&&",144 Or => "||",145 In => "in",146 }147 )148 }149}150151/// name, default value152#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]153#[derive(Debug, PartialEq, Trace)]154pub struct Param(pub IStr, pub Option<LocExpr>);155156/// Defined function parameters157#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]158#[derive(Debug, Clone, PartialEq, Trace)]159pub struct ParamsDesc(pub Rc<Vec<Param>>);160161impl Deref for ParamsDesc {162 type Target = Vec<Param>;163 fn deref(&self) -> &Self::Target {164 &self.0165 }166}167168#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]169#[derive(Debug, PartialEq, Trace)]170pub struct ArgsDesc {171 pub unnamed: Vec<LocExpr>,172 pub named: Vec<(IStr, LocExpr)>,173}174impl ArgsDesc {175 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {176 Self { unnamed, named }177 }178}179180#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]181#[derive(Debug, Clone, PartialEq, Trace)]182pub enum DestructRest {183 /// ...rest184 Keep(IStr),185 /// ...186 Drop,187}188189#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]190#[derive(Debug, Clone, PartialEq, Trace)]191pub enum Destruct {192 Full(IStr),193 #[cfg(feature = "exp-destruct")]194 Skip,195 #[cfg(feature = "exp-destruct")]196 Array {197 start: Vec<Destruct>,198 rest: Option<DestructRest>,199 end: Vec<Destruct>,200 },201 #[cfg(feature = "exp-destruct")]202 Object {203 fields: Vec<(IStr, Option<Destruct>)>,204 rest: Option<DestructRest>,205 },206}207impl Destruct {208 pub fn name(&self) -> Option<IStr> {209 match self {210 Self::Full(name) => Some(name.clone()),211 #[cfg(feature = "exp-destruct")]212 _ => None,213 }214 }215}216217#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]218#[derive(Debug, Clone, PartialEq, Trace)]219pub enum BindSpec {220 Field {221 into: Destruct,222 value: LocExpr,223 },224 Function {225 name: IStr,226 params: ParamsDesc,227 value: LocExpr,228 },229}230231#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]232#[derive(Debug, PartialEq, Trace)]233pub struct IfSpecData(pub LocExpr);234235#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]236#[derive(Debug, PartialEq, Trace)]237pub struct ForSpecData(pub IStr, pub LocExpr);238239#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]240#[derive(Debug, PartialEq, Trace)]241pub enum CompSpec {242 IfSpec(IfSpecData),243 ForSpec(ForSpecData),244}245246#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]247#[derive(Debug, PartialEq, Trace)]248pub struct ObjComp {249 pub pre_locals: Vec<BindSpec>,250 pub key: LocExpr,251 pub plus: bool,252 pub value: LocExpr,253 pub post_locals: Vec<BindSpec>,254 pub compspecs: Vec<CompSpec>,255}256257#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]258#[derive(Debug, PartialEq, Trace)]259pub enum ObjBody {260 MemberList(Vec<Member>),261 ObjComp(ObjComp),262}263264#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]265#[derive(Debug, PartialEq, Clone, Copy, Trace)]266pub enum LiteralType {267 This,268 Super,269 Dollar,270 Null,271 True,272 False,273}274275#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]276#[derive(Debug, PartialEq, Trace)]277pub struct SliceDesc {278 pub start: Option<LocExpr>,279 pub end: Option<LocExpr>,280 pub step: Option<LocExpr>,281}282283/// Syntax base284#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]285#[derive(Debug, PartialEq, Trace)]286pub enum Expr {287 Literal(LiteralType),288289 /// String value: "hello"290 Str(IStr),291 /// Number: 1, 2.0, 2e+20292 Num(f64),293 /// Variable name: test294 Var(IStr),295296 /// Array of expressions: [1, 2, "Hello"]297 Arr(Vec<LocExpr>),298 /// Array comprehension:299 /// ```jsonnet300 /// ingredients: [301 /// { kind: kind, qty: 4 / 3 }302 /// for kind in [303 /// 'Honey Syrup',304 /// 'Lemon Juice',305 /// 'Farmers Gin',306 /// ]307 /// ],308 /// ```309 ArrComp(LocExpr, Vec<CompSpec>),310311 /// Object: {a: 2}312 Obj(ObjBody),313 /// Object extension: var1 {b: 2}314 ObjExtend(LocExpr, ObjBody),315316 /// (obj)317 Parened(LocExpr),318319 /// -2320 UnaryOp(UnaryOpType, LocExpr),321 /// 2 - 2322 BinaryOp(LocExpr, BinaryOpType, LocExpr),323 /// assert 2 == 2 : "Math is broken"324 AssertExpr(AssertStmt, LocExpr),325 /// local a = 2; { b: a }326 LocalExpr(Vec<BindSpec>, LocExpr),327328 /// import "hello"329 Import(PathBuf),330 /// importStr "file.txt"331 ImportStr(PathBuf),332 /// importBin "file.txt"333 ImportBin(PathBuf),334 /// error "I'm broken"335 ErrorStmt(LocExpr),336 /// a(b, c)337 Apply(LocExpr, ArgsDesc, bool),338 /// a[b]339 Index(LocExpr, LocExpr),340 /// function(x) x341 Function(ParamsDesc, LocExpr),342 /// std.thisFile343 IntrinsicThisFile,344 /// std.id,345 IntrinsicId,346 /// std.primitiveEquals347 Intrinsic(IStr),348 /// if true == false then 1 else 2349 IfElse {350 cond: IfSpecData,351 cond_then: LocExpr,352 cond_else: Option<LocExpr>,353 },354 Slice(LocExpr, SliceDesc),355}356357/// file, begin offset, end offset358#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]359#[derive(Clone, PartialEq, Trace)]360#[skip_trace]361pub struct ExprLocation(pub Rc<Path>, pub usize, pub usize);362impl ExprLocation {363 pub fn belongs_to(&self, other: &ExprLocation) -> bool {364 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2365 }366}367368impl Debug for ExprLocation {369 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {370 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)371 }372}373374/// Holds AST expression and its location in source file375#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]376#[derive(Clone, PartialEq, Trace)]377pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);378379impl Debug for LocExpr {380 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {381 if f.alternate() {382 write!(f, "{:#?}", self.0)?;383 } else {384 write!(f, "{:?}", self.0)?;385 }386 write!(f, " from {:?}", self.1)?;387 Ok(())388 }389}1use std::{2 fmt::{self, Debug, Display},3 ops::Deref,4 rc::Rc,5};67use gcmodule::Trace;8use jrsonnet_interner::IStr;9#[cfg(feature = "serde")]10use serde::{Deserialize, Serialize};1112use crate::source::Source;1314#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]15#[derive(Debug, PartialEq, Trace)]16pub enum FieldName {17 /// {fixed: 2}18 Fixed(IStr),19 /// {["dyn"+"amic"]: 3}20 Dyn(LocExpr),21}2223#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]24#[derive(Debug, Clone, Copy, PartialEq, Trace)]25pub enum Visibility {26 /// :27 Normal,28 /// ::29 Hidden,30 /// :::31 Unhide,32}3334impl Visibility {35 pub fn is_visible(&self) -> bool {36 matches!(self, Self::Normal | Self::Unhide)37 }38}3940#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]41#[derive(Clone, Debug, PartialEq, Trace)]42pub struct AssertStmt(pub LocExpr, pub Option<LocExpr>);4344#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]45#[derive(Debug, PartialEq, Trace)]46pub struct FieldMember {47 pub name: FieldName,48 pub plus: bool,49 pub params: Option<ParamsDesc>,50 pub visibility: Visibility,51 pub value: LocExpr,52}5354#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]55#[derive(Debug, PartialEq, Trace)]56pub enum Member {57 Field(FieldMember),58 BindStmt(BindSpec),59 AssertStmt(AssertStmt),60}6162#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]63#[derive(Debug, Clone, Copy, PartialEq, Trace)]64pub enum UnaryOpType {65 Plus,66 Minus,67 BitNot,68 Not,69}7071impl Display for UnaryOpType {72 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {73 use UnaryOpType::*;74 write!(75 f,76 "{}",77 match self {78 Plus => "+",79 Minus => "-",80 BitNot => "~",81 Not => "!",82 }83 )84 }85}8687#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]88#[derive(Debug, Clone, Copy, PartialEq, Trace)]89pub enum BinaryOpType {90 Mul,91 Div,9293 /// Implemented as intrinsic, put here for completeness94 Mod,9596 Add,97 Sub,9899 Lhs,100 Rhs,101102 Lt,103 Gt,104 Lte,105 Gte,106107 BitAnd,108 BitOr,109 BitXor,110111 Eq,112 Neq,113114 And,115 Or,116117 // Equialent to std.objectHasEx(a, b, true)118 In,119}120121impl Display for BinaryOpType {122 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {123 use BinaryOpType::*;124 write!(125 f,126 "{}",127 match self {128 Mul => "*",129 Div => "/",130 Mod => "%",131 Add => "+",132 Sub => "-",133 Lhs => "<<",134 Rhs => ">>",135 Lt => "<",136 Gt => ">",137 Lte => "<=",138 Gte => ">=",139 BitAnd => "&",140 BitOr => "|",141 BitXor => "^",142 Eq => "==",143 Neq => "!=",144 And => "&&",145 Or => "||",146 In => "in",147 }148 )149 }150}151152/// name, default value153#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]154#[derive(Debug, PartialEq, Trace)]155pub struct Param(pub IStr, pub Option<LocExpr>);156157/// Defined function parameters158#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]159#[derive(Debug, Clone, PartialEq, Trace)]160pub struct ParamsDesc(pub Rc<Vec<Param>>);161162impl Deref for ParamsDesc {163 type Target = Vec<Param>;164 fn deref(&self) -> &Self::Target {165 &self.0166 }167}168169#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]170#[derive(Debug, PartialEq, Trace)]171pub struct ArgsDesc {172 pub unnamed: Vec<LocExpr>,173 pub named: Vec<(IStr, LocExpr)>,174}175impl ArgsDesc {176 pub fn new(unnamed: Vec<LocExpr>, named: Vec<(IStr, LocExpr)>) -> Self {177 Self { unnamed, named }178 }179}180181#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]182#[derive(Debug, Clone, PartialEq, Trace)]183pub enum DestructRest {184 /// ...rest185 Keep(IStr),186 /// ...187 Drop,188}189190#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]191#[derive(Debug, Clone, PartialEq, Trace)]192pub enum Destruct {193 Full(IStr),194 #[cfg(feature = "exp-destruct")]195 Skip,196 #[cfg(feature = "exp-destruct")]197 Array {198 start: Vec<Destruct>,199 rest: Option<DestructRest>,200 end: Vec<Destruct>,201 },202 #[cfg(feature = "exp-destruct")]203 Object {204 fields: Vec<(IStr, Option<Destruct>)>,205 rest: Option<DestructRest>,206 },207}208impl Destruct {209 pub fn name(&self) -> Option<IStr> {210 match self {211 Self::Full(name) => Some(name.clone()),212 #[cfg(feature = "exp-destruct")]213 _ => None,214 }215 }216}217218#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]219#[derive(Debug, Clone, PartialEq, Trace)]220pub enum BindSpec {221 Field {222 into: Destruct,223 value: LocExpr,224 },225 Function {226 name: IStr,227 params: ParamsDesc,228 value: LocExpr,229 },230}231232#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]233#[derive(Debug, PartialEq, Trace)]234pub struct IfSpecData(pub LocExpr);235236#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]237#[derive(Debug, PartialEq, Trace)]238pub struct ForSpecData(pub IStr, pub LocExpr);239240#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]241#[derive(Debug, PartialEq, Trace)]242pub enum CompSpec {243 IfSpec(IfSpecData),244 ForSpec(ForSpecData),245}246247#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]248#[derive(Debug, PartialEq, Trace)]249pub struct ObjComp {250 pub pre_locals: Vec<BindSpec>,251 pub key: LocExpr,252 pub plus: bool,253 pub value: LocExpr,254 pub post_locals: Vec<BindSpec>,255 pub compspecs: Vec<CompSpec>,256}257258#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]259#[derive(Debug, PartialEq, Trace)]260pub enum ObjBody {261 MemberList(Vec<Member>),262 ObjComp(ObjComp),263}264265#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]266#[derive(Debug, PartialEq, Clone, Copy, Trace)]267pub enum LiteralType {268 This,269 Super,270 Dollar,271 Null,272 True,273 False,274}275276#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]277#[derive(Debug, PartialEq, Trace)]278pub struct SliceDesc {279 pub start: Option<LocExpr>,280 pub end: Option<LocExpr>,281 pub step: Option<LocExpr>,282}283284/// Syntax base285#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]286#[derive(Debug, PartialEq, Trace)]287pub enum Expr {288 Literal(LiteralType),289290 /// String value: "hello"291 Str(IStr),292 /// Number: 1, 2.0, 2e+20293 Num(f64),294 /// Variable name: test295 Var(IStr),296297 /// Array of expressions: [1, 2, "Hello"]298 Arr(Vec<LocExpr>),299 /// Array comprehension:300 /// ```jsonnet301 /// ingredients: [302 /// { kind: kind, qty: 4 / 3 }303 /// for kind in [304 /// 'Honey Syrup',305 /// 'Lemon Juice',306 /// 'Farmers Gin',307 /// ]308 /// ],309 /// ```310 ArrComp(LocExpr, Vec<CompSpec>),311312 /// Object: {a: 2}313 Obj(ObjBody),314 /// Object extension: var1 {b: 2}315 ObjExtend(LocExpr, ObjBody),316317 /// (obj)318 Parened(LocExpr),319320 /// -2321 UnaryOp(UnaryOpType, LocExpr),322 /// 2 - 2323 BinaryOp(LocExpr, BinaryOpType, LocExpr),324 /// assert 2 == 2 : "Math is broken"325 AssertExpr(AssertStmt, LocExpr),326 /// local a = 2; { b: a }327 LocalExpr(Vec<BindSpec>, LocExpr),328329 /// import "hello"330 Import(IStr),331 /// importStr "file.txt"332 ImportStr(IStr),333 /// importBin "file.txt"334 ImportBin(IStr),335 /// error "I'm broken"336 ErrorStmt(LocExpr),337 /// a(b, c)338 Apply(LocExpr, ArgsDesc, bool),339 /// a[b]340 Index(LocExpr, LocExpr),341 /// function(x) x342 Function(ParamsDesc, LocExpr),343 /// std.thisFile344 IntrinsicThisFile,345 /// std.id,346 IntrinsicId,347 /// std.primitiveEquals348 Intrinsic(IStr),349 /// if true == false then 1 else 2350 IfElse {351 cond: IfSpecData,352 cond_then: LocExpr,353 cond_else: Option<LocExpr>,354 },355 Slice(LocExpr, SliceDesc),356}357358/// file, begin offset, end offset359#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]360#[derive(Clone, PartialEq, Trace)]361#[skip_trace]362#[repr(C)]363pub struct ExprLocation(pub Source, pub u32, pub u32);364impl ExprLocation {365 pub fn belongs_to(&self, other: &ExprLocation) -> bool {366 other.0 == self.0 && other.1 <= self.1 && other.2 >= self.2367 }368}369370#[cfg(target_pointer_width = "64")]371static_assertions::assert_eq_size!(ExprLocation, [u8; 16]);372373impl Debug for ExprLocation {374 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {375 write!(f, "{:?}:{:?}-{:?}", self.0, self.1, self.2)376 }377}378379/// Holds AST expression and its location in source file380#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]381#[derive(Clone, PartialEq, Trace)]382pub struct LocExpr(pub Rc<Expr>, pub ExprLocation);383384#[cfg(target_pointer_width = "64")]385static_assertions::assert_eq_size!(LocExpr, [u8; 24]);386387impl Debug for LocExpr {388 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {389 if f.alternate() {390 write!(f, "{:#?}", self.0)?;391 } else {392 write!(f, "{:?}", self.0)?;393 }394 write!(f, " from {:?}", self.1)?;395 Ok(())396 }397}crates/jrsonnet-parser/src/lib.rsdiffbeforeafterboth--- a/crates/jrsonnet-parser/src/lib.rs
+++ b/crates/jrsonnet-parser/src/lib.rs
@@ -1,19 +1,18 @@
#![allow(clippy::redundant_closure_call)]
-use std::{
- path::{Path, PathBuf},
- rc::Rc,
-};
+use std::rc::Rc;
use peg::parser;
mod expr;
pub use expr::*;
pub use jrsonnet_interner::IStr;
pub use peg;
+mod source;
mod unescape;
+pub use source::Source;
pub struct ParserSettings {
- pub file_name: Rc<Path>,
+ pub file_name: Source,
}
macro_rules! expr_bin {
@@ -232,7 +231,7 @@
pub rule var_expr(s: &ParserSettings) -> Expr
= n:id() { expr::Expr::Var(n) }
pub rule id_loc(s: &ParserSettings) -> LocExpr
- = a:position!() n:id() b:position!() { LocExpr(Rc::new(expr::Expr::Str(n)), ExprLocation(s.file_name.clone(), a,b)) }
+ = a:position!() n:id() b:position!() { LocExpr(Rc::new(expr::Expr::Str(n)), ExprLocation(s.file_name.clone(), a as u32,b as u32)) }
pub rule if_then_else_expr(s: &ParserSettings) -> Expr
= cond:ifspec(s) _ keyword("then") _ cond_then:expr(s) cond_else:(_ keyword("else") _ e:expr(s) {e})? {Expr::IfElse{
cond,
@@ -263,9 +262,9 @@
/ array_expr(s)
/ array_comp_expr(s)
- / keyword("importstr") _ path:string() {Expr::ImportStr(PathBuf::from(path))}
- / keyword("importbin") _ path:string() {Expr::ImportBin(PathBuf::from(path))}
- / keyword("import") _ path:string() {Expr::Import(PathBuf::from(path))}
+ / keyword("importstr") _ path:string() {Expr::ImportStr(path.into())}
+ / keyword("importbin") _ path:string() {Expr::ImportBin(path.into())}
+ / keyword("import") _ path:string() {Expr::Import(path.into())}
/ var_expr(s)
/ local_expr(s)
@@ -299,7 +298,7 @@
use UnaryOpType::*;
rule expr(s: &ParserSettings) -> LocExpr
= precedence! {
- start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.file_name.clone(), start, end)) }
+ start:position!() v:@ end:position!() { LocExpr(Rc::new(v), ExprLocation(s.file_name.clone(), start as u32, end as u32)) }
--
a:(@) _ binop(<"||">) _ b:@ {expr_bin!(a Or b)}
--
@@ -357,7 +356,7 @@
let len = str.len();
LocExpr(
Rc::new(Expr::Str(str)),
- ExprLocation(settings.file_name.clone(), 0, len),
+ ExprLocation(settings.file_name.clone(), 0, len as u32),
)
}
@@ -368,14 +367,14 @@
use BinaryOpType::*;
use super::{expr::*, parse};
- use crate::ParserSettings;
+ use crate::{source::Source, ParserSettings};
macro_rules! parse {
($s:expr) => {
parse(
$s,
&ParserSettings {
- file_name: PathBuf::from("test.jsonnet").into(),
+ file_name: Source::new(PathBuf::from("test.jsonnet")).unwrap(),
},
)
.unwrap()
@@ -386,7 +385,11 @@
($expr:expr, $from:expr, $to:expr$(,)?) => {
LocExpr(
std::rc::Rc::new($expr),
- ExprLocation(PathBuf::from("test.jsonnet").into(), $from, $to),
+ ExprLocation(
+ Source::new(PathBuf::from("test.jsonnet")).unwrap(),
+ $from,
+ $to,
+ ),
)
};
}
@@ -453,11 +456,15 @@
fn imports() {
assert_eq!(
parse!("import \"hello\""),
- el!(Expr::Import(PathBuf::from("hello")), 0, 14),
+ el!(Expr::Import("hello".into()), 0, 14),
);
assert_eq!(
parse!("importstr \"garnish.txt\""),
- el!(Expr::ImportStr(PathBuf::from("garnish.txt")), 0, 23)
+ el!(Expr::ImportStr("garnish.txt".into()), 0, 23)
+ );
+ assert_eq!(
+ parse!("importbin \"garnish.bin\""),
+ el!(Expr::ImportBin("garnish.bin".into()), 0, 23)
);
}
@@ -720,7 +727,7 @@
fn add_location_info_to_all_sub_expressions() {
use Expr::*;
- let file_name: std::rc::Rc<std::path::Path> = PathBuf::from("test.jsonnet").into();
+ let file_name = Source::new(PathBuf::from("test.jsonnet")).unwrap();
let expr = parse(
"{} { local x = 1, x: x } + {}",
&ParserSettings {
@@ -759,12 +766,5 @@
29
),
);
- }
- // From source code
- /*
- #[bench]
- fn bench_parse_peg(b: &mut Bencher) {
- b.iter(|| parse!(jrsonnet_stdlib::STDLIB_STR))
}
- */
}
crates/jrsonnet-parser/src/source.rsdiffbeforeafterboth--- /dev/null
+++ b/crates/jrsonnet-parser/src/source.rs
@@ -0,0 +1,93 @@
+use std::{
+ borrow::Cow,
+ fmt,
+ path::{Component, Path, PathBuf},
+ rc::Rc,
+};
+
+use gcmodule::{Trace, Tracer};
+#[cfg(feature = "serde")]
+use serde::{Deserialize, Serialize};
+
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[derive(PartialEq, Eq, Debug, Hash)]
+enum Inner {
+ Real(PathBuf),
+ Virtual(Cow<'static, str>),
+}
+
+/// Either real file, or virtual
+/// Hash of FileName always have same value as raw Path, to make it possible to use with raw_entry_mut
+#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
+#[derive(Clone, PartialEq, Eq, Debug)]
+pub struct Source(Rc<Inner>);
+static_assertions::assert_eq_size!(Source, *const ());
+
+impl Trace for Source {
+ fn trace(&self, _tracer: &mut Tracer) {}
+
+ fn is_type_tracked() -> bool {
+ false
+ }
+}
+
+impl Source {
+ /// Fails when path contains inner /../ or /./ references, or not absolute
+ pub fn new(path: PathBuf) -> Option<Self> {
+ if !path.is_absolute()
+ || path
+ .components()
+ .any(|c| matches!(c, Component::CurDir | Component::ParentDir))
+ {
+ return None;
+ }
+ Some(Self(Rc::new(Inner::Real(path))))
+ }
+
+ pub fn new_virtual(n: Cow<'static, str>) -> Self {
+ Self(Rc::new(Inner::Virtual(n)))
+ }
+
+ pub fn short_display(&self) -> ShortDisplay {
+ ShortDisplay(self.clone())
+ }
+ pub fn full_path(&self) -> String {
+ match self.inner() {
+ Inner::Real(r) => r.display().to_string(),
+ Inner::Virtual(v) => v.to_string(),
+ }
+ }
+
+ /// Returns None if file is virtual
+ pub fn path(&self) -> Option<&Path> {
+ match self.inner() {
+ Inner::Real(r) => Some(r),
+ Inner::Virtual(_) => None,
+ }
+ }
+ pub fn repr(&self) -> Result<&Path, &str> {
+ match self.inner() {
+ Inner::Real(r) => Ok(r),
+ Inner::Virtual(v) => Err(v.as_ref()),
+ }
+ }
+
+ fn inner(&self) -> &Inner {
+ &self.0 as &Inner
+ }
+}
+pub struct ShortDisplay(Source);
+impl fmt::Display for ShortDisplay {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+ match &self.0 .0 as &Inner {
+ Inner::Real(r) => {
+ write!(
+ f,
+ "{}",
+ r.file_name().expect("path is valid").to_string_lossy()
+ )
+ }
+ Inner::Virtual(n) => write!(f, "{}", n),
+ }
+ }
+}