src/noqa.bend
bolt@1.27.0.0 · 252 lines · 28 definitions
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15import Base
16import bolt@1.27.0.0/src/lazy/lazy.bend as Lazy
17import bolt@1.27.0.0/src/syntax/lex.bend as Lex
18import bolt@1.27.0.0/src/rchars.bend as Rchars
19import bolt@1.27.0.0/src/finding.bend as F
20import bolt@1.27.0.0/src/codes.bend as Codes
21import bolt@1.27.0.0/src/src.bend as Src
22
23
24
25type Mark is Data:
26 Mark{line: U32, col: U32, len: U32, codes: List<&2, String>}
27
28
29type Marks is Data:
30 Marks{path: String, marks: List<&2, Mark>}
31
32
33
34
35
36
37type Cls is Data:
38 CSpace{}
39 CComma{}
40 CCode{}
41 COther{}
42
43
44def cls(+cc: Char) -> Cls:
45 +code = Bool.or(Char.is_alpha(cc), Char.is_digit(cc))
46 +tail = Bool.pick(Cls, code, CCode{}, COther{})
47 Bool.pick(Cls, Char.is_eq(cc, ' '), CSpace{}, Bool.pick(Cls, Char.is_eq(cc, ','), CComma{}, tail))
48
49
50
51type Phase is Data:
52 Before{}
53 Inside{}
54 After{}
55 Past{}
56
57
58
59type Rd is Data:
60 Rd{phase: Phase, buf: List<&2, Char>, acc: List<&2, String>}
61
62
63def word(buf: List<&2, Char>) -> String:
64 Rchars.text(buf)
65
66
67
68def step.before(kk: Cls, +cc: Char, +acc: List<&2, String>) -> Rd:
69 match kk:
70 case CSpace{}:
71 Rd{Before{}, [], acc}
72 case CComma{}:
73 Rd{Past{}, [], acc}
74 case CCode{}:
75 Rd{Inside{}, [cc], acc}
76 case COther{}:
77 Rd{Past{}, [], acc}
78
79
80
81def step.inside(kk: Cls, +cc: Char, +buf: List<&2, Char>, +acc: List<&2, String>) -> Rd:
82 match kk:
83 case CSpace{}:
84 Rd{After{}, [], word(buf) <> acc}
85 case CComma{}:
86 Rd{Before{}, [], word(buf) <> acc}
87 case CCode{}:
88 Rd{Inside{}, cc <> buf, acc}
89 case COther{}:
90 Rd{Past{}, [], word(buf) <> acc}
91
92
93
94def step.after(kk: Cls, +acc: List<&2, String>) -> Rd:
95 match kk:
96 case CSpace{}:
97 Rd{After{}, [], acc}
98 case CComma{}:
99 Rd{Before{}, [], acc}
100 case CCode{}:
101 Rd{Past{}, [], acc}
102 case COther{}:
103 Rd{Past{}, [], acc}
104
105
106def step.at(ph: Phase, +cc: Char, +buf: List<&2, Char>, +acc: List<&2, String>) -> Rd:
107 match ph:
108 case Before{}:
109 step.before(cls(cc), cc, acc)
110 case Inside{}:
111 step.inside(cls(cc), cc, buf, acc)
112 case After{}:
113 step.after(cls(cc), acc)
114 case Past{}:
115 Rd{Past{}, buf, acc}
116
117
118def step(+cc: Char, rd: Rd) -> Rd:
119 Rd{ph, buf, acc} = rd
120 step.at(ph, cc, buf, acc)
121
122
123def run(tt: String, rd: Rd) -> Rd:
124 match tt:
125 case SNil{}:
126 rd
127 case SCon{cc, rest}:
128 run(rest, step(cc, rd))
129
130
131def finish.at(ph: Phase, +buf: List<&2, Char>, +acc: List<&2, String>) -> List<&2, String>:
132 match ph:
133 case Before{}:
134 List.reverse(&2, String, acc)
135 case Inside{}:
136 List.reverse(&2, String, word(buf) <> acc)
137 case After{}:
138 List.reverse(&2, String, acc)
139 case Past{}:
140 List.reverse(&2, String, acc)
141
142
143def finish(rd: Rd) -> List<&2, String>:
144 Rd{ph, buf, acc} = rd
145 finish.at(ph, buf, acc)
146
147
148def codes(tt: String) -> List<&2, String>:
149 finish(run(tt, Rd{Before{}, [], []}))
150
151
152def lead(tt: String) -> String:
153 match tt:
154 case SCon{' ', rest}:
155 lead(rest)
156 case other:
157 other
158
159
160
161def mark.rest(+line: U32, +col: U32, +len: U32, tt: String) -> List<&2, Mark>:
162 match tt:
163 case SNil{}:
164 [Mark{line, col, len, []}]
165 case SCon{':', rest}:
166 [Mark{line, col, len, codes(rest)}]
167 case SCon{' ', _rest}:
168 [Mark{line, col, len, []}]
169 case other:
170 []
171
172
173def mark.word(+line: U32, +col: U32, +len: U32, tt: String) -> List<&2, Mark>:
174 match tt:
175 case SCon{'n', SCon{'o', SCon{'q', SCon{'a', rest}}}}:
176 mark.rest(line, col, len, rest)
177 case other:
178 []
179
180
181def mark.text(+line: U32, +col: U32, +len: U32, tt: String) -> List<&2, Mark>:
182 match tt:
183 case SCon{'#', rest}:
184 mark.word(line, col, len, lead(rest))
185 case other:
186 []
187
188
189def mark.of(tk: Lex.Tok) -> List<&2, Mark>:
190 match tk:
191 case Lex.Tok{Lex.TComment{}, +t, l, c}:
192 mark.text(l, c, U32.from_nat(String.length(t)), t)
193 case other:
194 []
195
196
197def marks(toks: List<&2, Lex.Tok>) -> List<&2, Mark>:
198 match toks:
199 case Nil{}:
200 Nil{}
201 case Con{t, rest}:
202 List.append(&2, Mark, mark.of(t), marks(rest))
203
204
205def file(path: String, toks: List<&2, Lex.Tok>) -> Marks:
206 Marks{path, marks(toks)}
207
208
209def of_srcs(ss: List<&2, Src.Src>) -> List<&2, Marks>:
210 match ss:
211 case Nil{}:
212 Nil{}
213 case Con{Src.Src{path, _text, toks, _tree, _bound, _items}, rest}:
214 file(path, toks) <> of_srcs(rest)
215
216
217
218
219
220def named(cs: List<&2, String>, +code: String) -> Bool:
221 match cs:
222 case Nil{}:
223 False{}
224 case Con{c, rest}:
225 Lazy.or_else(String.eq(c, code), _u => named(rest, code))
226
227
228def on_line(mks: List<&2, Mark>, +line: U32, +code: String) -> Bool:
229 match mks:
230 case Nil{}:
231 False{}
232 case Con{Mark{l, _col, _len, cs}, rest}:
233 Lazy.or_else(Lazy.and_then(U32.is_eq(l, line), _u => named(cs, code)), _v => on_line(rest, line, code))
234
235
236def silenced(ms: List<&2, Marks>, +path: String, +line: U32, +code: String) -> Bool:
237 match ms:
238 case Nil{}:
239 False{}
240 case Con{Marks{p, mks}, rest}:
241 Lazy.or_else(Lazy.and_then(String.eq(p, path), _u => on_line(mks, line, code)),
242 _v => silenced(rest, path, line, code))
243
244
245def keep(+ms: List<&2, Marks>, gs: List<&2, F.Graded>) -> List<&2, F.Graded>:
246 match gs:
247 case Nil{}:
248 Nil{}
249 case Con{F.Graded{ll, F.Finding{+path, +line, col, len, +rule, msg}}, rest}:
250 +more = keep(ms, rest)
251 Bool.pick(List<&2, F.Graded>, silenced(ms, path, line, Codes.code(rule)), more,
252 F.Graded{ll, F.Finding{path, line, col, len, rule, msg}} <> more)