goodcheck 2.3.2 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +30 -1
- data/cheatsheet.pdf +0 -0
- data/lib/goodcheck/cli.rb +13 -0
- data/lib/goodcheck/commands/pattern.rb +41 -0
- data/lib/goodcheck/pattern.rb +68 -10
- data/lib/goodcheck/version.rb +1 -1
- data/lib/goodcheck.rb +1 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7da3a85a6dd3f95677661f7863fbc9d51da6ec01272c5e023fa2517aebd7db01
|
4
|
+
data.tar.gz: 8c5f69286210ead4b2f58cc9d11278afad7c704f9056fb2e29b43dad89859985
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7394690992cdec71af0ad640998142b77fd07814b9266ce148b18ca65d56f76eadde56d70384e5bc46e3d50911e41ef4350532aeab7f7fc8f85168c4bee46e8
|
7
|
+
data.tar.gz: 9acb5eb4387b21293c2e83501cc8478afd2a5c5e3acf49f6db05660cec6c8da28959bcfe398396f3a08312dad14b666c5b5cef199dffd0be0df9aee2071c80bc
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,11 @@
|
|
2
2
|
|
3
3
|
## master
|
4
4
|
|
5
|
+
## 2.4.0 (2019-07-11)
|
6
|
+
|
7
|
+
* Add `pattern` command to print regexp of patterns [#63](https://github.com/sider/goodcheck/pull/63)
|
8
|
+
* Fix variable pattern without a type [#62](https://github.com/sider/goodcheck/pull/62)
|
9
|
+
|
5
10
|
## 2.3.2 (2019-07-04)
|
6
11
|
|
7
12
|
* Update README
|
data/README.md
CHANGED
@@ -177,6 +177,26 @@ We have 8 built-in patterns:
|
|
177
177
|
|
178
178
|
You can find the exact definitions of the types in the definition of `Goodcheck::Pattern::Token` (`@@TYPES`).
|
179
179
|
|
180
|
+
You can omit the type of a variable binding.
|
181
|
+
|
182
|
+
```yaml
|
183
|
+
pattern:
|
184
|
+
- token: margin-left: ${size}px;
|
185
|
+
where:
|
186
|
+
size: true
|
187
|
+
- token: backgroundColor={${color}}
|
188
|
+
where:
|
189
|
+
color: true
|
190
|
+
```
|
191
|
+
|
192
|
+
In this case, the following character will be used to detect the range of binding. In the first example above, the `px` will be used as the marker for the end of `size` binding.
|
193
|
+
|
194
|
+
If parens are surrounding the variable, Goodcheck tries to match with nested ones in the variable. It expands five levels of nesting of parens. See the example of matches with the second `backgroundColor` pattern:
|
195
|
+
|
196
|
+
- `backgroundColor={color}` Matches (`color=="color"`)
|
197
|
+
- `backgroundColor={{ red: red(), green: green(), blue: green()-1 }}` Matches (`color=="{ red: red(), green: green(), blue: green()-1 }"`)
|
198
|
+
- `backgroundColor={ {{{{{{}}}}}} }` Matches (`color==" {{{{{{}}}}}"`)
|
199
|
+
|
180
200
|
### *glob*
|
181
201
|
|
182
202
|
A *glob* can be a string, or a hash.
|
@@ -352,13 +372,22 @@ The test contains:
|
|
352
372
|
|
353
373
|
Use `test` command when you add new rule to be sure you are writing rules correctly.
|
354
374
|
|
355
|
-
Available options
|
375
|
+
Available options are:
|
356
376
|
|
357
377
|
* `-c [CONFIG]`, `--config=[CONFIG]` to specify the configuration file.
|
358
378
|
* `-v`, `--verbose` to be verbose.
|
359
379
|
* `--debug` to print all debug messages.
|
360
380
|
* `--force` to ignore downloaded caches
|
361
381
|
|
382
|
+
### `goodcheck pattern [options] ids...`
|
383
|
+
|
384
|
+
The `pattern` command prints the regular expressions generated from the patterns.
|
385
|
+
The command is for debugging patterns, especially token patterns.
|
386
|
+
|
387
|
+
Available option is:
|
388
|
+
|
389
|
+
* `-c [CONFIG]`, `--config=[CONFIG]` to specify the configuration file.
|
390
|
+
|
362
391
|
## Downloaded rules
|
363
392
|
|
364
393
|
Downloaded rules are cached in `cache` directory in *goodcheck home directory*.
|
data/cheatsheet.pdf
CHANGED
Binary file
|
data/lib/goodcheck/cli.rb
CHANGED
@@ -16,6 +16,7 @@ module Goodcheck
|
|
16
16
|
init: "Generate a sample configuration file",
|
17
17
|
check: "Run check with a configuration",
|
18
18
|
test: "Test your configuration",
|
19
|
+
pattern: "Print regexp for rules",
|
19
20
|
version: "Print version",
|
20
21
|
help: "Show goodcheck version and quit"
|
21
22
|
}
|
@@ -161,5 +162,17 @@ module Goodcheck
|
|
161
162
|
end
|
162
163
|
0
|
163
164
|
end
|
165
|
+
|
166
|
+
def pattern(args)
|
167
|
+
config_path = Pathname("goodcheck.yml")
|
168
|
+
|
169
|
+
OptionParser.new("Usage: goodcheck pattern [options] ids...") do |opts|
|
170
|
+
opts.on("-c CONFIG", "--config=CONFIG") do |config|
|
171
|
+
config_path = Pathname(config)
|
172
|
+
end
|
173
|
+
end.parse!(args)
|
174
|
+
|
175
|
+
Commands::Pattern.new(stdout: stdout, stderr: stderr, path: config_path, ids: Set.new(args), home_path: home_path).run
|
176
|
+
end
|
164
177
|
end
|
165
178
|
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Goodcheck
|
2
|
+
module Commands
|
3
|
+
class Pattern
|
4
|
+
attr_reader :stdout
|
5
|
+
attr_reader :stderr
|
6
|
+
attr_reader :config_path
|
7
|
+
attr_reader :ids
|
8
|
+
attr_reader :home_path
|
9
|
+
|
10
|
+
include ConfigLoading
|
11
|
+
include HomePath
|
12
|
+
|
13
|
+
def initialize(stdout:, stderr:, path:, ids:, home_path:)
|
14
|
+
@stdout = stdout
|
15
|
+
@stderr = stderr
|
16
|
+
@config_path = path
|
17
|
+
@ids = ids
|
18
|
+
@home_path = home_path
|
19
|
+
end
|
20
|
+
|
21
|
+
def run
|
22
|
+
handle_config_errors stderr do
|
23
|
+
load_config!(cache_path: cache_dir_path, force_download: true)
|
24
|
+
|
25
|
+
config.rules.each do |rule|
|
26
|
+
if ids.empty? || ids.any? {|pat| pat == rule.id || rule.id.start_with?("#{pat}.") }
|
27
|
+
stdout.puts "#{rule.id}:"
|
28
|
+
rule.triggers.each do |trigger|
|
29
|
+
trigger.patterns.each do |pattern|
|
30
|
+
stdout.puts " - #{pattern.regexp.inspect}"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
0
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
data/lib/goodcheck/pattern.rb
CHANGED
@@ -162,13 +162,48 @@ module Goodcheck
|
|
162
162
|
/\b(?<#{name}>#{AUTO_EMAIL_RE})/
|
163
163
|
}
|
164
164
|
|
165
|
-
def self.
|
166
|
-
|
167
|
-
|
168
|
-
|
165
|
+
def self.expand(prefix, suffix, depth: 5)
|
166
|
+
if depth == 0
|
167
|
+
[
|
168
|
+
/[^#{suffix}]*/
|
169
|
+
]
|
170
|
+
else
|
171
|
+
expandeds = expand(prefix, suffix, depth: depth - 1)
|
172
|
+
[/[^#{prefix}#{suffix}]*#{prefix}#{expandeds.first}#{suffix}[^#{prefix}#{suffix}]*/] + expandeds
|
169
173
|
end
|
170
174
|
end
|
171
175
|
|
176
|
+
def self.regexp_for_type(name:, type:, scanner:)
|
177
|
+
prefix = scanner.pre_match[-1]
|
178
|
+
suffix = scanner.check(WORD_RE) || scanner.peek(1)
|
179
|
+
|
180
|
+
case
|
181
|
+
when type == :__
|
182
|
+
body = case
|
183
|
+
when prefix == "{" && suffix == "}"
|
184
|
+
::Regexp.union(expand(prefix, suffix))
|
185
|
+
when prefix == "(" && suffix == ")"
|
186
|
+
::Regexp.union(expand(prefix, suffix))
|
187
|
+
when prefix == "[" && suffix == "]"
|
188
|
+
::Regexp.union(expand(prefix, suffix))
|
189
|
+
when prefix == "<" && suffix == ">"
|
190
|
+
::Regexp.union(expand(prefix, suffix))
|
191
|
+
else
|
192
|
+
unless suffix.empty?
|
193
|
+
/(?~#{::Regexp.escape(suffix)})/
|
194
|
+
else
|
195
|
+
/.*/
|
196
|
+
end
|
197
|
+
end
|
198
|
+
/(?<#{name}>#{body})/
|
199
|
+
|
200
|
+
when @@TYPES.key?(type)
|
201
|
+
@@TYPES[type][name]
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
WORD_RE = /\w+|[\p{L}&&\p{^ASCII}]+/
|
206
|
+
|
172
207
|
def self.compile_tokens(source, variables, case_sensitive:)
|
173
208
|
tokens = []
|
174
209
|
s = StringScanner.new(source)
|
@@ -177,15 +212,24 @@ module Goodcheck
|
|
177
212
|
case
|
178
213
|
when s.scan(/\${(?<name>[a-zA-Z_]\w*)(?::(?<type>#{::Regexp.union(*@@TYPES.keys.map(&:to_s))}))?}/)
|
179
214
|
name = s[:name].to_sym
|
180
|
-
type = s[:type]
|
215
|
+
type = s[:type] ? s[:type].to_sym : :__
|
181
216
|
|
182
217
|
if variables.key?(name)
|
218
|
+
if !s[:type] && s.pre_match == ""
|
219
|
+
Goodcheck.logger.error "Variable binding ${#{name}} at the beginning of pattern would cause an unexpected match"
|
220
|
+
end
|
221
|
+
if !s[:type] && s.peek(1) == ""
|
222
|
+
Goodcheck.logger.error "Variable binding ${#{name}} at the end of pattern would cause an unexpected match"
|
223
|
+
end
|
224
|
+
|
225
|
+
tokens << :nobr
|
183
226
|
variables[name].type = type
|
184
|
-
regexp = regexp_for_type(name: name, type: type).to_s
|
227
|
+
regexp = regexp_for_type(name: name, type: type, scanner: s).to_s
|
185
228
|
if tokens.empty? && (type == :word || type == :identifier)
|
186
229
|
regexp = /\b#{regexp.to_s}/
|
187
230
|
end
|
188
231
|
tokens << regexp.to_s
|
232
|
+
tokens << :nobr
|
189
233
|
else
|
190
234
|
tokens << ::Regexp.escape("${")
|
191
235
|
tokens << ::Regexp.escape(name.to_s)
|
@@ -195,7 +239,7 @@ module Goodcheck
|
|
195
239
|
tokens << ::Regexp.escape(s.matched)
|
196
240
|
when s.scan(/\s+/)
|
197
241
|
tokens << '\s+'
|
198
|
-
when s.scan(
|
242
|
+
when s.scan(WORD_RE)
|
199
243
|
tokens << ::Regexp.escape(s.matched)
|
200
244
|
when s.scan(%r{[!"#%&'=\-^~¥\\|`@*:+;/?.,]+})
|
201
245
|
tokens << ::Regexp.escape(s.matched.rstrip)
|
@@ -204,18 +248,32 @@ module Goodcheck
|
|
204
248
|
end
|
205
249
|
end
|
206
250
|
|
207
|
-
if
|
251
|
+
if source[0] =~ /\p{L}/
|
208
252
|
tokens.first.prepend('\b')
|
209
253
|
end
|
210
254
|
|
211
|
-
if
|
255
|
+
if source[-1] =~ /\p{L}/
|
212
256
|
tokens.last << '\b'
|
213
257
|
end
|
214
258
|
|
215
259
|
options = ::Regexp::MULTILINE
|
216
260
|
options |= ::Regexp::IGNORECASE unless case_sensitive
|
217
261
|
|
218
|
-
|
262
|
+
buf, skip = tokens[0].is_a?(String) ? [tokens[0], false] : ["", true]
|
263
|
+
tokens.drop(1).each do |tok|
|
264
|
+
if tok == :nobr
|
265
|
+
skip = true
|
266
|
+
else
|
267
|
+
buf << '\s*' unless skip
|
268
|
+
skip = false
|
269
|
+
buf << tok
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
::Regexp.new(buf.
|
274
|
+
gsub(/\\s\*(\\s\+\\s\*)+/, '\s+').
|
275
|
+
gsub(/#{::Regexp.escape('\s+\s*')}/, '\s+').
|
276
|
+
gsub(/#{::Regexp.escape('\s*\s+')}/, '\s+'), options)
|
219
277
|
end
|
220
278
|
end
|
221
279
|
end
|
data/lib/goodcheck/version.rb
CHANGED
data/lib/goodcheck.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: goodcheck
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Soutaro Matsumoto
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-07-
|
11
|
+
date: 2019-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -158,6 +158,7 @@ files:
|
|
158
158
|
- lib/goodcheck/commands/check.rb
|
159
159
|
- lib/goodcheck/commands/config_loading.rb
|
160
160
|
- lib/goodcheck/commands/init.rb
|
161
|
+
- lib/goodcheck/commands/pattern.rb
|
161
162
|
- lib/goodcheck/commands/test.rb
|
162
163
|
- lib/goodcheck/config.rb
|
163
164
|
- lib/goodcheck/config_loader.rb
|