Kaynağa Gözat

Change to internal span storage for transaction.

Kestrel 2 gün önce
ebeveyn
işleme
ddcdc36e72
5 değiştirilmiş dosya ile 59 ekleme ve 27 silme
  1. 2 2
      src/check.rs
  2. 3 4
      src/cmd.rs
  3. 1 1
      src/cmd/infer.rs
  4. 46 12
      src/data.rs
  5. 7 8
      src/data/parse.rs

+ 2 - 2
src/check.rs

@@ -29,7 +29,7 @@ fn check_equal_sum(root: &data::Hoard) -> Result<(), DataError> {
             .iter()
             .try_fold(data::Decimal::ZERO, |acc, b| acc.checked_add(*b.amount));
         if net != Some(data::Decimal::ZERO) {
-            let report = ariadne::Report::build(ariadne::ReportKind::Error, tx.span()).with_labels(
+            let report = ariadne::Report::build(ariadne::ReportKind::Error, tx.source.unwrap_or_default()).with_labels(
                 tx.changes.iter().map(|v| {
                     let span = v.amount.span().union(v.unit.span());
                     ariadne::Label::new(span).with_message("change here")
@@ -125,7 +125,7 @@ fn check_balances(root: &data::Hoard) -> Result<(), DataError> {
 
             if let Some(sbal) = change.balance.as_ref() {
                 if **sbal != bal.0 {
-                    let report = ariadne::Report::build(ariadne::ReportKind::Error, txn.span())
+                    let report = ariadne::Report::build(ariadne::ReportKind::Error, txn.source.unwrap_or_default())
                         .with_label(ariadne::Label::new(sbal.span()).with_message(format!(
                             "Calculated balance is {} {}, specified balance is {} {}",
                             bal, change.unit, sbal, change.unit

+ 3 - 4
src/cmd.rs

@@ -114,7 +114,7 @@ impl Command {
 
                 let tt = show::TransactionTable::default();
                 if let Some(ld) = data.ledger_data_for(aname) {
-                    tt.show(Some(&data), aname, ld.iter().map(Spanned::as_ref));
+                    tt.show(Some(&data), aname, ld.iter());
                 } else {
                     log::error!("account not found!");
                 }
@@ -176,11 +176,10 @@ impl Command {
                     let new_source = std::fs::canonicalize(target.as_os_str())?
                         .into_os_string()
                         .into();
-                    let span = io::Span::null_for_file(new_source);
 
                     let new_data = imported
                         .into_iter()
-                        .map(|txn| data::LedgerEntry::Transaction(io::Spanned(txn, span)))
+                        .map(|txn| data::LedgerEntry::Transaction(txn))
                         .collect_vec();
 
                     data::format_ledger(
@@ -218,7 +217,7 @@ impl Command {
                 show::TransactionTable::default().show(
                     Some(&data),
                     *account,
-                    txs.iter().map(|v| &v.0),
+                    txs.into_iter()
                 );
             }
         }

+ 1 - 1
src/cmd/infer.rs

@@ -49,7 +49,7 @@ pub fn do_inference(data: &mut Hoard) -> anyhow::Result<bool> {
                 txn.title
             );
 
-            show_transaction(None, txn.as_ref());
+            show_transaction(None, txn);
 
             println!(
                 "Candidate account: {} (Y/n)",

+ 46 - 12
src/data.rs

@@ -112,21 +112,52 @@ impl Transaction {
     }
 }
 
+pub type TransactionRef = std::rc::Rc<std::cell::RefCell<Transaction>>;
+
+#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
+enum RawLedgerEntry {
+    Transaction(Transaction),
+    Comment(Spanned<String>),
+}
+
+impl RawLedgerEntry {
+    pub fn as_transaction(&self) -> Option<&Transaction> {
+        match self {
+            Self::Transaction(tx) => Some(tx),
+            _ => None,
+        }
+    }
+
+    pub fn as_transaction_mut(&mut self) -> Option<&mut Transaction> {
+        match self {
+            Self::Transaction(tx) => Some(tx),
+            _ => None,
+        }
+    }
+
+    pub fn span(&self) -> io::Span {
+        match self {
+            Self::Transaction(ts) => ts.source.unwrap_or_default(),
+            Self::Comment(c) => c.span(),
+        }
+    }
+}
+
 #[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
 pub enum LedgerEntry {
-    Transaction(Spanned<Transaction>),
+    Transaction(TransactionRef),
     Comment(Spanned<String>),
 }
 
 impl LedgerEntry {
-    pub fn as_transaction(&self) -> Option<&Spanned<Transaction>> {
+    pub fn as_transaction(&self) -> Option<&TransactionRef> {
         match self {
             Self::Transaction(tx) => Some(tx),
             _ => None,
         }
     }
 
-    pub fn as_transaction_mut(&mut self) -> Option<&mut Spanned<Transaction>> {
+    pub fn as_transaction_mut(&mut self) -> Option<&mut Transaction> {
         match self {
             Self::Transaction(tx) => Some(tx),
             _ => None,
@@ -135,7 +166,7 @@ impl LedgerEntry {
 
     pub fn span(&self) -> io::Span {
         match self {
-            Self::Transaction(ts) => ts.span(),
+            Self::Transaction(ts) => ts.source.unwrap_or_default(),
             Self::Comment(c) => c.span(),
         }
     }
@@ -146,9 +177,11 @@ pub struct Hoard {
     path: std::path::PathBuf,
     spec_root: spec::SpecRoot,
 
-    ledger_data: Vec<LedgerEntry>,
+    comments: Vec<Spanned<String>>,
+
+    raw_ledger_data: Vec<RawLedgerEntry>,
 
-    account_ledger_data: HashMap<AccountName, Vec<Spanned<Transaction>>>,
+    account_ledger_data: HashMap<AccountName, Vec<Transaction>>,
 }
 
 impl Hoard {
@@ -165,7 +198,8 @@ impl Hoard {
                 let mut r = Self {
                     path: path.into(),
                     spec_root,
-                    ledger_data: vec![],
+                    raw_ledger_data: vec![],
+                    comments: vec![],
                     account_ledger_data: Default::default(),
                 };
 
@@ -228,7 +262,7 @@ impl Hoard {
 
             let sf = io::SourceFile::new_from_string(path.into_os_string());
             if let Ok(data) = fsdata.fetch(&sf) {
-                self.ledger_data
+                self.raw_ledger_data
                     .extend(parse_ledger(sf, &self.spec_root, data.text())?);
             } else {
                 log::error!(
@@ -253,8 +287,8 @@ impl Hoard {
     }
 
     fn preprocess_ledger_data(&mut self) {
-        for entry in &self.ledger_data {
-            let LedgerEntry::Transaction(tx) = &entry else {
+        for entry in &self.raw_ledger_data {
+            let RawLedgerEntry::Transaction(tx) = &entry else {
                 continue;
             };
             for bal in &tx.changes {
@@ -274,14 +308,14 @@ impl Hoard {
         self.ledger_data.as_mut_slice()
     }
 
-    pub fn ledger_data_for(&self, aname: AccountName) -> Option<&[Spanned<Transaction>]> {
+    pub fn ledger_data_for(&self, aname: AccountName) -> Option<&[Transaction]> {
         self.account_ledger_data.get(&aname).map(Vec::as_slice)
     }
 
     pub fn ledger_data_for_mut(
         &mut self,
         aname: AccountName,
-    ) -> Option<&mut [Spanned<Transaction>]> {
+    ) -> Option<&mut [Transaction]> {
         self.account_ledger_data
             .get_mut(&aname)
             .map(Vec::as_mut_slice)

+ 7 - 8
src/data/parse.rs

@@ -2,7 +2,7 @@ use crate::prelude::*;
 
 use data::{AccountName, DataError, Datestamp, Decimal, Spanned, UnitName, spec::SpecRoot};
 
-use super::{Change, LedgerEntry, Transaction};
+use super::{Change, RawLedgerEntry, Transaction};
 
 use chumsky::{prelude::*, text::inline_whitespace};
 
@@ -11,7 +11,7 @@ type InputWithContext<'a> = chumsky::input::WithContext<io::Span, &'a str>;
 fn ledger_parser<'a>() -> impl Parser<
     'a,
     InputWithContext<'a>,
-    Vec<LedgerEntry>,
+    Vec<RawLedgerEntry>,
     chumsky::extra::Full<
         chumsky::error::Rich<'a, char, io::Span>,
         chumsky::extra::SimpleState<&'a SpecRoot>,
@@ -28,7 +28,7 @@ fn ledger_parser<'a>() -> impl Parser<
         .ignore_then(none_of("\n").repeated())
         .to_slice()
         .padded()
-        .map_with(|s: &str, e| LedgerEntry::Comment(Spanned::new(s.into(), e.span())));
+        .map_with(|s: &str, e| RawLedgerEntry::Comment(Spanned::new(s.into(), e.span())));
 
     let datestamp =
         group((int, just('-').ignored(), int, just('-').ignored(), int)).map(|(y, _, m, _, d)| {
@@ -140,16 +140,15 @@ fn ledger_parser<'a>() -> impl Parser<
     ))
     .map_with(
         |(_, datestamp, _, _, title, _, annotations, changes, _), e| {
-            LedgerEntry::Transaction(Spanned::new(
+            RawLedgerEntry::Transaction(
                 Transaction {
                     datestamp,
                     title: (!title.is_empty()).then_some(title),
                     annotations,
                     changes,
                     source: Some(e.span()),
-                },
-                e.span(),
-            ))
+                }
+            )
         },
     );
 
@@ -160,7 +159,7 @@ pub fn parse_ledger(
     source: io::SourceFile,
     spec: &SpecRoot,
     data: &str,
-) -> Result<Vec<LedgerEntry>, DataError> {
+) -> Result<Vec<RawLedgerEntry>, DataError> {
     let parser = ledger_parser();
 
     let (presult, errors) = parser