2021-05-25 00:58:14 +01:00
# frozen_string_literal: true
module RuboCop
module Cop
module Lint
2021-06-02 22:31:32 +01:00
class ModuleEnforceNotes < Base
2021-05-25 00:58:14 +01:00
2022-12-30 12:29:14 -06:00
NO_NOTES_MSG = 'Module is missing the Notes section which must include Stability, Reliability and SideEffects] - https://docs.metasploit.com/docs/development/developing-modules/module-metadata/definition-of-module-reliability-side-effects-and-stability.html'
MISSING_KEY_MSG = 'Module is missing %s from the Notes section - https://docs.metasploit.com/docs/development/developing-modules/module-metadata/definition-of-module-reliability-side-effects-and-stability.html'
2021-06-10 02:56:24 +01:00
REQUIRED_KEYS = %w[ Stability Reliability SideEffects ]
2021-05-25 00:58:14 +01:00
def_node_matcher :find_update_info_node , << ~ PATTERN
( def :initialize _args ( begin ( super $ ( send nil ? { :update_info :merge_info } ( lvar :info ) ( hash ... ) ) ) ... ) )
PATTERN
def_node_matcher :find_nested_update_info_node , << ~ PATTERN
( def :initialize _args ( super $ ( send nil ? { :update_info :merge_info } ( lvar :info ) ( hash ... ) ) ... ) )
PATTERN
def on_def ( node )
update_info_node = find_update_info_node ( node ) || find_nested_update_info_node ( node )
return if update_info_node . nil?
hash = update_info_node . arguments . find { | argument | hash_arg? ( argument ) }
notes_present = false
last_key = nil
notes = nil
hash . each_pair do | key , value |
if key . value == 'Notes'
notes_present = true
notes = value
end
last_key = key
end
if notes_present
2021-06-10 02:56:24 +01:00
check_for_required_keys ( notes )
2021-05-25 00:58:14 +01:00
else
add_offense ( last_key || hash , message : NO_NOTES_MSG )
end
end
private
2021-06-10 02:56:24 +01:00
def check_for_required_keys ( notes )
2021-05-25 00:58:14 +01:00
last_key = nil
2021-06-02 22:31:32 +01:00
keys_present = [ ]
2021-05-25 00:58:14 +01:00
notes . each_pair do | key , _value |
2021-06-10 02:56:24 +01:00
if REQUIRED_KEYS . include? key . value
2021-06-02 22:31:32 +01:00
keys_present << key . value
2021-05-25 00:58:14 +01:00
end
last_key = key
end
2021-06-10 02:56:24 +01:00
missing_keys = REQUIRED_KEYS - keys_present
2021-06-02 22:31:32 +01:00
unless missing_keys . empty?
if missing_keys . length == 1
msg = missing_keys [ 0 ]
else
msg = missing_keys [ 0 ... - 1 ] . join ( ', ' ) + ' and ' + missing_keys [ - 1 ]
end
add_offense ( last_key || notes , message : MISSING_KEY_MSG % msg )
2021-05-25 00:58:14 +01:00
end
end
def hash_arg? ( node )
node . type == :hash
end
end
end
end
end