all repos

clerk @ e2e9e2b27783c07fe5724268bf7ae828b3aacac7

missing tooling for ledger/hledger

clerk/internal/linter/rule_missing_commodity.go (view raw)

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
improve analyzer, 1 day ago
1
package linter
2
3
import (
4
	"olexsmir.xyz/clerk/internal/analyzer"
5
	"olexsmir.xyz/clerk/journal/ast"
6
)
7
8
// MissingCommodity flags amounts with a missing commodity.
9
type MissingCommodity struct{}
10
11
func (MissingCommodity) ID() RuleID         { return "missing-commodity" }
12
func (MissingCommodity) Severity() Severity { return SeverityWarning }
13
func (m *MissingCommodity) CheckJournal(an *analyzer.Analysis) []Find {
14
	var finds []Find
15
16
	for _, txn := range an.Transactions {
17
		m.checkPostings(&finds, txn.Postings)
18
	}
19
	for _, ptx := range an.PeriodicTransactions {
20
		m.checkPostings(&finds, ptx.Postings)
21
	}
22
	for _, atx := range an.AutomatedTransactions {
23
		m.checkPostings(&finds, atx.Postings)
24
	}
25
26
	for _, d := range an.Directives {
27
		switch e := d.(type) {
28
		case *ast.ConversionDirective:
29
			m.check(&finds, e.From)
30
			m.check(&finds, e.To)
31
		case *ast.CommodityDirective:
32
			if e.Format.Commodity != "" {
33
				m.check(&finds, e.Format)
34
			}
35
		case *ast.DefaultCommodityDirective:
36
			m.check(&finds, e.Amount)
37
		case *ast.MarketPriceDirective:
38
			m.check(&finds, e.Amount)
39
		}
40
	}
41
42
	return finds
43
}
44
45
func (m *MissingCommodity) checkPostings(finds *[]Find, postings []*ast.Posting) {
46
	for _, posting := range postings {
47
		if posting.Amount == nil {
48
			continue
49
		}
50
		m.check(finds, *posting.Amount)
51
		if posting.Cost != nil {
52
			m.check(finds, posting.Cost.Amount)
53
		}
54
		if posting.Balance != nil {
55
			m.check(finds, posting.Balance.Amount)
56
			if posting.Balance.Cost != nil {
57
				m.check(finds, posting.Balance.Cost.Amount)
58
			}
59
		}
60
	}
61
}
62
63
func (m *MissingCommodity) check(finds *[]Find, am ast.Amount) {
64
	if am.Commodity == "" {
65
		*finds = append(*finds, Find{
66
			Code:     m.ID(),
67
			Severity: m.Severity(),
68
			Message:  "amount missing commodity",
69
			Span:     am.Span,
70
		})
71
	}
72
}