rubocop-grep 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: d17d31d5330cf736985149bc97d6450855687f0c51f600e2255e74bdd0919a1d
4
+ data.tar.gz: f0d95990a73f923fa3206e5b965d2f9a719947e9fbfb76b85a44f64a87df4df1
5
+ SHA512:
6
+ metadata.gz: 6bc2ef94f372ae4d545ac5f320d30d4d876f58d35b4e659a18b4b833c46ff3cdba658f31a456c8f0a7cd85e6057baee75ee3cee19880c8767a23b70908e75590
7
+ data.tar.gz: d89343cd6f8c90e1302275ec8415dd2956c0fa0c4c32daed7ef7cfe361a7245e6fd37e1f168e6c9e5f647ffb94ccfbb123f9872f0f2f7cdc12301d5c2a2f71aa
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,3 @@
1
+ Naming/FileName:
2
+ Exclude:
3
+ - lib/rubocop-grep.rb
data/Gemfile ADDED
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ source "https://rubygems.org"
4
+
5
+ # Specify your gem's dependencies in rubocop-grep.gemspec
6
+ gemspec
7
+
8
+ gem "rake", "~> 13.0"
9
+
10
+ gem "rspec", "~> 3.0"
11
+
12
+ gem "rubocop", "~> 1.21"
13
+
14
+ gem 'steep', '1.4.0.dev.2', require: false
15
+ gem 'rbs', require: false
data/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # rubocop-grep
2
+
3
+ It is a RuboCop extension to define your cop with regexps.
4
+
5
+ Sometimes you need a custom cop to detect a problem. For example, if you need a cop to detect your internal library, RuboCop's core rules are not helpful.
6
+ But creating a new cop is not easy enough if you are not familiar with RuboCop. You need to know AST, RuboCop's API, and so on.
7
+
8
+ In this case, rubocop-grep can be helpful. You can create a custom cop only with a Regular expression! If a regexp is enough to detect your problem, this gem can be the best way to solve the problem.
9
+
10
+ ## Installation
11
+
12
+ Install the gem and add to the application's Gemfile by executing:
13
+
14
+ $ bundle add rubocop-grep --require=false
15
+
16
+ If bundler is not being used to manage dependencies, install the gem by executing:
17
+
18
+ $ gem install rubocop-grep
19
+
20
+ ## Usage
21
+
22
+ First of all, you need to tell RuboCop to load this extension.
23
+
24
+ Put this into your `.rubocop.yml`.
25
+
26
+ ```yaml
27
+ require: rubocop-grep
28
+ ```
29
+
30
+ Alternatively, use the following array notation when specifying multiple extensions.
31
+
32
+ ```yaml
33
+ require:
34
+ - rubocop-other-extension
35
+ - rubocop-grep
36
+ ```
37
+
38
+ Then, define your rule in `.rubocop.yml` like the following.
39
+
40
+ ```yaml
41
+ Grep/Grep:
42
+ Rules:
43
+ # The simplest rule definition. It warns if the regexp matches your code.
44
+ - Pattern: '\bENV\b'
45
+ Message: Do not refer ENV directly.
46
+
47
+ # Pattern can be an array.
48
+ - Pattern:
49
+ - 'binding\.irb'
50
+ - 'binding\.pry'
51
+ Message: 'Debug code remains'
52
+
53
+ # The pattern matches code comments with `comment: true` option (default: false).
54
+ - Pattern: 'Rspec'
55
+ Message: 'Rspec is a typo of RSpec'
56
+ MatchInComment: true
57
+ ```
58
+
59
+ ## Similar Projects
60
+
61
+ There are some similar projects to solve similar problems. Probably you should use one of the similar projects instead of rubocop-grep.
62
+
63
+ ### grep (1)
64
+
65
+ You can simply use `grep (1)` command, or `git grep (1)`.
66
+
67
+ * Pros
68
+ * They are available in most environments.
69
+ * You can use them for non-Ruby files too.
70
+ * Cons
71
+ * They are not integrated with RuboCop.
72
+ * rubocop-grep is fully integrated with RuboCop. It means you can integrate this gem out-of-the-box with CI, editors, and so on.
73
+ * But you need to set up a workflow for `grep (1)` if you want to use it on CI.
74
+ * They do not have a configuration file.
75
+ * You can configure rubocop-grep with `.rubocop.yml`, but you cannot configure grep.
76
+
77
+ If regexp is enough for your problem and you do not need RuboCop integration, `grep (1)` is a good solution.
78
+
79
+ ### Querly
80
+
81
+ https://github.com/soutaro/querly
82
+
83
+ Querly is a gem to detect a problem by the original query language.
84
+
85
+ * Pros
86
+ * The query is more powerful than regexp.
87
+ * It is based on AST, so you can ignore whitespaces, the order of keyword arguments, and so on.
88
+ * Cons
89
+ * They are not integrated with RuboCop.
90
+
91
+ If you need more powerful queries and you do not need RuboCop integration, Querly is a good solution.
92
+
93
+ ### Goodcheck
94
+
95
+ https://github.com/sider/goodcheck
96
+
97
+ Goodcheck is a linter based on Regexp.
98
+
99
+ * Pros
100
+ * It supports a tokenizer too.
101
+ * If you use a tokenizer, you don't need to care about whitespaces.
102
+ * You can use it for non-Ruby files too.
103
+ * It has a configuration file.
104
+ * Cons
105
+ * They are not integrated with RuboCop.
106
+
107
+ If regexp is enough for your problem and you do not need RuboCop integration, Goodcheck is a good solution.
108
+
109
+ ### Creating a custom cop by yourself
110
+
111
+ You can also create a custom cop by yourself to solve your problem.
112
+
113
+ * Pros
114
+ * Creating a custom cop is the most powerful approach in similar projects.
115
+ * It can find any problem that can be detected statically.
116
+ * Cons
117
+ * You need to know AST, RuboCop API, and so on.
118
+
119
+ If regexp is not enough for your problem and you are familiar with RuboCop, creating a custom cop is a good solution.
120
+
121
+ ## Development
122
+
123
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
124
+
125
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
126
+
127
+ ## Contributing
128
+
129
+ Bug reports and pull requests are welcome on GitHub at https://github.com/pocke/rubocop-grep.
data/Rakefile ADDED
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "bundler/gem_tasks"
4
+ require "rspec/core/rake_task"
5
+
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ require "rubocop/rake_task"
9
+
10
+ RuboCop::RakeTask.new
11
+
12
+ task default: %i[spec rubocop]
13
+
14
+ require 'rspec/core/rake_task'
15
+
16
+ RSpec::Core::RakeTask.new(:spec) do |spec|
17
+ spec.pattern = FileList['spec/**/*_spec.rb']
18
+ end
19
+
20
+ desc 'Generate a new cop with a template'
21
+ task :new_cop, [:cop] do |_task, args|
22
+ require 'rubocop'
23
+
24
+ cop_name = args.fetch(:cop) do
25
+ warn 'usage: bundle exec rake new_cop[Department/Name]'
26
+ exit!
27
+ end
28
+
29
+ generator = RuboCop::Cop::Generator.new(cop_name)
30
+
31
+ generator.write_source
32
+ generator.write_spec
33
+ generator.inject_require(root_file_path: 'lib/rubocop/cop/grep_cops.rb')
34
+ generator.inject_config(config_file_path: 'config/default.yml')
35
+
36
+ puts generator.todo
37
+ end
data/Steepfile ADDED
@@ -0,0 +1,10 @@
1
+ D = Steep::Diagnostic
2
+
3
+ target :lib do
4
+ signature "sig"
5
+
6
+ check "lib"
7
+ configure_code_diagnostics(D::Ruby.all_error) do |hash|
8
+ hash[D::Ruby::MethodDefinitionMissing] = :hint
9
+ end
10
+ end
@@ -0,0 +1,6 @@
1
+ # Write it!
2
+
3
+ Grep/Grep:
4
+ Description: 'It is a RuboCop extension to define your own cop with regexps.'
5
+ Enabled: true
6
+ VersionAdded: '0.1'
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Grep
6
+ # Detect code snippets which are matched with specified Regexps.
7
+ class Grepx < Base
8
+ include RangeHelp
9
+
10
+ def on_new_investigation
11
+ source = processed_source.raw_source
12
+
13
+ cop_config['Rules'].each do |rule|
14
+ match_comment = rule['MatchInComment']
15
+
16
+ # @type var patterns: Array[String]
17
+ patterns = _ = Array(rule['Pattern'])
18
+
19
+ opt = regexp_option(rule)
20
+ patterns.each do |pat|
21
+ re = Regexp.new(pat, opt)
22
+ from = 0
23
+ while m = re.match(source, from)
24
+ if match_comment || !in_comment?(m)
25
+ pos = position_from_matchdata(m)
26
+ range = source_range(processed_source.buffer, pos[:line], pos[:column], pos[:length])
27
+ add_offense(range, message: rule['Message'])
28
+ end
29
+ from = m.end(0) || raise
30
+ end
31
+ end
32
+ end
33
+ end
34
+
35
+ private def position_from_matchdata(m)
36
+ pre_match = m.pre_match
37
+ line = pre_match.count("\n") + 1
38
+ column = pre_match[/^([^\n]*)\z/, 1]&.size || 0
39
+ matched = m[0] or raise
40
+ length = matched.size
41
+
42
+ { line: line, column: column, length: length }
43
+ end
44
+
45
+ private def in_comment?(m)
46
+ line = position_from_matchdata(m)[:line]
47
+ processed_source.comments.any? { |c| c.loc.line == line }
48
+ end
49
+
50
+ private def regexp_option(rule)
51
+ opt = 0
52
+ opt |= Regexp::MULTILINE if rule['Multiline']
53
+ opt |= Regexp::EXTENDED if rule['Extended']
54
+ opt |= Regexp::IGNORECASE if rule['Ignorecase']
55
+ opt
56
+ end
57
+ end
58
+
59
+ Grep = _ = Grepx
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,2 @@
1
+ # frozen_string_literal: true
2
+ require_relative 'grep/grep'
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ # The original code is from https://github.com/rubocop/rubocop-rspec/blob/master/lib/rubocop/rspec/inject.rb
4
+ # See https://github.com/rubocop/rubocop-rspec/blob/master/MIT-LICENSE.md
5
+ module RuboCop
6
+ module Grep
7
+ # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
8
+ # bit of our configuration.
9
+ module Inject
10
+ def self.defaults!
11
+ path = CONFIG_DEFAULT.to_s
12
+ hash = ConfigLoader.send(:load_yaml_configuration, path)
13
+ config = (_ = Config.new(hash, path)).tap(&:make_excludes_absolute)
14
+ puts "configuration from #{path}" if ConfigLoader.debug?
15
+ config = ConfigLoader.merge_with_default(config, path)
16
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Grep
5
+ VERSION = "0.1.0"
6
+ end
7
+ end
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "grep/version"
4
+
5
+ module RuboCop
6
+ module Grep
7
+ # Your code goes here...
8
+ PROJECT_ROOT = Pathname.new(__dir__ || raise).parent.parent.expand_path.freeze
9
+ CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
10
+ CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
11
+
12
+ private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
13
+ end
14
+ end
15
+
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ require_relative 'rubocop/grep'
6
+ require_relative 'rubocop/grep/version'
7
+ require_relative 'rubocop/grep/inject'
8
+
9
+ RuboCop::Grep::Inject.defaults!
10
+
11
+ require_relative 'rubocop/cop/grep_cops'
@@ -0,0 +1,54 @@
1
+ ---
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ revision: 7765c1821affc50f5b09fda8fba3a7c9b429b216
6
+ remote: https://github.com/ruby/gem_rbs_collection.git
7
+ repo_dir: gems
8
+ path: ".gem_rbs_collection"
9
+ gems:
10
+ - name: ast
11
+ version: '2.4'
12
+ source:
13
+ type: git
14
+ name: ruby/gem_rbs_collection
15
+ revision: 03012a67119a706eb045ed758b8366b03eefc3cd
16
+ remote: https://github.com/ruby/gem_rbs_collection.git
17
+ repo_dir: gems
18
+ - name: dbm
19
+ version: '0'
20
+ source:
21
+ type: stdlib
22
+ - name: json
23
+ version: '0'
24
+ source:
25
+ type: stdlib
26
+ - name: parallel
27
+ version: '1.20'
28
+ source:
29
+ type: git
30
+ name: ruby/gem_rbs_collection
31
+ revision: 7765c1821affc50f5b09fda8fba3a7c9b429b216
32
+ remote: https://github.com/ruby/gem_rbs_collection.git
33
+ repo_dir: gems
34
+ - name: pathname
35
+ version: '0'
36
+ source:
37
+ type: stdlib
38
+ - name: pstore
39
+ version: '0'
40
+ source:
41
+ type: stdlib
42
+ - name: rainbow
43
+ version: '3.0'
44
+ source:
45
+ type: git
46
+ name: ruby/gem_rbs_collection
47
+ revision: 03012a67119a706eb045ed758b8366b03eefc3cd
48
+ remote: https://github.com/ruby/gem_rbs_collection.git
49
+ repo_dir: gems
50
+ - name: yaml
51
+ version: '0'
52
+ source:
53
+ type: stdlib
54
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,21 @@
1
+ # Download sources
2
+ sources:
3
+ - name: ruby/gem_rbs_collection
4
+ remote: https://github.com/ruby/gem_rbs_collection.git
5
+ revision: main
6
+ repo_dir: gems
7
+
8
+ # A directory to install the downloaded RBSs
9
+ path: .gem_rbs_collection
10
+
11
+ gems:
12
+ # Skip loading rbs gem's RBS.
13
+ # It's unnecessary if you don't use rbs as a library.
14
+ - name: rbs
15
+ ignore: true
16
+ - name: steep
17
+ ignore: true
18
+ - name: rubocop-grep
19
+ ignore: true
20
+ - name: pathname
21
+ - name: yaml
@@ -0,0 +1,38 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "lib/rubocop/grep/version"
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = "rubocop-grep"
7
+ spec.version = RuboCop::Grep::VERSION
8
+ spec.authors = ["Masataka Pocke Kuwabara"]
9
+ spec.email = ["kuwabara@pocke.me"]
10
+
11
+ spec.summary = "It is a RuboCop extension to define your own cop with regexps."
12
+ spec.description = "It is a RuboCop extension to define your own cop with regexps."
13
+ spec.homepage = "https://github.com/pocke/rubocop-grep"
14
+ spec.required_ruby_version = ">= 3.0.0"
15
+
16
+ spec.metadata["homepage_uri"] = spec.homepage
17
+ spec.metadata["source_code_uri"] = spec.homepage
18
+ # spec.metadata["changelog_uri"] = "TODO: Put your gem's CHANGELOG.md URL here."
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(__dir__) do
23
+ `git ls-files -z`.split("\x0").reject do |f|
24
+ (f == __FILE__) || f.match(%r{\A(?:(?:bin|test|spec|features)/|\.(?:git|circleci)|appveyor)})
25
+ end
26
+ end
27
+ spec.bindir = "exe"
28
+ spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
29
+ spec.require_paths = ["lib"]
30
+
31
+ # Uncomment to register a new dependency of your gem
32
+ # spec.add_dependency "example-gem", "~> 1.0"
33
+
34
+ # For more information and examples about making a new gem, check out our
35
+ # guide at: https://bundler.io/guides/creating_gem.html
36
+
37
+ spec.add_runtime_dependency 'rubocop'
38
+ end
data/sig/_shim.rbs ADDED
@@ -0,0 +1,66 @@
1
+ module RuboCop
2
+ class ConfigLoader
3
+ def self.debug?: () -> boolish
4
+ def self.merge_with_default: (Config, String) -> Config
5
+ end
6
+
7
+ class Config
8
+ def initialize: (Hash[untyped, untyped], String) -> void
9
+ end
10
+
11
+ module Cop
12
+ class Base
13
+ extend AST::NodePattern::Macros
14
+
15
+ def add_offense: (untyped node, ?message: String) -> void
16
+ def cop_config: () -> Hash[String, untyped]
17
+ def processed_source: () -> AST::ProcessedSource
18
+ end
19
+
20
+ module RangeHelp
21
+ def source_range: (Parser::Source::Buffer source_buffer, Integer line_number, Integer column, ?Integer length) -> Parser::Source::Range
22
+ end
23
+ end
24
+
25
+ class ProcessedSource = AST::ProcessedSource
26
+ end
27
+
28
+ module RuboCop
29
+ module AST
30
+ class ProcessedSource
31
+ def raw_source: () -> String
32
+ def buffer: () -> Parser::Source::Buffer
33
+ def comments: () -> Array[Parser::Source::Comment]
34
+ end
35
+
36
+ module NodePattern
37
+ module Macros
38
+ def def_node_matcher: (Symbol, String) -> void
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ module Parser
45
+ module Source
46
+ class Range
47
+ end
48
+
49
+ class Buffer
50
+ end
51
+
52
+ class Map
53
+ def line: () -> Integer
54
+ def first_line: () -> Integer
55
+ def last_line: () -> Integer
56
+ def column: () -> Integer
57
+ def first_column: () -> Integer
58
+ def last_column: () -> Integer
59
+ end
60
+
61
+ class Comment
62
+ def location: () -> Map
63
+ alias loc location
64
+ end
65
+ end
66
+ end
data/sig/manifest.yaml ADDED
@@ -0,0 +1,3 @@
1
+ dependencies:
2
+ - name: yaml
3
+ - name: pathname
@@ -0,0 +1,40 @@
1
+ module RuboCop
2
+ module Cop
3
+ module Grep
4
+ class Grepx < ::RuboCop::Cop::Base
5
+ include RangeHelp
6
+
7
+ type rule = {
8
+ 'Pattern' => String | Array[String],
9
+ 'Message' => String,
10
+ 'MatchInComment' => bool?,
11
+
12
+ # Regexp options
13
+ 'Multiline' => bool?,
14
+ 'Extended' => bool?,
15
+ 'Ignorecase' => bool?,
16
+ }
17
+
18
+ type config = {
19
+ 'Rules' => Array[rule]
20
+ }
21
+
22
+ def on_new_investigation: () -> void
23
+
24
+ private def position_from_matchdata: (MatchData) -> {
25
+ line: Integer,
26
+ column: Integer,
27
+ length: Integer,
28
+ }
29
+
30
+ private def in_comment?: (MatchData) -> bool
31
+
32
+ private def regexp_option: (rule) -> Integer
33
+
34
+ def cop_config: () -> config
35
+ end
36
+ # HACK: Steep has a bug when the class name is the same as the parent namespace name.
37
+ class Grep = Grepx
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,7 @@
1
+ module RuboCop
2
+ module Grep
3
+ module Inject
4
+ def self.defaults!: () -> void
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ module RuboCop
2
+ module Grep
3
+ VERSION: String
4
+
5
+ PROJECT_ROOT: Pathname
6
+ CONFIG_DEFAULT: Pathname
7
+ CONFIG: untyped
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,79 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rubocop-grep
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Masataka Pocke Kuwabara
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2023-03-05 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rubocop
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ description: It is a RuboCop extension to define your own cop with regexps.
28
+ email:
29
+ - kuwabara@pocke.me
30
+ executables: []
31
+ extensions: []
32
+ extra_rdoc_files: []
33
+ files:
34
+ - ".rspec"
35
+ - ".rubocop.yml"
36
+ - Gemfile
37
+ - README.md
38
+ - Rakefile
39
+ - Steepfile
40
+ - config/default.yml
41
+ - lib/rubocop-grep.rb
42
+ - lib/rubocop/cop/grep/grep.rb
43
+ - lib/rubocop/cop/grep_cops.rb
44
+ - lib/rubocop/grep.rb
45
+ - lib/rubocop/grep/inject.rb
46
+ - lib/rubocop/grep/version.rb
47
+ - rbs_collection.lock.yaml
48
+ - rbs_collection.yaml
49
+ - rubocop-grep.gemspec
50
+ - sig/_shim.rbs
51
+ - sig/manifest.yaml
52
+ - sig/rubocop/cop/cop/grep.rbs
53
+ - sig/rubocop/grep.rbs
54
+ - sig/rubocop/grep/inject.rbs
55
+ homepage: https://github.com/pocke/rubocop-grep
56
+ licenses: []
57
+ metadata:
58
+ homepage_uri: https://github.com/pocke/rubocop-grep
59
+ source_code_uri: https://github.com/pocke/rubocop-grep
60
+ post_install_message:
61
+ rdoc_options: []
62
+ require_paths:
63
+ - lib
64
+ required_ruby_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: '0'
74
+ requirements: []
75
+ rubygems_version: 3.5.0.dev
76
+ signing_key:
77
+ specification_version: 4
78
+ summary: It is a RuboCop extension to define your own cop with regexps.
79
+ test_files: []