inspecstyle 0.1.0 → 0.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.gitignore +1 -1
- data/Gemfile +1 -0
- data/Gemfile.lock +12 -7
- data/README.md +56 -5
- data/Rakefile +3 -0
- data/config/default.yml +18 -0
- data/doc/RuboCop.html +128 -0
- data/doc/RuboCop/Cop.html +117 -0
- data/doc/RuboCop/Cop/InSpecStyle.html +117 -0
- data/doc/RuboCop/Cop/InSpecStyle/AzureGenericResource.html +249 -0
- data/doc/RuboCop/Cop/InSpecStyle/DeprecatedAttributes.html +310 -0
- data/doc/RuboCop/Cop/InSpecStyle/FirstCop.html +345 -0
- data/doc/RuboCop/InSpecStyle.html +140 -0
- data/doc/RuboCop/InSpecStyle/Error.html +124 -0
- data/doc/RuboCop/InSpecStyle/Inject.html +195 -0
- data/doc/_index.html +211 -0
- data/doc/class_list.html +51 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +58 -0
- data/doc/css/style.css +496 -0
- data/doc/file.README.html +131 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +131 -0
- data/doc/js/app.js +314 -0
- data/doc/js/full_list.js +216 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +99 -0
- data/doc/top-level-namespace.html +110 -0
- data/lib/rubocop/cop/inspecstyle/azure_generic_resource.rb +34 -0
- data/lib/rubocop/cop/inspecstyle/deprecated_attributes.rb +15 -14
- data/lib/rubocop/cop/inspecstyle/first_cop.rb +0 -1
- data/lib/rubocop/cop/inspecstyle/oracle_db_session_pass.rb +37 -0
- data/lib/rubocop/cop/inspecstyle/shadow_properties.rb +59 -0
- data/lib/rubocop/cop/inspecstyle_cops.rb +3 -0
- data/lib/rubocop/inspecstyle/version.rb +1 -1
- data/notes-for-development.md +3 -0
- data/tasks/cops_documentation.rake +300 -0
- metadata +29 -2
@@ -1,11 +1,11 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
# TODO: when finished, run `rake generate_cops_documentation` to update the docs
|
4
3
|
module RuboCop
|
5
4
|
module Cop
|
6
5
|
module InSpecStyle
|
6
|
+
# Checks if deprecated method attribute is used.
|
7
7
|
#
|
8
|
-
# @example
|
8
|
+
# @example EnforcedStyle: InSpecStyle (default)
|
9
9
|
# # Attributes have been deprecated for inputs
|
10
10
|
# # https://github.com/inspec/inspec/issues/3802
|
11
11
|
#
|
@@ -26,24 +26,25 @@ module RuboCop
|
|
26
26
|
|
27
27
|
def on_send(node)
|
28
28
|
return unless attribute?(node)
|
29
|
-
|
29
|
+
|
30
|
+
add_offense(node, location: node.loc.selector)
|
31
|
+
end
|
32
|
+
|
33
|
+
def autocorrect(node)
|
34
|
+
lambda do |corrector|
|
35
|
+
corrector.replace(offense_range(node), preferred_replacement)
|
36
|
+
end
|
30
37
|
end
|
31
38
|
|
32
39
|
private
|
33
40
|
|
34
|
-
def
|
35
|
-
|
36
|
-
range_between(node.source_range.begin_pos,
|
37
|
-
node.source_range.begin_pos+9
|
38
|
-
)
|
41
|
+
def offense_range(node)
|
42
|
+
node.loc.selector
|
39
43
|
end
|
40
44
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
# corrector.remove(node.source_range, 'attribute')
|
45
|
-
# end
|
46
|
-
# end
|
45
|
+
def preferred_replacement
|
46
|
+
cop_config.fetch('PreferredReplacement')
|
47
|
+
end
|
47
48
|
end
|
48
49
|
end
|
49
50
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module InSpecStyle
|
6
|
+
#
|
7
|
+
# @example EnforcedStyle: InSpecStyle (default)
|
8
|
+
# # Description of the `bar` style.
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# sql = oracledb_session(user: 'my_user', pass: 'password')
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# sql = oracledb_session(user: 'my_user', password: 'password')
|
15
|
+
class OracleDbSessionPass < Cop
|
16
|
+
include MatchRange
|
17
|
+
MSG = 'Use `:password` instead of `:pass`.'
|
18
|
+
|
19
|
+
def_node_matcher :oracledb_session_pass?, <<~PATTERN
|
20
|
+
(send _ :oracledb_session
|
21
|
+
(hash
|
22
|
+
...
|
23
|
+
(pair
|
24
|
+
(sym $:pass)
|
25
|
+
...)))
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
# Getting location was a bit tricky on this one, looking at docs perhaps
|
29
|
+
# convention does allow highlighting an entire line.
|
30
|
+
def on_send(node)
|
31
|
+
return unless result = oracledb_session_pass?(node)
|
32
|
+
add_offense(node, message: MSG)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# NOTE TO SELF - this one isn't currently working even though my pattern works in Rubocop's bin/console
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
module Cop
|
7
|
+
module InSpecStyle
|
8
|
+
# Shadow resource property user is deprecated in favor of `users`
|
9
|
+
#
|
10
|
+
# @example EnforcedStyle: InSpecStyle (default)
|
11
|
+
# # Use users instead
|
12
|
+
#
|
13
|
+
# # bad
|
14
|
+
# describe shadow('/etc/my-custom-place/shadow') do
|
15
|
+
# its('user') { should eq 'user' }
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # good
|
19
|
+
# describe shadow('/etc/my-custom-place/shadow') do
|
20
|
+
# its('users') { should eq 'user' }
|
21
|
+
# end
|
22
|
+
#
|
23
|
+
class ShadowProperties < Cop
|
24
|
+
# TODO: Implement the cop in here.
|
25
|
+
#
|
26
|
+
# In many cases, you can use a node matcher for matching node pattern.
|
27
|
+
# See https://github.com/rubocop-hq/rubocop-ast/blob/master/lib/rubocop/node_pattern.rb
|
28
|
+
#
|
29
|
+
# For example
|
30
|
+
MSG = 'Use `#users` instead of `#user`. This property will be removed '\
|
31
|
+
'in InSpec 5'
|
32
|
+
|
33
|
+
def_node_matcher :shadow_resource_user_property?, <<~PATTERN
|
34
|
+
(block
|
35
|
+
(send _ :describe
|
36
|
+
(send _ :shadow ...) ...)
|
37
|
+
(args ...)
|
38
|
+
(block
|
39
|
+
(send _ :its
|
40
|
+
(str ${"user" "password" "last_change" "expiry_date" "line"} ...) ...) ...) ...)
|
41
|
+
PATTERN
|
42
|
+
|
43
|
+
def on_block(node)
|
44
|
+
return unless shadow_resource_user_property?(node) do |result|
|
45
|
+
require 'pry'
|
46
|
+
# binding.pry
|
47
|
+
add_offense(node, message: message(result))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def message(result)
|
54
|
+
MSG #
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -1,3 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
require_relative 'inspecstyle/first_cop'
|
3
3
|
require_relative 'inspecstyle/deprecated_attributes'
|
4
|
+
require_relative 'inspecstyle/azure_generic_resource'
|
5
|
+
require_relative 'inspecstyle/shadow_properties'
|
6
|
+
require_relative 'inspecstyle/oracle_db_session_pass'
|
data/notes-for-development.md
CHANGED
@@ -0,0 +1,300 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'yard'
|
4
|
+
require 'rubocop'
|
5
|
+
|
6
|
+
YARD::Rake::YardocTask.new(:yard_for_generate_documentation) do |task|
|
7
|
+
task.files = ['lib/rubocop/cop/*/*.rb']
|
8
|
+
task.options = ['--no-output']
|
9
|
+
end
|
10
|
+
|
11
|
+
desc 'Generate docs of all cops departments'
|
12
|
+
task generate_cops_documentation: :yard_for_generate_documentation do
|
13
|
+
def cops_of_department(cops, department)
|
14
|
+
cops.with_department(department).sort!
|
15
|
+
end
|
16
|
+
|
17
|
+
# rubocop:disable Metrics/AbcSize
|
18
|
+
def cops_body(config, cop, description, examples_objects, pars)
|
19
|
+
content = h2(cop.cop_name)
|
20
|
+
content << required_ruby_version(cop)
|
21
|
+
content << properties(cop.new(config))
|
22
|
+
content << "#{description}\n"
|
23
|
+
content << examples(examples_objects) if examples_objects.count.positive?
|
24
|
+
content << configurations(pars)
|
25
|
+
content << references(config, cop)
|
26
|
+
content
|
27
|
+
end
|
28
|
+
# rubocop:enable Metrics/AbcSize
|
29
|
+
|
30
|
+
def examples(examples_object)
|
31
|
+
examples_object.each_with_object(h3('Examples').dup) do |example, content|
|
32
|
+
content << "\n" unless content.end_with?("\n\n")
|
33
|
+
content << h4(example.name) unless example.name == ''
|
34
|
+
content << code_example(example)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def required_ruby_version(cop)
|
39
|
+
return '' unless cop.respond_to?(:required_minimum_ruby_version)
|
40
|
+
|
41
|
+
"NOTE: Required Ruby version: #{cop.required_minimum_ruby_version}\n\n"
|
42
|
+
end
|
43
|
+
|
44
|
+
# rubocop:disable Metrics/MethodLength
|
45
|
+
def properties(cop_instance)
|
46
|
+
header = [
|
47
|
+
'Enabled by default', 'Safe', 'Supports autocorrection', 'VersionAdded',
|
48
|
+
'VersionChanged'
|
49
|
+
]
|
50
|
+
autocorrect = if cop_instance.support_autocorrect?
|
51
|
+
"Yes#{' (Unsafe)' unless cop_instance.safe_autocorrect?}"
|
52
|
+
else
|
53
|
+
'No'
|
54
|
+
end
|
55
|
+
cop_config = cop_instance.cop_config
|
56
|
+
content = [[
|
57
|
+
cop_status(cop_config.fetch('Enabled')),
|
58
|
+
cop_config.fetch('Safe', true) ? 'Yes' : 'No',
|
59
|
+
autocorrect,
|
60
|
+
cop_config.fetch('VersionAdded', '-'),
|
61
|
+
cop_config.fetch('VersionChanged', '-')
|
62
|
+
]]
|
63
|
+
to_table(header, content) + "\n"
|
64
|
+
end
|
65
|
+
# rubocop:enable Metrics/MethodLength
|
66
|
+
|
67
|
+
def h2(title)
|
68
|
+
content = +"\n"
|
69
|
+
content << "== #{title}\n"
|
70
|
+
content << "\n"
|
71
|
+
content
|
72
|
+
end
|
73
|
+
|
74
|
+
def h3(title)
|
75
|
+
content = +"\n"
|
76
|
+
content << "=== #{title}\n"
|
77
|
+
content << "\n"
|
78
|
+
content
|
79
|
+
end
|
80
|
+
|
81
|
+
def h4(title)
|
82
|
+
content = +"==== #{title}\n"
|
83
|
+
content << "\n"
|
84
|
+
content
|
85
|
+
end
|
86
|
+
|
87
|
+
def code_example(ruby_code)
|
88
|
+
content = +"[source,ruby]\n----\n"
|
89
|
+
content << ruby_code.text.gsub('@good', '# good')
|
90
|
+
.gsub('@bad', '# bad').strip
|
91
|
+
content << "\n----\n"
|
92
|
+
content
|
93
|
+
end
|
94
|
+
|
95
|
+
def configurations(pars)
|
96
|
+
return '' if pars.empty?
|
97
|
+
|
98
|
+
header = ['Name', 'Default value', 'Configurable values']
|
99
|
+
configs = pars
|
100
|
+
.each_key
|
101
|
+
.reject { |key| key.start_with?('Supported') }
|
102
|
+
.reject { |key| key.start_with?('AllowMultipleStyles') }
|
103
|
+
content = configs.map do |name|
|
104
|
+
configurable = configurable_values(pars, name)
|
105
|
+
default = format_table_value(pars[name])
|
106
|
+
[name, default, configurable]
|
107
|
+
end
|
108
|
+
|
109
|
+
h3('Configurable attributes') + to_table(header, content)
|
110
|
+
end
|
111
|
+
|
112
|
+
# rubocop:disable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
113
|
+
def configurable_values(pars, name)
|
114
|
+
case name
|
115
|
+
when /^Enforced/
|
116
|
+
supported_style_name = RuboCop::Cop::Util.to_supported_styles(name)
|
117
|
+
format_table_value(pars[supported_style_name])
|
118
|
+
when 'IndentationWidth'
|
119
|
+
'Integer'
|
120
|
+
when 'Database'
|
121
|
+
format_table_value(pars['SupportedDatabases'])
|
122
|
+
else
|
123
|
+
case pars[name]
|
124
|
+
when String
|
125
|
+
'String'
|
126
|
+
when Integer
|
127
|
+
'Integer'
|
128
|
+
when Float
|
129
|
+
'Float'
|
130
|
+
when true, false
|
131
|
+
'Boolean'
|
132
|
+
when Array
|
133
|
+
'Array'
|
134
|
+
else
|
135
|
+
''
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
# rubocop:enable Metrics/CyclomaticComplexity,Metrics/MethodLength
|
140
|
+
|
141
|
+
def to_table(header, content)
|
142
|
+
table = [
|
143
|
+
'|===',
|
144
|
+
"| #{header.join(' | ')}\n\n"
|
145
|
+
].join("\n")
|
146
|
+
marked_contents = content.map do |plain_content|
|
147
|
+
plain_content.map { |c| "| #{c}" }.join("\n")
|
148
|
+
end
|
149
|
+
table << marked_contents.join("\n\n")
|
150
|
+
table << "\n|===\n"
|
151
|
+
end
|
152
|
+
|
153
|
+
def format_table_value(val)
|
154
|
+
value =
|
155
|
+
case val
|
156
|
+
when Array
|
157
|
+
if val.empty?
|
158
|
+
'`[]`'
|
159
|
+
else
|
160
|
+
val.map { |config| format_table_value(config) }.join(', ')
|
161
|
+
end
|
162
|
+
else
|
163
|
+
wrap_backtick(val.nil? ? '<none>' : val)
|
164
|
+
end
|
165
|
+
value.gsub("#{Dir.pwd}/", '').rstrip
|
166
|
+
end
|
167
|
+
|
168
|
+
def wrap_backtick(value)
|
169
|
+
if value.is_a?(String)
|
170
|
+
# Use `+` to prevent text like `**/*.gemspec` from being bold.
|
171
|
+
value.start_with?('*') ? "`+#{value}+`" : "`#{value}`"
|
172
|
+
else
|
173
|
+
"`#{value}`"
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def references(config, cop)
|
178
|
+
cop_config = config.for_cop(cop)
|
179
|
+
urls = RuboCop::Cop::MessageAnnotator.new(
|
180
|
+
config, cop.name, cop_config, {}
|
181
|
+
).urls
|
182
|
+
return '' if urls.empty?
|
183
|
+
|
184
|
+
content = h3('References')
|
185
|
+
content << urls.map { |url| "* #{url}" }.join("\n")
|
186
|
+
content << "\n"
|
187
|
+
content
|
188
|
+
end
|
189
|
+
|
190
|
+
def print_cops_of_department(cops, department, config)
|
191
|
+
selected_cops = cops_of_department(cops, department)
|
192
|
+
content = +"= #{department}\n"
|
193
|
+
selected_cops.each do |cop|
|
194
|
+
content << print_cop_with_doc(cop, config)
|
195
|
+
end
|
196
|
+
file_name = "#{Dir.pwd}/docs/modules/ROOT/pages/cops_#{department.downcase}.adoc"
|
197
|
+
File.open(file_name, 'w') do |file|
|
198
|
+
puts "* generated #{file_name}"
|
199
|
+
file.write(content.strip + "\n")
|
200
|
+
end
|
201
|
+
end
|
202
|
+
|
203
|
+
def print_cop_with_doc(cop, config)
|
204
|
+
t = config.for_cop(cop)
|
205
|
+
non_display_keys = %w[
|
206
|
+
Description Enabled StyleGuide Reference Safe SafeAutoCorrect VersionAdded
|
207
|
+
VersionChanged
|
208
|
+
]
|
209
|
+
pars = t.reject { |k| non_display_keys.include? k }
|
210
|
+
description = 'No documentation'
|
211
|
+
examples_object = []
|
212
|
+
cop_code(cop) do |code_object|
|
213
|
+
description = code_object.docstring unless code_object.docstring.blank?
|
214
|
+
examples_object = code_object.tags('example')
|
215
|
+
end
|
216
|
+
cops_body(config, cop, description, examples_object, pars)
|
217
|
+
end
|
218
|
+
|
219
|
+
def cop_code(cop)
|
220
|
+
YARD::Registry.all(:class).detect do |code_object|
|
221
|
+
next unless RuboCop::Cop::Badge.for(code_object.to_s) == cop.badge
|
222
|
+
|
223
|
+
yield code_object
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def table_of_content_for_department(cops, department)
|
228
|
+
type_title = department[0].upcase + department[1..-1]
|
229
|
+
filename = "cops_#{department.downcase}.adoc"
|
230
|
+
content = +"=== Department xref:#{filename}[#{type_title}]\n\n"
|
231
|
+
cops_of_department(cops, department.to_sym).each do |cop|
|
232
|
+
anchor = cop.cop_name.sub('/', '').downcase
|
233
|
+
content << "* xref:#{filename}##{anchor}[#{cop.cop_name}]\n"
|
234
|
+
end
|
235
|
+
|
236
|
+
content
|
237
|
+
end
|
238
|
+
|
239
|
+
def print_table_of_contents(cops)
|
240
|
+
path = "#{Dir.pwd}/docs/modules/ROOT/pages/cops.adoc"
|
241
|
+
original = File.read(path)
|
242
|
+
content = +"// START_COP_LIST\n\n"
|
243
|
+
|
244
|
+
content << table_contents(cops)
|
245
|
+
|
246
|
+
content << "\n// END_COP_LIST"
|
247
|
+
|
248
|
+
content = original.sub(
|
249
|
+
%r{// START_COP_LIST.+// END_COP_LIST}m, content
|
250
|
+
)
|
251
|
+
File.write(path, content)
|
252
|
+
end
|
253
|
+
|
254
|
+
def table_contents(cops)
|
255
|
+
cops
|
256
|
+
.departments
|
257
|
+
.map(&:to_s)
|
258
|
+
.sort
|
259
|
+
.map { |department| table_of_content_for_department(cops, department) }
|
260
|
+
.join("\n")
|
261
|
+
end
|
262
|
+
|
263
|
+
def cop_status(status)
|
264
|
+
return 'Disabled' unless status
|
265
|
+
|
266
|
+
status == 'pending' ? 'Pending' : 'Enabled'
|
267
|
+
end
|
268
|
+
|
269
|
+
def assert_docs_synchronized
|
270
|
+
# Do not print diff and yield whether exit code was zero
|
271
|
+
sh('git diff --quiet docs') do |outcome, _|
|
272
|
+
return if outcome
|
273
|
+
|
274
|
+
# Output diff before raising error
|
275
|
+
sh('GIT_PAGER=cat git diff docs')
|
276
|
+
|
277
|
+
warn 'The docs directory is out of sync. ' \
|
278
|
+
'Run `rake generate_cops_documentation` and commit the results.'
|
279
|
+
exit!
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def main
|
284
|
+
cops = RuboCop::Cop::Cop.registry
|
285
|
+
config = RuboCop::ConfigLoader.default_configuration
|
286
|
+
|
287
|
+
YARD::Registry.load!
|
288
|
+
cops.departments.sort!.each do |department|
|
289
|
+
print_cops_of_department(cops, department, config)
|
290
|
+
end
|
291
|
+
|
292
|
+
print_table_of_contents(cops)
|
293
|
+
|
294
|
+
assert_docs_synchronized if ENV['CI'] == 'true'
|
295
|
+
ensure
|
296
|
+
RuboCop::ConfigLoader.default_configuration = nil
|
297
|
+
end
|
298
|
+
|
299
|
+
main
|
300
|
+
end
|