From 7c580556319658daae5a77b252e83bfc54305e64 Mon Sep 17 00:00:00 2001 From: Yorick Peterse Date: Thu, 13 Dec 2018 15:46:01 +0100 Subject: Added Cop for injecting EE modules This Cop enforces the rule that injecting EE modules (using prepend, include, or extend) is done by placing the injection on the last line of a file, instead of somewhere in the middle. By placing these lines at the very end, merge conflicts will not happen. --- rubocop/cop/inject_enterprise_edition_module.rb | 47 +++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 rubocop/cop/inject_enterprise_edition_module.rb (limited to 'rubocop/cop') diff --git a/rubocop/cop/inject_enterprise_edition_module.rb b/rubocop/cop/inject_enterprise_edition_module.rb new file mode 100644 index 00000000000..c8b8aca51ab --- /dev/null +++ b/rubocop/cop/inject_enterprise_edition_module.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + # Cop that blacklists the injecting of EE specific modules anywhere but on + # the last line of a file. Injecting a module in the middle of a file will + # cause merge conflicts, while placing it on the last line will not. + class InjectEnterpriseEditionModule < RuboCop::Cop::Cop + MSG = 'Injecting EE modules must be done on the last line of this file' \ + ', outside of any class or module definitions' + + METHODS = Set.new(%i[include extend prepend]).freeze + + def_node_matcher :ee_const?, <<~PATTERN + (const (const _ :EE) _) + PATTERN + + def on_send(node) + return unless METHODS.include?(node.children[1]) + return unless ee_const?(node.children[2]) + + line = node.location.line + buffer = node.location.expression.source_buffer + last_line = buffer.last_line + + # Parser treats the final newline (if present) as a separate line, + # meaning that a simple `line < last_line` would yield true even though + # the expression is the last line _of code_. + last_line -= 1 if buffer.source.end_with?("\n") + + add_offense(node) if line < last_line + end + + # Automatically correcting these offenses is not always possible, as + # sometimes code needs to be refactored to make this work. As such, we + # only allow developers to easily blacklist existing offenses. + def autocorrect(node) + lambda do |corrector| + corrector.insert_after( + node.source_range, + " # rubocop: disable #{cop_name}" + ) + end + end + end + end +end -- cgit v1.2.3