Skip to content

Commit

Permalink
Add ChefModernize/DefaultActionFromInitialize and ChefModernize/Resou…
Browse files Browse the repository at this point in the history
…rceNameFromInitialize: (#348)

Migrating HWRPs into custom resources one DSL call at a time

Signed-off-by: Tim Smith <tsmith@chef.io>
  • Loading branch information
tas50 authored Oct 24, 2019
1 parent 03e9a8d commit bc3d11a
Show file tree
Hide file tree
Showing 5 changed files with 244 additions and 0 deletions.
18 changes: 18 additions & 0 deletions config/cookstyle.yml
Original file line number Diff line number Diff line change
Expand Up @@ -805,6 +805,24 @@ ChefModernize/PowerShellGuardInterpreter:
Exclude:
- '**/metadata.rb'

ChefModernize/DefaultActionFromInitialize:
Description: The default actions can now be specified using the `default_action` helper instead of using the @action variable in the resource provider initialize method.
Enabled: true
VersionAdded: '5.10.0'
Include:
- '**/resources/*.rb'
- '**/providers/*.rb'
- '**/libraries/*.rb'

ChefModernize/ResourceNameFromInitialize:
Description: The name of a resource can be set with the "resource_name" helper instead of using the initialize method.
Enabled: true
VersionAdded: '5.10.0'
Include:
- '**/resources/*.rb'
- '**/providers/*.rb'
- '**/libraries/*.rb'

###############################
# Migrating to new patterns
###############################
Expand Down
66 changes: 66 additions & 0 deletions lib/rubocop/cop/chef/modernize/default_action_initializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#
# Copyright:: 2019, Chef Software Inc.
# Author:: Tim Smith (<tsmith@chef.io>)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module RuboCop
module Cop
module Chef
module ChefModernize
# The default actions can now be specified using the `default_action` helper instead of using the @action variable in the resource provider initialize method. In general we recommend against writing HWRPs, but if HWRPs are necessary you should utilize as much of the resource DSL as possible.
#
# @example
#
# # bad
# def initialize(*args)
# super
# @action = :create
# end
#
# # good
# default_action :create

class DefaultActionFromInitialize < Cop
include RangeHelp

MSG = 'The default action of a resource can be set with the "default_action" helper instead of using the initialize method.'.freeze

def on_def(node)
return unless node.method_name == :initialize
return if node.body.nil? # nil body is an empty initialize method

node.body.each_node do |x|
if x.assignment? && !x.node_parts.empty? && x.node_parts.first == :@action
add_offense(x, location: :expression, message: MSG, severity: :refactor)
end
end
end

def_node_search :intialize_method, '(def :initialize ... )'

def autocorrect(node)
lambda do |corrector|
# insert the new default_action call above the initialize method
initialize_node = intialize_method(processed_source.ast).first
corrector.insert_before(initialize_node.source_range, "default_action #{node.asgn_rhs.source}\n\n")

# remove the variable from the initialize method
corrector.remove(range_with_surrounding_space(range: node.loc.expression, side: :left))
end
end
end
end
end
end
end
66 changes: 66 additions & 0 deletions lib/rubocop/cop/chef/modernize/resource_name_initializer.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
#
# Copyright:: 2019, Chef Software Inc.
# Author:: Tim Smith (<tsmith@chef.io>)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
module RuboCop
module Cop
module Chef
module ChefModernize
# The resource name can now be specified using the `resource_name` helper instead of using the @resource_name variable in the resource provider initialize method. In general we recommend against writing HWRPs, but if HWRPs are necessary you should utilize as much of the resource DSL as possible.
#
# @example
#
# # bad
# def initialize(*args)
# super
# @resource_name = :foo
# end
#
# # good
# resource_name :create

class ResourceNameFromInitialize < Cop
include RangeHelp

MSG = 'The name of a resource can be set with the "resource_name" helper instead of using the initialize method.'.freeze

def on_def(node)
return unless node.method_name == :initialize
return if node.body.nil? # nil body is an empty initialize method

node.body.each_node do |x|
if x.assignment? && !x.node_parts.empty? && x.node_parts.first == :@resource_name
add_offense(x, location: :expression, message: MSG, severity: :refactor)
end
end
end

def_node_search :intialize_method, '(def :initialize ... )'

def autocorrect(node)
lambda do |corrector|
# insert the new resource_name call above the initialize method
initialize_node = intialize_method(processed_source.ast).first
corrector.insert_before(initialize_node.source_range, "resource_name #{node.asgn_rhs.source}\n\n")

# remove the variable from the initialize method
corrector.remove(range_with_surrounding_space(range: node.loc.expression, side: :left))
end
end
end
end
end
end
end
47 changes: 47 additions & 0 deletions spec/rubocop/cop/chef/modernize/default_action_initializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# Copyright:: 2019, Chef Software, Inc.
# Author:: Tim Smith (<tsmith@chef.io>)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'spec_helper'

describe RuboCop::Cop::Chef::ChefModernize::DefaultActionFromInitialize, :config do
subject(:cop) { described_class.new(config) }

it 'registers an offense with a HWRP specifies the default_action in the initializer' do
expect_offense(<<~RUBY)
def initialize(*args)
super
@action = :create
^^^^^^^^^^^^^^^^^ The default action of a resource can be set with the "default_action" helper instead of using the initialize method.
end
RUBY

expect_correction(<<~RUBY)
default_action :create
def initialize(*args)
super
end
RUBY
end

it 'does not register an offense with an empty initialize method' do
expect_no_offenses(<<~RUBY)
def initialize(*args)
end
RUBY
end
end
47 changes: 47 additions & 0 deletions spec/rubocop/cop/chef/modernize/resource_name_initializer_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
#
# Copyright:: 2019, Chef Software, Inc.
# Author:: Tim Smith (<tsmith@chef.io>)
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#

require 'spec_helper'

describe RuboCop::Cop::Chef::ChefModernize::ResourceNameFromInitialize, :config do
subject(:cop) { described_class.new(config) }

it 'registers an offense with a HWRP specifies the resource_name in the initializer' do
expect_offense(<<~RUBY)
def initialize(*args)
super
@resource_name = :foo
^^^^^^^^^^^^^^^^^^^^^ The name of a resource can be set with the "resource_name" helper instead of using the initialize method.
end
RUBY

expect_correction(<<~RUBY)
resource_name :foo
def initialize(*args)
super
end
RUBY
end

it 'does not register an offense with an empty initialize method' do
expect_no_offenses(<<~RUBY)
def initialize(*args)
end
RUBY
end
end

0 comments on commit bc3d11a

Please sign in to comment.