From 1f7cf9416f9de7d62ea4fdcf39d05e419b71557d Mon Sep 17 00:00:00 2001 From: nicolasguridi Date: Fri, 21 Apr 2023 19:04:17 -0400 Subject: [PATCH] feat(cop): add Platanus/EnvInModule cop --- config/default.yml | 8 +++ lib/rubocop/cop/platanus/env_in_module.rb | 63 +++++++++++++++++++ lib/rubocop/cop/platanus_cops.rb | 1 + .../cop/platanus/env_in_module_spec.rb | 41 ++++++++++++ 4 files changed, 113 insertions(+) create mode 100644 lib/rubocop/cop/platanus/env_in_module.rb create mode 100644 spec/rubocop/cop/platanus/env_in_module_spec.rb diff --git a/config/default.yml b/config/default.yml index aee22b8..9c89bd3 100644 --- a/config/default.yml +++ b/config/default.yml @@ -57,3 +57,11 @@ Platanus/SingularSerializer: Include: - "app/serializers/**/*.rb" VersionAdded: "<>" + +Platanus/EnvInModule: + Description: 'Prefer retrieving environment variables in a dedicated module.' + Enabled: true + Include: + - 'app/**/*.rb' + VersionAdded: '<>' + diff --git a/lib/rubocop/cop/platanus/env_in_module.rb b/lib/rubocop/cop/platanus/env_in_module.rb new file mode 100644 index 0000000..1f8a831 --- /dev/null +++ b/lib/rubocop/cop/platanus/env_in_module.rb @@ -0,0 +1,63 @@ +# frozen_string_literal: true + +module RuboCop + module Cop + module Platanus + # Environment variables should not be retrieved directly. Prefer retrieving them in a + # dedicated module. This centralizes their location, enhances their functionality and makes + # them easier to stub. + # + # @example + # + # # bad + # class Foo + # BAR = ENV.fetch('BAR') + # + # def foo_method + # BAR + # end + # end + # + # # bad + # class Foo + # BAR = ENV['BAR'] + # + # def foo_method + # BAR + # end + # end + # + # # good + # module EnvironmentVariables + # extend self + # + # BAR = ENV.fetch('BAR') + # + # def bar + # BAR + # end + # end + # + # class Foo + # def foo_method + # EnvironmentVariables.bar + # end + # end + # + class EnvInModule < Base + MSG = 'Use dedicated module for environment variables retrieval instead.' + + # @!method env_retrieve?(node) + def_node_matcher :env_retrieve?, <<~PATTERN + (send (const nil? :ENV) { :fetch | :[] } ...) + PATTERN + + def on_send(node) + return unless env_retrieve?(node) + + add_offense(node) + end + end + end + end +end diff --git a/lib/rubocop/cop/platanus_cops.rb b/lib/rubocop/cop/platanus_cops.rb index 66238f8..acc19cd 100644 --- a/lib/rubocop/cop/platanus_cops.rb +++ b/lib/rubocop/cop/platanus_cops.rb @@ -8,3 +8,4 @@ require_relative 'platanus/no_where_aasm_state' require_relative 'platanus/pundit_in_application_controller' require_relative 'platanus/singular_serializer' +require_relative 'platanus/env_in_module' diff --git a/spec/rubocop/cop/platanus/env_in_module_spec.rb b/spec/rubocop/cop/platanus/env_in_module_spec.rb new file mode 100644 index 0000000..087d15d --- /dev/null +++ b/spec/rubocop/cop/platanus/env_in_module_spec.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +RSpec.describe RuboCop::Cop::Platanus::EnvInModule, :config do + let(:config) { RuboCop::Config.new } + + it 'registers an offense when using `ENV.fetch`' do + expect_offense <<~RUBY + class Foo + BAR = ENV.fetch('BAR') + ^^^^^^^^^^^^^^^^ Use dedicated module for environment variables retrieval instead. + + def foo_method + BAR + end + end + RUBY + end + + it 'registers an offense when using `ENV[]`' do + expect_offense <<~RUBY + class Foo + BAR = ENV['BAR'] + ^^^^^^^^^^ Use dedicated module for environment variables retrieval instead. + + def foo_method + BAR + end + end + RUBY + end + + it 'does not register an offense when not using `ENV.fetch` or `ENV`' do + expect_no_offenses <<~RUBY + class Foo + def foo_method + EnviromentVariables.bar + end + end + RUBY + end +end