From 1aac38d3d37fd58f60a900d60ea6de1613d10773 Mon Sep 17 00:00:00 2001 From: Mykola Orliuk Date: Wed, 24 Oct 2018 00:23:26 +0200 Subject: [PATCH] lib: include source info in txn balance errors Partially address simonmichael/hledger#904 --- hledger-lib/Hledger/Data/Transaction.hs | 13 ++++++----- tests/journal/parse-errors.test | 30 +++++++++++++++++++++++-- 2 files changed, 35 insertions(+), 8 deletions(-) diff --git a/hledger-lib/Hledger/Data/Transaction.hs b/hledger-lib/Hledger/Data/Transaction.hs index 1f2e31cc0..96e3b4f3c 100644 --- a/hledger-lib/Hledger/Data/Transaction.hs +++ b/hledger-lib/Hledger/Data/Transaction.hs @@ -335,13 +335,13 @@ balanceTransactionUpdate :: MonadError String m -> Maybe (Map.Map CommoditySymbol AmountStyle) -> Transaction -> m Transaction balanceTransactionUpdate update mstyles t = - finalize =<< inferBalancingAmount update (fromMaybe Map.empty mstyles) t + (finalize =<< inferBalancingAmount update (fromMaybe Map.empty mstyles) t) + `catchError` (throwError . annotateErrorWithTxn t) where finalize t' = let t'' = inferBalancingPrices t' in if isTransactionBalanced mstyles t'' then return $ txnTieKnot t'' - else throwError $ printerr $ nonzerobalanceerror t'' - printerr s = intercalate "\n" [s, showTransactionUnelided t] + else throwError $ nonzerobalanceerror t'' nonzerobalanceerror :: Transaction -> String nonzerobalanceerror t = printf "could not balance this transaction (%s%s%s)" rmsg sep bvmsg where @@ -354,6 +354,8 @@ balanceTransactionUpdate update mstyles t = ++ showMixedAmount (costOfMixedAmount bvsum) sep = if not (null rmsg) && not (null bvmsg) then "; " else "" :: String + annotateErrorWithTxn t e = intercalate "\n" [showGenericSourcePos $ tsourcepos t, e, showTransactionUnelided t] + -- | Infer up to one missing amount for this transactions's real postings, and -- likewise for its balanced virtual postings, if needed; or return an error -- message if we can't. @@ -368,14 +370,13 @@ inferBalancingAmount :: MonadError String m => -> m Transaction inferBalancingAmount update styles t@Transaction{tpostings=ps} | length amountlessrealps > 1 - = throwError $ printerr "could not balance this transaction - can't have more than one real posting with no amount (remember to put 2 or more spaces before amounts)" + = throwError "could not balance this transaction - can't have more than one real posting with no amount (remember to put 2 or more spaces before amounts)" | length amountlessbvps > 1 - = throwError $ printerr "could not balance this transaction - can't have more than one balanced virtual posting with no amount (remember to put 2 or more spaces before amounts)" + = throwError "could not balance this transaction - can't have more than one balanced virtual posting with no amount (remember to put 2 or more spaces before amounts)" | otherwise = do postings <- mapM inferamount ps return t{tpostings=postings} where - printerr s = intercalate "\n" [s, showTransactionUnelided t] (amountfulrealps, amountlessrealps) = partition hasAmount (realPostings t) realsum = sumStrict $ map pamount amountfulrealps (amountfulbvps, amountlessbvps) = partition hasAmount (balancedVirtualPostings t) diff --git a/tests/journal/parse-errors.test b/tests/journal/parse-errors.test index b24347f78..66ee73109 100644 --- a/tests/journal/parse-errors.test +++ b/tests/journal/parse-errors.test @@ -34,7 +34,12 @@ $ hledger -f - print # 3. So in these tests we must sometimes force the desired format, like so. # Now we see the error from the journal reader. $ hledger -f journal:- print ->2 /hledger: could not balance this transaction \(real postings are off by 1\)/ +>2 /could not balance this transaction \(real postings are off by 1\)/ +>=1 + +# 4. We expect to have reference to line number with last posting +$ hledger -f journal:- print +>2 /\<2\>/ >=1 # A posting without two spaces between account and amount. @@ -42,7 +47,7 @@ $ hledger -f journal:- print 2018/1/1 (a) 1 -# 4. hledger doesn't detect this as an error directly, it parses account name "(a) 1" and +# 5. hledger doesn't detect this as an error directly, it parses account name "(a) 1" and # amount 0 here. $ hledger -f - print -x 2018/01/01 @@ -50,3 +55,24 @@ $ hledger -f - print -x >= +# 6. Two (or more) postings with implicit amount cannot be balanced. +< +2018/1/1 + a 1 + b + c + +$ hledger -f journal:- print +>2 /\<4\>/ +>=1 + +# 7. Two (or more) virtual postings with implicit amount cannot be balanced. +< +2018/1/1 + [a] 1 + [b] + [c] + +$ hledger -f journal:- print +>2 /\<4\>/ +>=1