rubocop-faker 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rubocop'
4
+
5
+ require_relative 'rubocop/faker'
6
+ require_relative 'rubocop/faker/version'
7
+ require_relative 'rubocop/faker/inject'
8
+
9
+ RuboCop::Faker::Inject.defaults!
10
+
11
+ require_relative 'rubocop/cop/faker_cops'
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Faker
6
+ #
7
+ # Checks that Faker arguments style is based on Faker 2.
8
+ # Use keyword arguments instead of positional arguments.
9
+ #
10
+ # @example
11
+ # # bad
12
+ # Avatar.image(slug, size, format)
13
+ #
14
+ # # good
15
+ # Avatar.image(slug: slug, size: size, format: format)
16
+ #
17
+ class DeprecatedArguments < Cop
18
+ include RangeHelp
19
+
20
+ MSG = 'Passing `%<arg>s` with the %<index>s argument of ' \
21
+ '`%<class_name>s.%<method_name>s` is deprecated. ' \
22
+ 'Use keyword argument like `%<class_name>s.%<method_name>s' \
23
+ '(%<keyword>s: %<arg>s)` instead.'
24
+
25
+ def on_send(node)
26
+ return unless node.receiver
27
+
28
+ class_name = faker_class_name(node)
29
+
30
+ return unless (methods = argument_keywords[class_name])
31
+ return unless (keywords = methods[node.method_name.to_s])
32
+
33
+ node.arguments.each_with_index do |argument, index|
34
+ next if argument.hash_type?
35
+
36
+ message = format_message(
37
+ keyword: keywords[index], arg: argument.source,
38
+ class_name: class_name, index: index,
39
+ method_name: node.method_name
40
+ )
41
+
42
+ add_offense_for_arguments(node, argument, message)
43
+ end
44
+ end
45
+
46
+ def autocorrect(node)
47
+ methods = argument_keywords[faker_class_name(node)]
48
+ keywords = methods[node.method_name.to_s]
49
+
50
+ kwargs = build_kwargs_style(node, keywords)
51
+
52
+ lambda do |corrector|
53
+ corrector.replace(arguments_range(node), kwargs)
54
+ end
55
+ end
56
+
57
+ private
58
+
59
+ def format_message(keyword:, arg:, index:, class_name:, method_name:)
60
+ i = case index
61
+ when 0 then '1st'
62
+ when 1 then '2nd'
63
+ when 2 then '3rd'
64
+ else "#{index + 1}th"
65
+ end
66
+ format(
67
+ MSG,
68
+ keyword: keyword,
69
+ arg: arg,
70
+ index: i,
71
+ class_name: class_name,
72
+ method_name: method_name
73
+ )
74
+ end
75
+
76
+ def add_offense_for_arguments(node, argument, message)
77
+ add_offense(
78
+ node,
79
+ location: argument.source_range,
80
+ message: message
81
+ )
82
+ end
83
+
84
+ def build_kwargs_style(node, keywords)
85
+ node.arguments.map.with_index do |positional_argument, index|
86
+ if positional_argument.hash_type?
87
+ positional_argument.source
88
+ else
89
+ "#{keywords[index]}: #{positional_argument.source}"
90
+ end
91
+ end.join(', ')
92
+ end
93
+
94
+ def faker_class_name(node)
95
+ node.receiver.source
96
+ end
97
+
98
+ def arguments_range(node)
99
+ arguments = node.arguments
100
+
101
+ range_between(
102
+ arguments.first.source_range.begin_pos,
103
+ arguments.last.source_range.end_pos
104
+ )
105
+ end
106
+
107
+ def argument_keywords
108
+ cop_config.fetch('ArgumentKeywords', {})
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'faker/deprecated_arguments'
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ # RuboCop Faker project namespace
5
+ module Faker
6
+ PROJECT_ROOT = Pathname.new(__dir__).parent.parent.expand_path.freeze
7
+ CONFIG_DEFAULT = PROJECT_ROOT.join('config', 'default.yml').freeze
8
+ CONFIG = YAML.safe_load(CONFIG_DEFAULT.read).freeze
9
+
10
+ private_constant(:CONFIG_DEFAULT, :PROJECT_ROOT)
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Faker
5
+ # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
6
+ # bit of our configuration.
7
+ module Inject
8
+ def self.defaults!
9
+ path = CONFIG_DEFAULT.to_s
10
+ hash = ConfigLoader.send(:load_yaml_configuration, path)
11
+ config = Config.new(hash, path)
12
+ puts "configuration from #{path}" if ConfigLoader.debug?
13
+ config = ConfigLoader.merge_with_default(config, path)
14
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Faker
5
+ VERSION = '0.1.0'
6
+ end
7
+ end
@@ -0,0 +1,6 @@
1
+ <!-- START_COP_LIST -->
2
+ #### Department [Faker](cops_faker.md)
3
+
4
+ * [Faker/DeprecatedArguments](cops_faker.md#fakerdeprecatedarguments)
5
+
6
+ <!-- END_COP_LIST -->
@@ -0,0 +1,30 @@
1
+ # Faker
2
+
3
+ ## Faker/DeprecatedArguments
4
+
5
+ Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
6
+ --- | --- | --- | --- | ---
7
+ Enabled | Yes | Yes | 0.1 | -
8
+
9
+ Checks that Faker arguments style is based on Faker 2.
10
+ Use keyword arguments instead of positional arguments.
11
+
12
+ ### Examples
13
+
14
+ ```ruby
15
+ # bad
16
+ Avatar.image(slug, size, format)
17
+
18
+ # good
19
+ Avatar.image(slug: slug, size: size, format: format)
20
+ ```
21
+
22
+ ### Configurable attributes
23
+
24
+ Name | Default value | Configurable values
25
+ --- | --- | ---
26
+ ArgumentKeywords | `{"Faker::Dune"=>{"quote"=>["character"], "saying"=>["source"]}, "Faker::Books::Lovecraft"=>{"fhtagn"=>["number"], "sentence"=>["word_count", "random_words_to_add"], "words"=>["number", "spaces_allowed"], "sentences"=>["number"], "paragraph"=>["sentence_count", "random_sentences_to_add"], "paragraphs"=>["number"], "paragraph_by_chars"=>["characters"]}, "Faker::Address"=>{"city"=>["options"], "street_address"=>["include_secondary"], "zip_code"=>["state_abbreviation"], "country_by_code"=>["code"], "country_name_to_code"=>["name"]}, "Faker::Alphanumeric"=>{"alpha"=>["number"], "alphanumeric"=>["number"]}, "Faker::App"=>{"semantic_version"=>["major", "minor", "patch"]}, "Faker::Avatar"=>{"image"=>["slug", "size", "format", "set", "bgset"]}, "Faker::Bank"=>{"account_number"=>["digits"], "iban"=>["country_code"]}, "Faker::Boolean"=>{"boolean"=>["true_ratio"]}, "Faker::ChileRut"=>{"rut"=>["min_rut", "fixed"], "full_rut"=>["min_rut", "fixed"]}, "Faker::Code"=>{"isbn"=>["base"], "ean"=>["base"], "nric"=>["min_age", "max_age"]}, "Faker::Commerce"=>{"promotion_code"=>["digits"], "department"=>["max", "fixed_amount"], "price"=>["range", "as_string"]}, "Faker::Company"=>{"polish_register_of_national_economy"=>["length"], "brazilian_company_number"=>["formatted"]}, "Faker::CryptoCoin"=>{"coin_name"=>["coin"], "acronym"=>["coin"], "url_logo"=>["coin"]}, "Faker::Date"=>{"between"=>["from", "to"], "between_except"=>["from", "to", "excepted"], "forward"=>["days"], "backward"=>["days"], "birthday"=>["min_age", "max_age"]}, "Faker::Demographic"=>{"height"=>["unit"]}, "Faker::DrivingLicence"=>{"british_driving_licence"=>["last_name", "initials", "gender", "date_of_birth"]}, "Faker::File"=>{"dir"=>["segment_count", "root", "directory_separator"], "file_name"=>["dir", "name", "ext", "directory_separator"]}, "Faker::Fillmurray"=>{"image"=>["grayscale", "width", "height"]}, "Faker::Finance"=>{"vat_number"=>["country"]}, "Faker::Hipster"=>{"words"=>["number", "supplemental", "spaces_allowed"], "sentence"=>["word_count", "supplemental", "random_words_to_add"], "sentences"=>["number", "supplemental"], "paragraph"=>["sentence_count", "supplemental", "random_sentences_to_add"], "paragraphs"=>["number", "supplemental"], "paragraph_by_chars"=>["characters", "supplemental"]}, "Faker::IDNumber"=>{"brazilian_citizen_number"=>["formatted"], "brazilian_id"=>["formatted"]}, "Faker::Internet"=>{"email"=>["name", "separators"], "free_email"=>["name"], "safe_email"=>["name"], "username"=>["specifier", "separators"], "password"=>["min_length", "max_length", "mix_case", "special_characters"], "domain_name"=>["subdomain"], "fix_umlauts"=>["string"], "mac_address"=>["prefix"], "url"=>["host", "path", "scheme"], "slug"=>["words", "glue"], "user_agent"=>["vendor"]}, "Faker::Invoice"=>{"amount_between"=>["from", "to"], "creditor_reference"=>["ref"], "reference"=>["ref"]}, "Faker::Json"=>{"shallow_json"=>["width", "options"], "add_depth_to_json"=>["json", "width", "options"]}, "Faker::Lorem"=>{"words"=>["number", "supplemental"], "characters"=>["number"], "sentence"=>["word_count", "supplemental", "random_words_to_add"], "sentences"=>["number", "supplemental"], "paragraph"=>["sentence_count", "supplemental", "random_sentences_to_add"], "paragraphs"=>["number", "supplemental"], "paragraph_by_chars"=>["number", "supplemental"], "question"=>["word_count", "supplemental", "random_words_to_add"], "questions"=>["number", "supplemental"]}, "Faker::LoremFlickr"=>{"image"=>["size", "search_terms", "match_all"], "grayscale_image"=>["size", "search_terms", "match_all"], "pixelated_image"=>["size", "search_terms", "match_all"], "colorized_image"=>["size", "color", "search_terms", "match_all"]}, "Faker::LoremPixel"=>{"image"=>["size", "is_gray", "category", "number", "text", "secure"]}, "Faker::Markdown"=>{"sandwich"=>["sentences", "repeat"]}, "Faker::Measurement"=>{"height"=>["amount"], "length"=>["amount"], "volume"=>["amount"], "weight"=>["amount"], "metric_height"=>["amount"], "metric_length"=>["amount"], "metric_volume"=>["amount"], "metric_weight"=>["amount"]}, "Faker::Name"=>{"initials"=>["number"]}, "Faker::NationalHealthService"=>{"check_digit"=>["number"]}, "Faker::Number"=>{"number"=>["digits"], "leading_zero_number"=>["digits"], "decimal_part"=>["digits"], "decimal"=>["l_digits", "r_digits"], "hexadecimal"=>["digits"], "normal"=>["mean", "standard_deviation"], "between"=>["from", "to"], "within"=>["range"], "positive"=>["from", "to"], "negative"=>["from", "to"]}, "Faker::Omniauth"=>{"google"=>["name", "email", "uid"], "facebook"=>["name", "email", "username", "uid"], "twitter"=>["name", "nickname", "uid"], "linkedin"=>["name", "email", "uid"], "github"=>["name", "email", "uid"]}, "Faker::PhoneNumber"=>{"subscriber_number"=>["length"]}, "Faker::Placeholdit"=>{"image"=>["size", "format", "background_color", "text_color", "text"]}, "Faker::Relationship"=>{"familial"=>["connection"]}, "Faker::Source"=>{"hello_world"=>["lang"], "print"=>["str", "lang"], "print_1_to_10"=>["lang"]}, "Faker::String"=>{"random"=>["length"]}, "Faker::Stripe"=>{"valid_card"=>["card_type"], "valid_token"=>["card_type"], "invalid_card"=>["card_error"], "ccv"=>["card_type"]}, "Faker::Time"=>{"between"=>["from", "to", "format"], "between_dates"=>["from", "to", "period", "format"], "forward"=>["days", "period", "format"], "backward"=>["days", "period", "format"]}, "Faker::Twitter"=>{"user"=>["include_status", "include_email"], "status"=>["include_user", "include_photo"], "status_entities"=>["include_photo"]}, "Faker::Types"=>{"rb_string"=>["words"], "rb_integer"=>["from", "to"], "rb_hash"=>["number", "type"], "complex_rb_hash"=>["number"], "rb_array"=>["len"]}, "Faker::Vehicle"=>{"model"=>["make_of_model"], "mileage"=>["min", "max"], "license_plate"=>["state_abreviation"]}, "Faker::WorldCup"=>{"group"=>["group"], "roster"=>["country", "type"]}, "Faker::Dota"=>{"quote"=>["hero"]}, "Faker::Movies::StarWars"=>{"quote"=>["character"]}}` |
27
+
28
+ ### References
29
+
30
+ * [https://github.com/faker-ruby/faker/blob/master/CHANGELOG.md#v20-2019-31-07](https://github.com/faker-ruby/faker/blob/master/CHANGELOG.md#v20-2019-31-07)
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'lib/rubocop/faker/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'rubocop-faker'
7
+ spec.version = RuboCop::Faker::VERSION
8
+ spec.authors = ['Koichi ITO']
9
+ spec.email = ['koic.ito@gmail.com']
10
+
11
+ spec.summary = 'A RuboCop extension for Faker'
12
+ spec.description = 'A RuboCop extension for Faker'
13
+ spec.homepage = 'https://github.com/koic/rubocop-faker'
14
+ spec.license = 'MIT'
15
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
16
+
17
+ spec.metadata['homepage_uri'] = spec.homepage
18
+
19
+ # Specify which files should be added to the gem when it is released.
20
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
21
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
22
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
23
+ end
24
+ spec.bindir = 'exe'
25
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
26
+ spec.require_paths = ['lib']
27
+
28
+ spec.add_runtime_dependency 'rubocop', '>= 0.74'
29
+ end
@@ -0,0 +1,310 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'yard'
4
+ require 'rubocop'
5
+ require 'rubocop-faker'
6
+
7
+ YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task|
8
+ task.files = ['lib/rubocop/cop/**/*.rb']
9
+ task.options = ['--no-output']
10
+ end
11
+
12
+ desc 'Generate docs of all cops departments'
13
+ task generate_cops_documentation: :yard_for_generate_documentation do
14
+ def cops_of_department(cops, department)
15
+ cops.with_department(department).sort!
16
+ end
17
+
18
+ def cops_body(config, cop, description, examples_objects, pars)
19
+ content = h2(cop.cop_name)
20
+ content << properties(config, cop)
21
+ content << "#{description}\n"
22
+ content << examples(examples_objects) if examples_objects.count.positive?
23
+ content << configurations(pars)
24
+ content << references(config, cop)
25
+ content
26
+ end
27
+
28
+ def examples(examples_object)
29
+ examples_object.each_with_object(h3('Examples').dup) do |example, content|
30
+ content << h4(example.name) unless example.name == ''
31
+ content << code_example(example)
32
+ end
33
+ end
34
+
35
+ # rubocop:disable Metrics/MethodLength
36
+ def properties(config, cop)
37
+ header = [
38
+ 'Enabled by default', 'Safe', 'Supports autocorrection', 'VersionAdded',
39
+ 'VersionChanged'
40
+ ]
41
+ config = config.for_cop(cop)
42
+ safe_auto_correct = config.fetch('SafeAutoCorrect', true)
43
+ autocorrect = if cop.new.support_autocorrect?
44
+ "Yes #{'(Unsafe)' unless safe_auto_correct}"
45
+ else
46
+ 'No'
47
+ end
48
+ content = [[
49
+ config.fetch('Enabled') ? 'Enabled' : 'Disabled',
50
+ config.fetch('Safe', true) ? 'Yes' : 'No',
51
+ autocorrect,
52
+ config.fetch('VersionAdded', '-'),
53
+ config.fetch('VersionChanged', '-')
54
+ ]]
55
+ to_table(header, content) + "\n"
56
+ end
57
+ # rubocop:enable Metrics/MethodLength
58
+
59
+ def h2(title)
60
+ content = +"\n"
61
+ content << "## #{title}\n"
62
+ content << "\n"
63
+ content
64
+ end
65
+
66
+ def h3(title)
67
+ content = +"\n"
68
+ content << "### #{title}\n"
69
+ content << "\n"
70
+ content
71
+ end
72
+
73
+ def h4(title)
74
+ content = +"#### #{title}\n"
75
+ content << "\n"
76
+ content
77
+ end
78
+
79
+ def code_example(ruby_code)
80
+ content = +"```ruby\n"
81
+ content << ruby_code.text
82
+ .gsub('@good', '# good').gsub('@bad', '# bad').strip
83
+ content << "\n```\n"
84
+ content
85
+ end
86
+
87
+ def configurations(pars)
88
+ return '' if pars.empty?
89
+
90
+ header = ['Name', 'Default value', 'Configurable values']
91
+ configs = pars.each_key.reject { |key| key.start_with?('Supported') }
92
+ content = configs.map do |name|
93
+ configurable = configurable_values(pars, name)
94
+ default = format_table_value(pars[name])
95
+ [name, default, configurable]
96
+ end
97
+
98
+ h3('Configurable attributes') + to_table(header, content)
99
+ end
100
+
101
+ # rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
102
+ def configurable_values(pars, name)
103
+ case name
104
+ when /^Enforced/
105
+ supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
106
+ format_table_value(pars[supported_style_name])
107
+ when 'IndentationWidth'
108
+ 'Integer'
109
+ else
110
+ case pars[name]
111
+ when String
112
+ 'String'
113
+ when Integer
114
+ 'Integer'
115
+ when Float
116
+ 'Float'
117
+ when true, false
118
+ 'Boolean'
119
+ when Array
120
+ 'Array'
121
+ else
122
+ ''
123
+ end
124
+ end
125
+ end
126
+ # rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
127
+
128
+ def to_table(header, content)
129
+ table = [
130
+ header.join(' | '),
131
+ Array.new(header.size, '---').join(' | ')
132
+ ]
133
+ table.concat(content.map { |c| c.join(' | ') })
134
+ table.join("\n") + "\n"
135
+ end
136
+
137
+ def format_table_value(val)
138
+ value =
139
+ case val
140
+ when Array
141
+ if val.empty?
142
+ '`[]`'
143
+ else
144
+ val.map { |config| format_table_value(config) }.join(', ')
145
+ end
146
+ else
147
+ "`#{val.nil? ? '<none>' : val}`"
148
+ end
149
+ value.gsub("#{Dir.pwd}/", '').rstrip
150
+ end
151
+
152
+ def references(config, cop)
153
+ cop_config = config.for_cop(cop)
154
+ urls = RuboCop::Cop::MessageAnnotator.new(
155
+ config, cop.name, cop_config, {}
156
+ ).urls
157
+ return '' if urls.empty?
158
+
159
+ content = h3('References')
160
+ content << urls.map { |url| "* [#{url}](#{url})" }.join("\n")
161
+ content << "\n"
162
+ content
163
+ end
164
+
165
+ def print_cops_of_department(cops, department, config)
166
+ selected_cops = cops_of_department(cops, department).select do |cop|
167
+ cop.to_s.start_with?('RuboCop::Cop::Faker')
168
+ end
169
+ return if selected_cops.empty?
170
+
171
+ content = +"# #{department}\n"
172
+ selected_cops.each do |cop|
173
+ content << print_cop_with_doc(cop, config)
174
+ end
175
+ file_name = "#{Dir.pwd}/manual/cops_#{department.downcase}.md"
176
+ File.open(file_name, 'w') do |file|
177
+ puts "* generated #{file_name}"
178
+ file.write(content.strip + "\n")
179
+ end
180
+ end
181
+
182
+ def print_cop_with_doc(cop, config)
183
+ t = config.for_cop(cop)
184
+ non_display_keys = %w[
185
+ Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
186
+ VersionChanged
187
+ ]
188
+ pars = t.reject { |k| non_display_keys.include? k }
189
+ description = 'No documentation'
190
+ examples_object = []
191
+ YARD::Registry.all(:class).detect do |code_object|
192
+ next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
193
+
194
+ description = code_object.docstring unless code_object.docstring.blank?
195
+ examples_object = code_object.tags('example')
196
+ end
197
+ cops_body(config, cop, description, examples_object, pars)
198
+ end
199
+
200
+ # rubocop:disable Metrics/AbcSize
201
+ def table_of_content_for_department(cops, department)
202
+ selected_cops = cops_of_department(cops, department.to_sym).select do |cop|
203
+ cop.to_s.start_with?('RuboCop::Cop::Faker')
204
+ end
205
+ return if selected_cops.empty?
206
+
207
+ type_title = department[0].upcase + department[1..-1]
208
+ filename = "cops_#{department.downcase}.md"
209
+ content = +"#### Department [#{type_title}](#{filename})\n\n"
210
+ selected_cops.each do |cop|
211
+ anchor = cop.cop_name.sub('/', '').downcase
212
+ content << "* [#{cop.cop_name}](#{filename}##{anchor})\n"
213
+ end
214
+
215
+ content
216
+ end
217
+ # rubocop:enable Metrics/AbcSize
218
+
219
+ def print_table_of_contents(cops)
220
+ path = "#{Dir.pwd}/manual/cops.md"
221
+ original = File.read(path)
222
+ content = +"<!-- START_COP_LIST -->\n"
223
+
224
+ content << table_contents(cops)
225
+
226
+ content << "\n<!-- END_COP_LIST -->"
227
+
228
+ content = if original.empty?
229
+ content
230
+ else
231
+ original.sub(
232
+ /<!-- START_COP_LIST -->.+<!-- END_COP_LIST -->/m, content
233
+ )
234
+ end
235
+ File.write(path, content)
236
+ end
237
+
238
+ def table_contents(cops)
239
+ cops
240
+ .departments
241
+ .map(&:to_s)
242
+ .sort
243
+ .map { |department| table_of_content_for_department(cops, department) }
244
+ .reject(&:nil?)
245
+ .join("\n")
246
+ end
247
+
248
+ def assert_manual_synchronized
249
+ # Do not print diff and yield whether exit code was zero
250
+ sh('git diff --quiet manual') do |outcome, _|
251
+ return if outcome
252
+
253
+ # Output diff before raising error
254
+ sh('GIT_PAGER=cat git diff manual')
255
+
256
+ warn 'The manual directory is out of sync. ' \
257
+ 'Run `rake generate_cops_documentation` and commit the results.'
258
+ exit!
259
+ end
260
+ end
261
+
262
+ def main
263
+ cops = RuboCop::Cop::Cop.registry
264
+ config = RuboCop::ConfigLoader.load_file('config/default.yml')
265
+
266
+ YARD::Registry.load!
267
+ cops.departments.sort!.each do |department|
268
+ print_cops_of_department(cops, department, config)
269
+ end
270
+
271
+ print_table_of_contents(cops)
272
+
273
+ assert_manual_synchronized if ENV['CI'] == 'true'
274
+ ensure
275
+ RuboCop::ConfigLoader.default_configuration = nil
276
+ end
277
+
278
+ main
279
+ end
280
+
281
+ desc 'Syntax check for the documentation comments'
282
+ task documentation_syntax_check: :yard_for_generate_documentation do
283
+ require 'parser/ruby25'
284
+
285
+ ok = true
286
+ YARD::Registry.load!
287
+ cops = RuboCop::Cop::Cop.registry
288
+ cops.each do |cop|
289
+ examples = YARD::Registry.all(:class).find do |code_object|
290
+ next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
291
+
292
+ break code_object.tags('example')
293
+ end
294
+
295
+ examples.to_a.each do |example|
296
+ begin
297
+ buffer = Parser::Source::Buffer.new('<code>', 1)
298
+ buffer.source = example.text
299
+ parser = Parser::Ruby25.new(RuboCop::AST::Builder.new)
300
+ parser.diagnostics.all_errors_are_fatal = true
301
+ parser.parse(buffer)
302
+ rescue Parser::SyntaxError => e
303
+ path = example.object.file
304
+ puts "#{path}: Syntax Error in an example. #{e}"
305
+ ok = false
306
+ end
307
+ end
308
+ end
309
+ abort unless ok
310
+ end