5 files changed,
55 insertions(+),
0 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-08-06 16:58:06 +0300
Authored at:
2026-08-06 16:57:41 +0300
Change ID:
ruwokolqmyrpoqqtupvpwwnnlvkrqzsk
Parent:
e3c8c08
M
internal/linter/linter_test.go
··· 28 28 "undeclared-tag": {&UndeclaredTag{}}, 29 29 "undeclared-commodity": {&UndeclaredCommodity{}}, 30 30 "undeclared-account": {&UndeclaredAccount{}}, 31 + "undeclared-payee": {&UndeclaredPayee{}}, 31 32 "unbalanced-transaction": {&UnbalancedTransaction{}}, 32 33 "unused-account": {&UnusedAccount{}}, 33 34 "unused-tag": {&UnusedTag{}},
A
internal/linter/rule_undeclared_payee.go
··· 1 +package linter 2 + 3 +import ( 4 + "fmt" 5 + 6 + "olexsmir.xyz/clerk/internal/analyzer" 7 +) 8 + 9 +// UndeclaredPayee flags transactions that reference a payee not declared via `payee` directive. 10 +type UndeclaredPayee struct{} 11 + 12 +func (UndeclaredPayee) ID() RuleID { return "undeclared-payee" } 13 +func (UndeclaredPayee) Severity() Severity { return SeverityWarning } 14 +func (u *UndeclaredPayee) CheckJournal(an *analyzer.Analysis) []Find { 15 + var finds []Find 16 + for name, info := range an.Payees { 17 + if name == "" { 18 + continue 19 + } 20 + if len(info.Directives) > 0 { 21 + continue 22 + } 23 + for _, usage := range info.Usage { 24 + finds = append(finds, Find{ 25 + Code: u.ID(), 26 + Severity: u.Severity(), 27 + Span: usage.Payee.Span, 28 + Message: fmt.Sprintf("undeclared payee: %s", name), 29 + }) 30 + } 31 + } 32 + return finds 33 +}
A
internal/linter/testdata/undeclared-payee.txtar
··· 1 +-- in.journal -- 2 +payee "Groceries" 3 + 4 +2024-05-01 * "Groceries" 5 + expenses:food 50.00 USD 6 + assets:cash 7 + 8 +2024-05-02 * "Cafe" 9 + expenses:food 15.00 USD 10 + assets:cash 11 + 12 +2024-05-03 * "Cafe" 13 + expenses:food 20.00 USD 14 + assets:cash 15 + 16 +-- expect -- 17 +in.journal:7:14: undeclared-payee: undeclared payee: Cafe 18 +in.journal:11:14: undeclared-payee: undeclared payee: Cafe