Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix ensure_first_param fix method to retrieve the full value of the ensure parameter #673

Merged
merged 5 commits into from
Mar 27, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 74 additions & 0 deletions lib/puppet-lint/lexer/token.rb
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,80 @@ def to_manifest
@value
end
end

# Public: Search from this token to find the next token of a given type.
#
# type - A Symbol type of the token to find, or an Array of Symbols.
# opts - An optional Hash
# :value - A token value to search for in addition to type
# :skip_blocks - A Boolean to specify whether { } blocks should be
# skipped over (defaults to true).
#
# Returns a PuppetLint::Lexer::Token object if a matching token could be
# found, otherwise nil.
def next_token_of(type, opts = {})
find_token_of(:next, type, opts)
end

# Public: Search from this token to find the previous token of a given type.
#
# type - A Symbol type of the token to find, or an Array of Symbols.
# opts - An optional Hash
# :value - A token value to search for in addition to type
# :skip_blocks - A Boolean to specify whether { } blocks should be
# skipped over (defaults to true).
#
# Returns a PuppetLint::Lexer::Token object if a matching token could be
# found, otherwise nil.
def prev_token_of(type, opts = {})
find_token_of(:prev, type, opts)
end

# Internal: Search from this token to find the next token of a given type
# in a given direction.
#
# direction - A Symbol direction to search (:next or :prev).
# type - A Symbol type of the token to find, or an Array of Symbols.
# opts - An optional Hash
# :value - A token value to search for in addition to type
# :skip_blocks - A Boolean to specify whether { } blocks should be
# skipped over (defaults to true).
#
# Returns a PuppetLint::Lexer::Token object if a matching token could be
# found, otherwise nil.
def find_token_of(direction, type, opts = {})
return nil unless [:next, :prev].include?(direction)

opts[:skip_blocks] ||= true
to_find = Array[*type]

token_iter = self.send("#{direction}_token".to_sym)
while !token_iter.nil?
if to_find.include? token_iter.type
if opts[:value]
return token_iter if token_iter.value == opts[:value]
else
return token_iter
end
end

opening_token = direction == :next ? "L" : "R"
closing_token = direction == :next ? "R" : "L"

if opts[:skip_blocks]
case token_iter.type
when "#{opening_token}BRACE".to_sym
token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}BRACE".to_sym, opts])
when "#{opening_token}BRACK".to_sym
token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}BRACK".to_sym, opts])
when "#{opening_token}PAREN".to_sym
token_iter = token_iter.send("#{direction}_token_of".to_sym, ["#{closing_token}PAREN".to_sym, opts])
end
end
token_iter = token_iter.send("#{direction}_token".to_sym)
end
nil
end
end
end
end
45 changes: 12 additions & 33 deletions lib/puppet-lint/plugins/check_resources.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,43 +47,22 @@ def check
end
end
end

def fix(problem)
# We find the first and ensure paramss boundaries
first_param_name_token = nil
first_param_name_idx = nil
first_param_comma_token = nil
first_param_comma_idx = nil
ensure_param_name_token = nil
ensure_param_name_idx = nil
ensure_param_comma_token = nil
ensure_param_comma_idx = nil
tokens[(problem[:resource][:start])..(problem[:resource][:end])].each_with_index do |token, token_idx|
if first_param_name_token.nil?
if token.type == :NAME
first_param_name_token = token
first_param_name_idx = problem[:resource][:start] + token_idx
end
elsif first_param_comma_token.nil?
if token.type == :COMMA
first_param_comma_token = token
first_param_comma_idx = problem[:resource][:start] + token_idx
end
elsif ensure_param_name_token.nil?
if token.type == :NAME and token.value == 'ensure'
ensure_param_name_token = token
ensure_param_name_idx = problem[:resource][:start] + token_idx
end
elsif ensure_param_comma_token.nil?
if token.type == :COMMA or token.type == :SEMIC
ensure_param_comma_token = token
ensure_param_comma_idx = problem[:resource][:start] + token_idx
break
end
end
end
first_param_name_token = tokens[problem[:resource][:start]].next_token_of(:NAME)
first_param_comma_token = first_param_name_token.next_token_of(:COMMA)
ensure_param_name_token = first_param_comma_token.next_token_of(:NAME, :value => 'ensure')
ensure_param_comma_token = ensure_param_name_token.next_token_of([:COMMA, :SEMIC])

if first_param_name_token.nil? or first_param_comma_token.nil? or ensure_param_name_token.nil? or ensure_param_comma_token.nil?
raise PuppetLint::NoFix
end

first_param_name_idx = tokens.index(first_param_name_token)
first_param_comma_idx = tokens.index(first_param_comma_token)
ensure_param_name_idx = tokens.index(ensure_param_name_token)
ensure_param_comma_idx = tokens.index(ensure_param_comma_token)

# Flip params
prev_token = first_param_name_token.prev_token
first_param_name_token.prev_token = ensure_param_name_token.prev_token
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,5 +159,45 @@ class {'thang':
expect(problems).to have(0).problems
end
end

context 'ensure is a selector' do
let(:code) { "
file { 'foo':
mode => '0640',
ensure => $::operatingsystem ? {
'redhat' => absent,
default => $::phase_of_the_moon ? {
'full' => absent,
default => present,
},
},
}
" }

let(:fixed) { "
file { 'foo':
ensure => $::operatingsystem ? {
'redhat' => absent,
default => $::phase_of_the_moon ? {
'full' => absent,
default => present,
},
},
mode => '0640',
}
" }

it 'should detect a problem' do
expect(problems).to have(1).problem
end

it 'should fix the problem' do
expect(problems).to contain_fixed(msg).on_line(4).in_column(11)
end

it 'should move the whole ensure parameter to the top' do
expect(manifest).to eq(fixed)
end
end
end
end