all repos

clerk @ 0c15ec4

missing tooling for ledger/hledger

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

Oleksandr Smirnov Oleksandr Smirnov
olexsmir@gmail.com
linter: refactor to use semantic context, 1 month ago
1
package linter
2
3
import (
4
	"olexsmir.xyz/clerk/journal/token"
5
6
	"olexsmir.xyz/clerk/journal/semantic"
7
)
8
9
// A Find represents a single lint finding.
10
type Find struct {
11
	Code     RuleID
12
	Severity Severity
13
	Message  string
14
	Span     token.Span
15
}
16
17
// Linter runs lint rules against a parsed journal.
18
type Linter struct {
19
	rules []Rule
20
}
21
22
// NewLinter creates a [Linter] with the given rules.
23
func NewLinter(rules []Rule) *Linter {
24
	return &Linter{rules: rules}
25
}
26
27
// Run runs all rules against the semantic context.
28
func (l *Linter) Run(ctx *semantic.Context) []Find {
29
	var finds []Find
30
31
	// per-entry traversal
32
	for _, pf := range ctx.Files {
33
		for _, entry := range pf.Ast.Entries {
34
			for _, rule := range l.rules {
35
				if ec, ok := rule.(EntryChecker); ok {
36
					finds = append(finds, ec.CheckEntry(entry)...)
37
				}
38
			}
39
		}
40
	}
41
42
	// post-traversal
43
	for _, rule := range l.rules {
44
		if jc, ok := rule.(JournalChecker); ok {
45
			finds = append(finds, jc.CheckJournal(ctx)...)
46
		}
47
	}
48
49
	return finds
50
}
51
52
// Severity represents severity of the litning find.
53
type Severity int
54
55
const (
56
	SeverityError   Severity = 1
57
	SeverityWarning Severity = 2
58
	SeverityInfo    Severity = 3
59
	SeverityHint    Severity = 4
60
)
61
62
func (s Severity) String() string {
63
	switch s {
64
	case SeverityError:
65
		return "error"
66
	case SeverityWarning:
67
		return "warning"
68
	case SeverityInfo:
69
		return "info"
70
	case SeverityHint:
71
		return "hint"
72
	}
73
	panic("impossible severity state")
74
}