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