class RuboCop::Cop::SketchupSuggestions::Compatibility
It's easy to lose track of what API feature was added in what version or SketchUp
. You can configure your target SketchUp
version and be notified if you use features introduced in newer versions.
@example Add this to your .rubocop.yml
AllCops: SketchUp: TargetSketchUpVersion: 2016 M1
Constants
- MSG
Public Instance Methods
on_const(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 49 def on_const(node) if node.parent && module_definition?(node.parent) # This catches definition of classes and modules. namespace = Namespace.new(node.parent_module_name) return unless namespace.top_level? end feature_name = node.const_name [:class, :module, :constant].each { |type| check_feature(node, type, feature_name) } end
on_def(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 25 def on_def(node) return unless observer_method?(node) feature_name = "##{node.method_name}" check_feature(node, :method, feature_name) end
on_send(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 32 def on_send(node) feature_name = '' if module_method?(node) feature_name = "#{node.receiver.const_name}.#{node.method_name}" else # Instance methods are harder. It's difficult to infer the type of # the receiver. If we only check the method name in isolation we # will get too many false positives with method names matching # methods in Ruby itself and other older features. # We try to match names that are unlikely to cause much noise. return unless checkable_instance_method?(node) feature_name = "##{node.method_name}" end check_feature(node, :method, feature_name) end
Private Instance Methods
check_feature(node, type, feature_name)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 64 def check_feature(node, type, feature_name) return unless sketchup_target_version? full_feature_name = feature_name FEATURES.each { |feature_set| version = feature_set[:version] feature_version = SketchUp::SketchUpVersion.new(version) next unless feature_version > sketchup_target_version objects = feature_set[:types][type] || [] if type == :method && instance_method?(feature_name) # Instance methods are simply matching the method name since it's # very difficult to determine the type of the receiver. full_feature_name = objects.find { |object| object.end_with?(feature_name) } next unless full_feature_name else next unless objects.include?(feature_name) end report(node, full_feature_name, feature_version, type) } end
checkable_instance_method?(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 117 def checkable_instance_method?(node) INSTANCE_METHODS.include?(node.method_name) end
find_node_location(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 96 def find_node_location(node) # Highlight the most pertinent piece of the expression. if node.const_type? :expression elsif node.send_type? :selector elsif node.def_type? :name else :expression end end
instance_method?(feature_name)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 113 def instance_method?(feature_name) feature_name.start_with?('#') end
module_method?(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 109 def module_method?(node) node.receiver&.const_type? end
observer_method?(node)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 121 def observer_method?(node) OBSERVER_METHODS.include?(node.method_name) end
report(node, feature_name, feature_version, feature_type)
click to toggle source
# File lib/rubocop/sketchup/cop/suggestions/compatibility.rb, line 88 def report(node, feature_name, feature_version, feature_type) message = "The #{feature_type} `#{feature_name}` was added in "\ "#{feature_version} which is incompatible with target "\ "#{sketchup_target_version}." location = find_node_location(node) add_offense(node, location: location, message: message) end