all repos

clerk @ cea9a8c

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
fix: missing_commodity: skip it format is not provided, 1 month ago
1
package linter
2
3
import "olexsmir.xyz/clerk/journal/ast"
4
5
// MissingCommodity flags amounts with a missing commodity.
6
type MissingCommodity struct{}
7
8
func (MissingCommodity) ID() RuleID         { return "missing-commodity" }
9
func (MissingCommodity) Severity() Severity { return SeverityWarning }
10
func (m *MissingCommodity) CheckEntry(entry ast.Entry) []Find {
11
	var finds []Find
12
	switch e := entry.(type) {
13
	case *ast.Transaction:
14
		m.checkPostings(&finds, e.Postings)
15
	case *ast.PeriodicTransaction:
16
		m.checkPostings(&finds, e.Postings)
17
	case *ast.AutomatedTransaction:
18
		m.checkPostings(&finds, e.Postings)
19
	case *ast.ConversionDirective:
20
		m.check(&finds, e.From)
21
		m.check(&finds, e.To)
22
	case *ast.CommodityDirective:
23
		if e.Format.Commodity != "" {
24
			m.check(&finds, e.Format)
25
		}
26
	case *ast.DefaultCommodityDirective:
27
		m.check(&finds, e.Amount)
28
	case *ast.MarketPriceDirective:
29
		m.check(&finds, e.Amount)
30
	}
31
	return finds
32
}
33
34
func (m *MissingCommodity) checkPostings(finds *[]Find, postings []*ast.Posting) {
35
	for _, posting := range postings {
36
		if posting.Amount == nil {
37
			continue
38
		}
39
		m.check(finds, *posting.Amount)
40
		if posting.Cost != nil {
41
			m.check(finds, posting.Cost.Amount)
42
		}
43
		if posting.Balance != nil {
44
			m.check(finds, posting.Balance.Amount)
45
			if posting.Balance.Cost != nil {
46
				m.check(finds, posting.Balance.Cost.Amount)
47
			}
48
		}
49
	}
50
}
51
52
func (m *MissingCommodity) check(finds *[]Find, am ast.Amount) {
53
	if am.Commodity == "" {
54
		*finds = append(*finds, Find{
55
			Code:     m.ID(),
56
			Severity: m.Severity(),
57
			Message:  "amount missing commodity",
58
			Span:     am.Span,
59
		})
60
	}
61
}