-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathrange_import_rule.go
132 lines (104 loc) · 2.83 KB
/
range_import_rule.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
package ptproc
import (
"context"
"errors"
"log/slog"
"regexp"
"cuelang.org/go/cue/cuecontext"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/attribute"
)
var _ Rule = (*rangeImportRule)(nil)
var DefaultRangeImportStartRegEx = regexp.MustCompile(`range:(?P<Cue>[^\s]+)`)
var DefaultRangeImportEndRegEx = regexp.MustCompile(`range.end`)
type RangeImportRuleConfig struct {
Name string
StartRegExp *regexp.Regexp
EndRegExp *regexp.Regexp
}
func NewRangeImportRule(cfg *RangeImportRuleConfig) (Rule, error) {
if cfg == nil {
cfg = &RangeImportRuleConfig{}
}
return &rangeImportRule{
targetName: cfg.Name,
startRegExp: cfg.StartRegExp,
endRegExp: cfg.EndRegExp,
}, nil
}
type rangeImportRule struct {
targetName string
startRegExp *regexp.Regexp
endRegExp *regexp.Regexp
}
type rangeImportParams struct {
Name string `cue:"name"`
}
func (rule *rangeImportRule) Apply(ctx context.Context, opts *RuleOptions, ns []Node) (_ []Node, err error) {
ctx, span := otel.Tracer("ptproc").Start(ctx, "rangeImportRule.Apply")
defer func() {
if err != nil {
span.RecordError(err)
}
span.End()
}()
span.SetAttributes(attribute.String("targetName", rule.targetName))
startRegExp := rule.startRegExp
if startRegExp == nil {
startRegExp = DefaultRangeImportStartRegEx
}
endRegExp := rule.endRegExp
if endRegExp == nil {
endRegExp = DefaultRangeImportEndRegEx
}
slog.DebugContext(ctx, "start range import rule processing")
newNodes := make([]Node, 0, len(ns))
var inRangeImportRange bool
for _, n := range ns {
txt := n.Text()
if !inRangeImportRange {
group := startRegExp.FindStringSubmatch(txt)
if len(group) == 2 {
params, err := rule.textToParams(ctx, group[1])
if err != nil {
return nil, err
}
name := params.Name
slog.DebugContext(ctx, "find range directive", slog.String("name", name))
if name != rule.targetName {
continue
}
inRangeImportRange = true
}
} else if endRegExp.MatchString(txt) {
inRangeImportRange = false
} else {
newNodes = append(newNodes, n)
}
}
if inRangeImportRange {
return nil, errors.New("range end directive is not found")
}
return newNodes, nil
}
func (rule *rangeImportRule) textToParams(ctx context.Context, s string) (*rangeImportParams, error) {
cuectx := cuecontext.New()
cv := cuectx.CompileString(s)
err := cv.Validate()
if err != nil {
slog.DebugContext(ctx, "cue validate failed. evaluate to string", "err", err, "value", s)
return &rangeImportParams{Name: s}, nil
}
v, err := cv.String()
if err == nil {
return &rangeImportParams{Name: v}, nil
} else {
slog.DebugContext(ctx, "failed to convert cue value to string. continue processing", "err", err, "value", s)
}
params := &rangeImportParams{}
err = cv.Decode(params)
if err != nil {
return nil, err
}
return params, nil
}