all repos

clerk @ 8909472

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
feat: config (#6), 1 month ago
1
package linter
2
3
import (
4
	"bytes"
5
	"encoding/json"
6
	"fmt"
7
8
	"olexsmir.xyz/clerk/internal/analyzer"
9
	"olexsmir.xyz/clerk/journal/ast"
10
)
11
12
const AccountDepthLimitID = "account-depth"
13
14
// AccountDepthLimit checks that account names don't exceed MaxDepth
15
type AccountDepthLimit struct {
16
	MaxDepth int `json:"max-depth"`
17
}
18
19
func (AccountDepthLimit) ID() RuleID { return AccountDepthLimitID }
20
func (a *AccountDepthLimit) CheckJournal(an *analyzer.Analysis) []Find {
21
	var finds []Find
22
23
	for _, txn := range an.Transactions {
24
		for _, p := range txn.Postings {
25
			a.check(&finds, p.Account)
26
		}
27
	}
28
	for _, ptx := range an.PeriodicTransactions {
29
		for _, p := range ptx.Postings {
30
			a.check(&finds, p.Account)
31
		}
32
	}
33
	for _, atx := range an.AutomatedTransactions {
34
		for _, p := range atx.Postings {
35
			a.check(&finds, p.Account)
36
		}
37
	}
38
39
	for _, d := range an.Directives {
40
		switch e := d.(type) {
41
		case *ast.AccountDirective:
42
			a.check(&finds, e.Account)
43
		case *ast.AliasDirective:
44
			a.check(&finds, e.From)
45
			a.check(&finds, e.To)
46
		}
47
	}
48
49
	return finds
50
}
51
52
func (a *AccountDepthLimit) Clone() Rule { cpy := *a; return &cpy }
53
func (a *AccountDepthLimit) UnmarshalOptions(data json.RawMessage) error {
54
	d := json.NewDecoder(bytes.NewReader(data))
55
	d.DisallowUnknownFields()
56
	return d.Decode(a)
57
}
58
59
func (a *AccountDepthLimit) check(finds *[]Find, acc ast.Account) {
60
	if depth := len(acc.Name); depth > a.MaxDepth {
61
		*finds = append(*finds, Find{
62
			Code: a.ID(),
63
			Message: fmt.Sprintf("account %q depth (%d) exceeds max allowed depth (%d)",
64
				acc.String(), depth, a.MaxDepth),
65
			Span: acc.Span,
66
		})
67
	}
68
}