puppet-lint 0.4.0.pre1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.travis.yml +3 -4
- data/Gemfile +2 -5
- data/README.md +2 -149
- data/Rakefile +0 -5
- data/lib/puppet-lint.rb +74 -20
- data/lib/puppet-lint/bin.rb +20 -85
- data/lib/puppet-lint/checkplugin.rb +158 -12
- data/lib/puppet-lint/checks.rb +39 -222
- data/lib/puppet-lint/configuration.rb +12 -31
- data/lib/puppet-lint/data.rb +329 -0
- data/lib/puppet-lint/lexer.rb +37 -30
- data/lib/puppet-lint/lexer/token.rb +14 -16
- data/lib/puppet-lint/monkeypatches/string_prepend.rb +6 -0
- data/lib/puppet-lint/optparser.rb +105 -0
- data/lib/puppet-lint/plugins.rb +28 -9
- data/lib/puppet-lint/plugins/check_classes.rb +162 -238
- data/lib/puppet-lint/plugins/check_comments.rb +40 -25
- data/lib/puppet-lint/plugins/check_conditionals.rb +16 -20
- data/lib/puppet-lint/plugins/check_documentation.rb +14 -20
- data/lib/puppet-lint/plugins/check_nodes.rb +23 -0
- data/lib/puppet-lint/plugins/check_resources.rb +127 -141
- data/lib/puppet-lint/plugins/check_strings.rb +133 -107
- data/lib/puppet-lint/plugins/check_variables.rb +11 -11
- data/lib/puppet-lint/plugins/check_whitespace.rb +86 -92
- data/lib/puppet-lint/tasks/puppet-lint.rb +17 -1
- data/lib/puppet-lint/version.rb +1 -1
- data/puppet-lint.gemspec +4 -2
- data/spec/fixtures/test/manifests/ignore.pp +1 -0
- data/spec/fixtures/test/manifests/ignore_reason.pp +1 -0
- data/spec/puppet-lint/bin_spec.rb +104 -84
- data/spec/puppet-lint/configuration_spec.rb +19 -19
- data/spec/puppet-lint/ignore_overrides_spec.rb +97 -0
- data/spec/puppet-lint/lexer/token_spec.rb +9 -9
- data/spec/puppet-lint/lexer_spec.rb +352 -325
- data/spec/puppet-lint/plugins/check_classes/autoloader_layout_spec.rb +77 -23
- data/spec/puppet-lint/plugins/check_classes/class_inherits_from_params_class_spec.rb +14 -12
- data/spec/puppet-lint/plugins/check_classes/inherits_across_namespaces_spec.rb +18 -14
- data/spec/puppet-lint/plugins/check_classes/names_containing_dash_spec.rb +30 -30
- data/spec/puppet-lint/plugins/check_classes/nested_classes_or_defines_spec.rb +31 -26
- data/spec/puppet-lint/plugins/check_classes/parameter_order_spec.rb +34 -28
- data/spec/puppet-lint/plugins/check_classes/right_to_left_relationship_spec.rb +14 -12
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +74 -30
- data/spec/puppet-lint/plugins/check_comments/slash_comments_spec.rb +27 -20
- data/spec/puppet-lint/plugins/check_comments/star_comments_spec.rb +78 -13
- data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +17 -12
- data/spec/puppet-lint/plugins/check_conditionals/selector_inside_resource_spec.rb +13 -10
- data/spec/puppet-lint/plugins/check_documentation/documentation_spec.rb +21 -16
- data/spec/puppet-lint/plugins/check_nodes/unquoted_node_name_spec.rb +69 -0
- data/spec/puppet-lint/plugins/check_resources/duplicate_params_spec.rb +42 -38
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +22 -10
- data/spec/puppet-lint/plugins/check_resources/ensure_not_symlink_target_spec.rb +81 -18
- data/spec/puppet-lint/plugins/check_resources/file_mode_spec.rb +69 -112
- data/spec/puppet-lint/plugins/check_resources/unquoted_file_mode_spec.rb +27 -20
- data/spec/puppet-lint/plugins/check_resources/unquoted_resource_title_spec.rb +177 -171
- data/spec/puppet-lint/plugins/check_strings/double_quoted_strings_spec.rb +165 -88
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +97 -22
- data/spec/puppet-lint/plugins/check_strings/puppet_url_without_modules_spec.rb +25 -0
- data/spec/puppet-lint/plugins/check_strings/quoted_booleans_spec.rb +97 -111
- data/spec/puppet-lint/plugins/check_strings/single_quote_string_with_variables_spec.rb +10 -9
- data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +53 -53
- data/spec/puppet-lint/plugins/check_variables/variable_contains_dash_spec.rb +26 -14
- data/spec/puppet-lint/plugins/check_whitespace/2sp_soft_tabs_spec.rb +10 -9
- data/spec/puppet-lint/plugins/check_whitespace/80chars_spec.rb +31 -15
- data/spec/puppet-lint/plugins/check_whitespace/arrow_alignment_spec.rb +340 -322
- data/spec/puppet-lint/plugins/check_whitespace/hard_tabs_spec.rb +30 -23
- data/spec/puppet-lint/plugins/check_whitespace/trailing_whitespace_spec.rb +42 -41
- data/spec/puppet-lint_spec.rb +3 -3
- data/spec/spec_helper.rb +109 -116
- metadata +109 -50
- data/spec/puppet-lint/plugins/check_classes/class_parameter_defaults_spec.rb +0 -60
@@ -1,35 +1,37 @@
|
|
1
1
|
class PuppetLint
|
2
2
|
class Lexer
|
3
|
+
# Public: Stores a fragment of the manifest and the information about its
|
4
|
+
# location in the manifest.
|
3
5
|
class Token
|
4
|
-
#
|
6
|
+
# Public: Returns the Symbol type of the Token.
|
5
7
|
attr_accessor :type
|
6
8
|
|
7
|
-
#
|
9
|
+
# Public: Returns the String value of the Token.
|
8
10
|
attr_accessor :value
|
9
11
|
|
10
|
-
#
|
12
|
+
# Public: Returns the Integer line number of the manifest text where
|
11
13
|
# the Token can be found.
|
12
14
|
attr_reader :line
|
13
15
|
|
14
|
-
#
|
16
|
+
# Public: Returns the Integer column number of the line of the manifest
|
15
17
|
# text where the Token can be found.
|
16
18
|
attr_reader :column
|
17
19
|
|
18
|
-
#
|
20
|
+
# Public: Gets/sets the next token in the manifest.
|
19
21
|
attr_accessor :next_token
|
20
22
|
|
21
|
-
#
|
23
|
+
# Public: Gets/sets the previous token in the manifest.
|
22
24
|
attr_accessor :prev_token
|
23
25
|
|
24
|
-
#
|
26
|
+
# Public: Gets/sets the next code token (skips whitespace, comments,
|
25
27
|
# etc) in the manifest.
|
26
28
|
attr_accessor :next_code_token
|
27
29
|
|
28
|
-
#
|
30
|
+
# Public: Gets/sets the previous code tokne (skips whitespace,
|
29
31
|
# comments, etc) in the manifest.
|
30
32
|
attr_accessor :prev_code_token
|
31
33
|
|
32
|
-
#
|
34
|
+
# Public: Initialise a new Token object.
|
33
35
|
#
|
34
36
|
# type - An upper case Symbol describing the type of Token.
|
35
37
|
# value - The String value of the Token.
|
@@ -50,7 +52,7 @@ class PuppetLint
|
|
50
52
|
@prev_code_token = nil
|
51
53
|
end
|
52
54
|
|
53
|
-
#
|
55
|
+
# Public: Produce a human friendly description of the Token when
|
54
56
|
# inspected.
|
55
57
|
#
|
56
58
|
# Returns a String describing the Token.
|
@@ -58,7 +60,7 @@ class PuppetLint
|
|
58
60
|
"<Token #{@type.inspect} (#{@value}) @#{@line}:#{@column}>"
|
59
61
|
end
|
60
62
|
|
61
|
-
#
|
63
|
+
# Public: Produce a Puppet DSL representation of a Token.
|
62
64
|
#
|
63
65
|
# Returns a Puppet DSL String.
|
64
66
|
def to_manifest
|
@@ -82,11 +84,7 @@ class PuppetLint
|
|
82
84
|
when :NEWLINE
|
83
85
|
"\n"
|
84
86
|
when :COMMENT
|
85
|
-
|
86
|
-
"##{@value}"
|
87
|
-
else
|
88
|
-
"# #{@value}"
|
89
|
-
end
|
87
|
+
"##{@value}"
|
90
88
|
when :REGEX
|
91
89
|
"/#{@value}/"
|
92
90
|
else
|
@@ -1,5 +1,11 @@
|
|
1
1
|
unless String.respond_to?('prepend')
|
2
|
+
# Internal: Monkey patching String.
|
2
3
|
class String
|
4
|
+
# Internal: Prepends a String to self.
|
5
|
+
#
|
6
|
+
# lead - The String to prepend self with.
|
7
|
+
#
|
8
|
+
# Returns a String which is lead and self concatenated.
|
3
9
|
def prepend(lead)
|
4
10
|
self.replace "#{lead}#{self}"
|
5
11
|
end
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
# Public: Contains the puppet-lint option parser so that it can be used easily
|
4
|
+
# in multiple places.
|
5
|
+
class PuppetLint::OptParser
|
6
|
+
HELP_TEXT = <<-EOF
|
7
|
+
puppet-lint
|
8
|
+
|
9
|
+
Basic Command Line Usage:
|
10
|
+
puppet-lint [OPTIONS] PATH
|
11
|
+
|
12
|
+
PATH The path to the Puppet manifest.
|
13
|
+
|
14
|
+
Option:
|
15
|
+
EOF
|
16
|
+
|
17
|
+
# Public: Initialise a new puppet-lint OptionParser.
|
18
|
+
#
|
19
|
+
# Returns an OptionParser object.
|
20
|
+
def self.build
|
21
|
+
OptionParser.new do |opts|
|
22
|
+
opts.banner = HELP_TEXT
|
23
|
+
|
24
|
+
opts.on('--version', 'Display the current version.') do
|
25
|
+
PuppetLint.configuration.display_version = true
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on('-c', '--config FILE', 'Load puppet-lint options from file.') do |file|
|
29
|
+
opts.load(file)
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on('--with-context', 'Show where in the manifest the problem is.') do
|
33
|
+
PuppetLint.configuration.with_context = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on('--with-filename', 'Display the filename before the warning.') do
|
37
|
+
PuppetLint.configuration.with_filename = true
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on('--fail-on-warnings', 'Return a non-zero exit status for warnings') do
|
41
|
+
PuppetLint.configuration.fail_on_warnings = true
|
42
|
+
end
|
43
|
+
|
44
|
+
opts.on('--error-level LEVEL', [:all, :warning, :error],
|
45
|
+
'The level of error to return (warning, error or all).') do |el|
|
46
|
+
PuppetLint.configuration.error_level = el
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on('--show-ignored', 'Show problems that have been ignored by control comments') do
|
50
|
+
PuppetLint.configuration.show_ignored = true
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on('--relative', 'Compare module layout relative to the module root') do
|
54
|
+
PuppetLint.configuration.relative = true
|
55
|
+
end
|
56
|
+
|
57
|
+
opts.on('-l', '--load FILE', 'Load a file containing custom puppet-lint checks.') do |f|
|
58
|
+
load f
|
59
|
+
end
|
60
|
+
|
61
|
+
opts.on('-f', '--fix', 'Attempt to automatically fix errors') do
|
62
|
+
PuppetLint.configuration.fix = true
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.on('--log-format FORMAT',
|
66
|
+
'Change the log format.', 'Overrides --with-filename.',
|
67
|
+
'The following placeholders can be used:',
|
68
|
+
'%{filename} - Filename without path.',
|
69
|
+
'%{path} - Path as provided to puppet-lint.',
|
70
|
+
'%{fullpath} - Expanded path to the file.',
|
71
|
+
'%{line} - Line number.',
|
72
|
+
'%{column} - Column number.',
|
73
|
+
'%{kind} - The kind of message (warning, error).',
|
74
|
+
'%{KIND} - Uppercase version of %{kind}.',
|
75
|
+
'%{check} - The name of the check.',
|
76
|
+
'%{message} - The message.'
|
77
|
+
) do |format|
|
78
|
+
if format.include?('%{linenumber}')
|
79
|
+
$stderr.puts "DEPRECATION: Please use %{line} instead of %{linenumber}"
|
80
|
+
end
|
81
|
+
PuppetLint.configuration.log_format = format
|
82
|
+
end
|
83
|
+
|
84
|
+
opts.separator ''
|
85
|
+
opts.separator ' Checks:'
|
86
|
+
|
87
|
+
opts.on('--only-checks CHECKS', 'A comma separated list of checks that should be run') do |checks|
|
88
|
+
enable_checks = checks.split(',').map(&:to_sym)
|
89
|
+
(PuppetLint.configuration.checks - enable_checks).each do |check|
|
90
|
+
PuppetLint.configuration.send("disable_#{check}")
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
PuppetLint.configuration.checks.each do |check|
|
95
|
+
opts.on("--no-#{check}-check", "Skip the #{check} check.") do
|
96
|
+
PuppetLint.configuration.send("disable_#{check}")
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
opts.load('/etc/puppet-lint.rc')
|
101
|
+
opts.load(File.expand_path('~/.puppet-lint.rc')) if ENV['HOME']
|
102
|
+
opts.load('.puppet-lint.rc')
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
data/lib/puppet-lint/plugins.rb
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
require 'pathname'
|
2
2
|
|
3
3
|
class PuppetLint
|
4
|
+
# Public: Various methods that implement puppet-lint's plugin system
|
5
|
+
#
|
6
|
+
# Examples
|
7
|
+
#
|
8
|
+
# PuppetLint::Plugins.load_spec_helper
|
4
9
|
class Plugins
|
5
|
-
#
|
10
|
+
# Internal: Find any gems containing puppet-lint plugins and load them.
|
6
11
|
#
|
7
12
|
# Returns nothing.
|
8
13
|
def self.load_from_gems
|
@@ -14,6 +19,14 @@ class PuppetLint
|
|
14
19
|
end
|
15
20
|
end
|
16
21
|
end
|
22
|
+
|
23
|
+
# Public: Load the puppet-lint spec_helper.rb
|
24
|
+
#
|
25
|
+
# Returns nothings.
|
26
|
+
def self.load_spec_helper
|
27
|
+
gemspec = gemspecs.select { |spec| spec.name == 'puppet-lint' }.first
|
28
|
+
load Pathname.new(gemspec.full_gem_path) + 'spec/spec_helper.rb'
|
29
|
+
end
|
17
30
|
private
|
18
31
|
# Internal: Check if RubyGems is loaded and available.
|
19
32
|
#
|
@@ -22,19 +35,24 @@ class PuppetLint
|
|
22
35
|
defined? ::Gem
|
23
36
|
end
|
24
37
|
|
38
|
+
# Internal: Retrieve a list of avaliable gemspecs.
|
39
|
+
#
|
40
|
+
# Returns an Array of Gem::Specification objects.
|
41
|
+
def self.gemspecs
|
42
|
+
@gemspecs ||= if Gem::Specification.respond_to?(:latest_specs)
|
43
|
+
Gem::Specification.latest_specs
|
44
|
+
else
|
45
|
+
Gem.searcher.init_gemspecs
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
25
49
|
# Internal: Retrieve a list of available gem paths from RubyGems.
|
26
50
|
#
|
27
51
|
# Returns an Array of Pathname objects.
|
28
52
|
def self.gem_directories
|
29
53
|
if has_rubygems?
|
30
|
-
|
31
|
-
|
32
|
-
Pathname.new(spec.full_gem_path) + 'lib'
|
33
|
-
end
|
34
|
-
else
|
35
|
-
Gem.searcher.init_gemspecs.map do |spec|
|
36
|
-
Pathname.new(spec.full_gem_path) + 'lib'
|
37
|
-
end
|
54
|
+
gemspecs.reject { |spec| spec.name == 'puppet-lint' }.map do |spec|
|
55
|
+
Pathname.new(spec.full_gem_path) + 'lib'
|
38
56
|
end
|
39
57
|
else
|
40
58
|
[]
|
@@ -51,5 +69,6 @@ require 'puppet-lint/plugins/check_strings'
|
|
51
69
|
require 'puppet-lint/plugins/check_variables'
|
52
70
|
require 'puppet-lint/plugins/check_whitespace'
|
53
71
|
require 'puppet-lint/plugins/check_resources'
|
72
|
+
require 'puppet-lint/plugins/check_nodes'
|
54
73
|
|
55
74
|
PuppetLint::Plugins.load_from_gems
|
@@ -1,200 +1,115 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
# Returns nothing.
|
6
|
-
check 'right_to_left_relationship' do
|
1
|
+
# Public: Test the manifest tokens for any right-to-left (<-) chaining
|
2
|
+
# operators and record a warning for each instance found.
|
3
|
+
PuppetLint.new_check(:right_to_left_relationship) do
|
4
|
+
def check
|
7
5
|
tokens.select { |r| r.type == :OUT_EDGE }.each do |token|
|
8
6
|
notify :warning, {
|
9
|
-
:message
|
10
|
-
:
|
11
|
-
:column
|
7
|
+
:message => 'right-to-left (<-) relationship',
|
8
|
+
:line => token.line,
|
9
|
+
:column => token.column,
|
12
10
|
}
|
13
11
|
end
|
14
12
|
end
|
13
|
+
end
|
15
14
|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
unless fullpath == ''
|
15
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
16
|
+
# not in an appropriately named file for the autoloader to detect and record
|
17
|
+
# an error of each instance found.
|
18
|
+
PuppetLint.new_check(:autoloader_layout) do
|
19
|
+
def check
|
20
|
+
unless fullpath.nil? || fullpath == ''
|
23
21
|
(class_indexes + defined_type_indexes).each do |class_idx|
|
24
|
-
|
25
|
-
title_token = class_tokens[class_tokens.index { |r| r.type == :NAME }]
|
22
|
+
title_token = class_idx[:name_token]
|
26
23
|
split_title = title_token.value.split('::')
|
27
24
|
mod = split_title.first
|
28
25
|
if split_title.length > 1
|
29
|
-
expected_path = "
|
26
|
+
expected_path = "/#{mod}/manifests/#{split_title[1..-1].join('/')}.pp"
|
30
27
|
else
|
31
|
-
expected_path = "
|
28
|
+
expected_path = "/#{title_token.value}/manifests/init.pp"
|
29
|
+
end
|
30
|
+
|
31
|
+
if PuppetLint.configuration.relative
|
32
|
+
expected_path = expected_path.gsub(/^\//,'').split('/')[1..-1].join('/')
|
32
33
|
end
|
33
34
|
|
34
35
|
unless fullpath.end_with? expected_path
|
35
36
|
notify :error, {
|
36
|
-
:message
|
37
|
-
:
|
38
|
-
:column
|
37
|
+
:message => "#{title_token.value} not in autoload module layout",
|
38
|
+
:line => title_token.line,
|
39
|
+
:column => title_token.column,
|
39
40
|
}
|
40
41
|
end
|
41
42
|
end
|
42
43
|
end
|
43
44
|
end
|
45
|
+
end
|
44
46
|
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
check 'names_containing_dash' do
|
47
|
+
# Public: Check the manifest tokens for any classes or defined types that
|
48
|
+
# have a dash in their name and record a warning for each instance found.
|
49
|
+
PuppetLint.new_check(:names_containing_dash) do
|
50
|
+
def check
|
50
51
|
(class_indexes + defined_type_indexes).each do |class_idx|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
if title_token.value.include? '-'
|
55
|
-
if class_tokens.first.type == :CLASS
|
52
|
+
if class_idx[:name_token].value.include? '-'
|
53
|
+
if class_idx[:type] == :CLASS
|
56
54
|
obj_type = 'class'
|
57
55
|
else
|
58
56
|
obj_type = 'defined type'
|
59
57
|
end
|
60
58
|
|
61
59
|
notify :warning, {
|
62
|
-
:message
|
63
|
-
:
|
64
|
-
:column
|
60
|
+
:message => "#{obj_type} name containing a dash",
|
61
|
+
:line => class_idx[:name_token].line,
|
62
|
+
:column => class_idx[:name_token].column,
|
65
63
|
}
|
66
64
|
end
|
67
65
|
end
|
68
66
|
end
|
67
|
+
end
|
69
68
|
|
70
|
-
|
69
|
+
# Public: Check the manifest tokens for any classes that inherit a params
|
70
|
+
# subclass and record a warning for each instance found.
|
71
|
+
PuppetLint.new_check(:class_inherits_from_params_class) do
|
72
|
+
def check
|
71
73
|
class_indexes.each do |class_idx|
|
72
|
-
|
73
|
-
|
74
|
-
unless inherits_idx.nil?
|
75
|
-
inherited_class_token = class_tokens[inherits_idx].next_code_token
|
76
|
-
if inherited_class_token.value.end_with? '::params'
|
74
|
+
unless class_idx[:inherited_token].nil?
|
75
|
+
if class_idx[:inherited_token].value.end_with? '::params'
|
77
76
|
notify :warning, {
|
78
|
-
:message
|
79
|
-
:
|
80
|
-
:column
|
77
|
+
:message => 'class inheriting from params class',
|
78
|
+
:line => class_idx[:inherited_token].line,
|
79
|
+
:column => class_idx[:inherited_token].column,
|
81
80
|
}
|
82
81
|
end
|
83
82
|
end
|
84
83
|
end
|
85
84
|
end
|
85
|
+
end
|
86
86
|
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
rparen_idx = nil
|
93
|
-
class_name_token = tokens[class_idx[:start]].next_code_token
|
94
|
-
|
95
|
-
if class_name_token.next_code_token.type == :LPAREN
|
96
|
-
tokens[token_idx..-1].each_index do |t|
|
97
|
-
idx = token_idx + t
|
98
|
-
if tokens[idx].type == :LPAREN
|
99
|
-
depth += 1
|
100
|
-
lparen_idx = idx if depth == 1
|
101
|
-
elsif tokens[idx].type == :RPAREN
|
102
|
-
depth -= 1
|
103
|
-
if depth == 0
|
104
|
-
rparen_idx = idx
|
105
|
-
break
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
unless lparen_idx.nil? or rparen_idx.nil?
|
112
|
-
param_tokens = tokens[lparen_idx+1..rparen_idx-1].reject { |r|
|
113
|
-
formatting_tokens.include? r.type
|
114
|
-
}
|
115
|
-
|
116
|
-
paren_stack = []
|
117
|
-
param_tokens.each_index do |param_tokens_idx|
|
118
|
-
this_token = param_tokens[param_tokens_idx]
|
119
|
-
next_token = this_token.next_code_token
|
120
|
-
prev_token = this_token.prev_code_token
|
121
|
-
|
122
|
-
if this_token.type == :LPAREN
|
123
|
-
paren_stack.push(true)
|
124
|
-
elsif this_token.type == :RPAREN
|
125
|
-
paren_stack.pop
|
126
|
-
end
|
127
|
-
next unless paren_stack.empty?
|
128
|
-
|
129
|
-
if this_token.type == :VARIABLE
|
130
|
-
if !next_token.nil? && next_token.type != :EQUALS
|
131
|
-
if !prev_token.nil? && prev_token.type != :EQUALS
|
132
|
-
notify :warning, {
|
133
|
-
:message => 'parameterised class parameter without a default value',
|
134
|
-
:linenumber => this_token.line,
|
135
|
-
:column => this_token.column,
|
136
|
-
}
|
137
|
-
end
|
138
|
-
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
|
-
|
145
|
-
# Public: Test the manifest tokens for any parameterised classes or defined
|
146
|
-
# types that take parameters and record a warning if there are any optional
|
147
|
-
# parameters listed before required parameters.
|
148
|
-
#
|
149
|
-
# Returns nothing.
|
150
|
-
check 'parameter_order' do
|
87
|
+
# Public: Test the manifest tokens for any parameterised classes or defined
|
88
|
+
# types that take parameters and record a warning if there are any optional
|
89
|
+
# parameters listed before required parameters.
|
90
|
+
PuppetLint.new_check(:parameter_order) do
|
91
|
+
def check
|
151
92
|
defined_type_indexes.each do |class_idx|
|
152
|
-
|
153
|
-
depth = 0
|
154
|
-
lparen_idx = nil
|
155
|
-
rparen_idx = nil
|
156
|
-
tokens[token_idx..-1].each_index do |t|
|
157
|
-
idx = token_idx + t
|
158
|
-
if tokens[idx].type == :LPAREN
|
159
|
-
depth += 1
|
160
|
-
lparen_idx = idx if depth == 1
|
161
|
-
elsif tokens[idx].type == :RPAREN
|
162
|
-
depth -= 1
|
163
|
-
if depth == 0
|
164
|
-
rparen_idx = idx
|
165
|
-
break
|
166
|
-
end
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
unless lparen_idx.nil? or rparen_idx.nil?
|
171
|
-
param_tokens = tokens[lparen_idx+1..rparen_idx-1].reject { |r|
|
172
|
-
formatting_tokens.include? r.type
|
173
|
-
}
|
174
|
-
|
93
|
+
unless class_idx[:param_tokens].nil?
|
175
94
|
paren_stack = []
|
176
|
-
param_tokens.
|
177
|
-
|
178
|
-
next_token = param_tokens[param_tokens_idx+1]
|
179
|
-
prev_token = param_tokens[param_tokens_idx-1]
|
180
|
-
|
181
|
-
if this_token.type == :LPAREN
|
95
|
+
class_idx[:param_tokens].each_with_index do |token, i|
|
96
|
+
if token.type == :LPAREN
|
182
97
|
paren_stack.push(true)
|
183
|
-
elsif
|
98
|
+
elsif token.type == :RPAREN
|
184
99
|
paren_stack.pop
|
185
100
|
end
|
186
101
|
next unless paren_stack.empty?
|
187
102
|
|
188
|
-
if
|
189
|
-
if
|
190
|
-
prev_tokens = param_tokens[0..
|
103
|
+
if token.type == :VARIABLE
|
104
|
+
if token.next_code_token.nil? || [:COMMA, :RPAREN].include?(token.next_code_token.type)
|
105
|
+
prev_tokens = class_idx[:param_tokens][0..i]
|
191
106
|
unless prev_tokens.rindex { |r| r.type == :EQUALS }.nil?
|
192
|
-
unless
|
107
|
+
unless token.prev_code_token.nil? or token.prev_code_token.type == :EQUALS
|
193
108
|
msg = 'optional parameter listed before required parameter'
|
194
109
|
notify :warning, {
|
195
|
-
:message
|
196
|
-
:
|
197
|
-
:column
|
110
|
+
:message => msg,
|
111
|
+
:line => token.line,
|
112
|
+
:column => token.column,
|
198
113
|
}
|
199
114
|
end
|
200
115
|
end
|
@@ -204,140 +119,149 @@ class PuppetLint::Plugins::CheckClasses < PuppetLint::CheckPlugin
|
|
204
119
|
end
|
205
120
|
end
|
206
121
|
end
|
122
|
+
end
|
207
123
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
check 'inherits_across_namespaces' do
|
124
|
+
# Public: Test the manifest tokens for any classes that inherit across
|
125
|
+
# namespaces and record a warning for each instance found.
|
126
|
+
PuppetLint.new_check(:inherits_across_namespaces) do
|
127
|
+
def check
|
213
128
|
class_indexes.each do |class_idx|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
next if inherits_token.nil?
|
218
|
-
|
219
|
-
if inherits_token.type == :INHERITS
|
220
|
-
inherited_class_token = inherits_token.next_code_token
|
221
|
-
inherited_module_name = inherited_class_token.value.split('::').reject { |r| r.empty? }.first
|
222
|
-
class_module_name = class_name_token.value.split('::').reject { |r| r.empty? }.first
|
129
|
+
unless class_idx[:inherited_token].nil?
|
130
|
+
inherited_module_name = class_idx[:inherited_token].value.split('::').reject { |r| r.empty? }.first
|
131
|
+
class_module_name = class_idx[:name_token].value.split('::').reject { |r| r.empty? }.first
|
223
132
|
|
224
133
|
unless class_module_name == inherited_module_name
|
225
134
|
notify :warning, {
|
226
|
-
:message
|
227
|
-
:
|
228
|
-
:column
|
135
|
+
:message => "class inherits across module namespaces",
|
136
|
+
:line => class_idx[:inherited_token].line,
|
137
|
+
:column => class_idx[:inherited_token].column,
|
229
138
|
}
|
230
139
|
end
|
231
140
|
end
|
232
141
|
end
|
233
142
|
end
|
143
|
+
end
|
144
|
+
|
145
|
+
# Public: Test the manifest tokens for any classes or defined types that are
|
146
|
+
# defined inside another class.
|
147
|
+
PuppetLint.new_check(:nested_classes_or_defines) do
|
148
|
+
TOKENS = Set[:CLASS, :DEFINE]
|
234
149
|
|
235
|
-
|
236
|
-
# defined inside another class.
|
237
|
-
#
|
238
|
-
# Returns nothing.
|
239
|
-
check 'nested_classes_or_defines' do
|
150
|
+
def check
|
240
151
|
class_indexes.each do |class_idx|
|
241
152
|
# Skip the first token so that we don't pick up the first :CLASS
|
242
|
-
class_tokens =
|
153
|
+
class_tokens = class_idx[:tokens][1..-1]
|
243
154
|
|
244
155
|
class_tokens.each do |token|
|
245
|
-
if token.type
|
156
|
+
if TOKENS.include?(token.type)
|
246
157
|
if token.next_code_token.type != :LBRACE
|
158
|
+
type = token.type == :CLASS ? 'class' : 'defined type'
|
159
|
+
|
247
160
|
notify :warning, {
|
248
|
-
:message
|
249
|
-
:
|
250
|
-
:column
|
161
|
+
:message => "#{type} defined inside a class",
|
162
|
+
:line => token.line,
|
163
|
+
:column => token.column,
|
251
164
|
}
|
252
165
|
end
|
253
166
|
end
|
254
|
-
|
255
|
-
if token.type == :DEFINE
|
256
|
-
notify :warning, {
|
257
|
-
:message => "define defined inside a class",
|
258
|
-
:linenumber => token.line,
|
259
|
-
:column => token.column,
|
260
|
-
}
|
261
|
-
end
|
262
167
|
end
|
263
168
|
end
|
264
169
|
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Public: Test the manifest tokens for any variables that are referenced in
|
173
|
+
# the manifest. If the variables are not fully qualified or one of the
|
174
|
+
# variables automatically created in the scope, check that they have been
|
175
|
+
# defined in the local scope and record a warning for each variable that has
|
176
|
+
# not.
|
177
|
+
PuppetLint.new_check(:variable_scope) do
|
178
|
+
DEFAULT_SCOPE_VARS = Set[
|
179
|
+
'name',
|
180
|
+
'title',
|
181
|
+
'module_name',
|
182
|
+
'environment',
|
183
|
+
'clientcert',
|
184
|
+
'clientversion',
|
185
|
+
'servername',
|
186
|
+
'serverip',
|
187
|
+
'serverversion',
|
188
|
+
'caller_module_name',
|
189
|
+
]
|
190
|
+
POST_VAR_TOKENS = Set[:COMMA, :EQUALS, :RPAREN]
|
191
|
+
|
192
|
+
def check
|
193
|
+
variables_in_scope = DEFAULT_SCOPE_VARS.clone
|
265
194
|
|
266
|
-
# Public: Test the manifest tokens for any variables that are referenced in
|
267
|
-
# the manifest. If the variables are not fully qualified or one of the
|
268
|
-
# variables automatically created in the scope, check that they have been
|
269
|
-
# defined in the local scope and record a warning for each variable that has
|
270
|
-
# not.
|
271
|
-
#
|
272
|
-
# Returns nothing.
|
273
|
-
check 'variable_scope' do
|
274
|
-
variables_in_scope = [
|
275
|
-
'name',
|
276
|
-
'title',
|
277
|
-
'module_name',
|
278
|
-
'environment',
|
279
|
-
'clientcert',
|
280
|
-
'clientversion',
|
281
|
-
'servername',
|
282
|
-
'serverip',
|
283
|
-
'serverversion',
|
284
|
-
'caller_module_name',
|
285
|
-
]
|
286
195
|
(class_indexes + defined_type_indexes).each do |idx|
|
287
|
-
|
288
|
-
object_tokens
|
289
|
-
depth = 0
|
290
|
-
lparen_idx = nil
|
291
|
-
rparen_idx = nil
|
292
|
-
object_tokens.each_index do |t|
|
293
|
-
if object_tokens[t].type == :LPAREN
|
294
|
-
depth += 1
|
295
|
-
lparen_idx = t if depth == 1
|
296
|
-
elsif object_tokens[t].type == :RPAREN
|
297
|
-
depth -= 1
|
298
|
-
if depth == 0
|
299
|
-
rparen_idx = t
|
300
|
-
break
|
301
|
-
end
|
302
|
-
end
|
303
|
-
end
|
304
|
-
referenced_variables = []
|
196
|
+
referenced_variables = Set[]
|
197
|
+
object_tokens = idx[:tokens]
|
305
198
|
|
306
|
-
unless
|
307
|
-
param_tokens
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
if this_token.type == :VARIABLE
|
312
|
-
if {:COMMA => true, :EQUALS => true, :RPAREN => true}.include? next_token.type
|
313
|
-
variables_in_scope << this_token.value
|
199
|
+
unless idx[:param_tokens].nil?
|
200
|
+
idx[:param_tokens].each do |token|
|
201
|
+
if token.type == :VARIABLE
|
202
|
+
if POST_VAR_TOKENS.include? token.next_code_token.type
|
203
|
+
variables_in_scope << token.value
|
314
204
|
end
|
315
205
|
end
|
316
206
|
end
|
317
207
|
end
|
318
208
|
|
319
|
-
|
320
|
-
|
321
|
-
|
209
|
+
future_parser_scopes = {}
|
210
|
+
in_pipe = false
|
211
|
+
temp_scope_vars = []
|
212
|
+
|
213
|
+
object_tokens.each do |token|
|
214
|
+
if token.type == :VARIABLE
|
215
|
+
if in_pipe
|
216
|
+
temp_scope_vars << token.value
|
217
|
+
else
|
218
|
+
if token.next_code_token.type == :EQUALS
|
219
|
+
variables_in_scope << token.value
|
220
|
+
else
|
221
|
+
referenced_variables << token
|
222
|
+
end
|
223
|
+
end
|
224
|
+
elsif token.type == :PIPE
|
225
|
+
in_pipe = !in_pipe
|
322
226
|
|
323
|
-
|
324
|
-
|
325
|
-
variables_in_scope << this_token.value
|
227
|
+
if in_pipe
|
228
|
+
temp_scope_vars = []
|
326
229
|
else
|
327
|
-
|
230
|
+
start_idx = tokens.find_index(token)
|
231
|
+
end_token = nil
|
232
|
+
brace_depth = 0
|
233
|
+
|
234
|
+
tokens[start_idx..-1].each do |sub_token|
|
235
|
+
case sub_token.type
|
236
|
+
when :LBRACE
|
237
|
+
brace_depth += 1
|
238
|
+
when :RBRACE
|
239
|
+
brace_depth -= 1
|
240
|
+
if brace_depth == 0
|
241
|
+
end_token = sub_token
|
242
|
+
break
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
246
|
+
|
247
|
+
future_parser_scopes.merge!(Hash[(token.line..end_token.line).to_a.map { |i| [i, temp_scope_vars] }])
|
328
248
|
end
|
329
249
|
end
|
330
250
|
end
|
331
251
|
|
332
252
|
msg = "top-scope variable being used without an explicit namespace"
|
333
253
|
referenced_variables.each do |token|
|
254
|
+
unless future_parser_scopes[token.line].nil?
|
255
|
+
next if future_parser_scopes[token.line].include?(token.value)
|
256
|
+
end
|
257
|
+
|
334
258
|
unless token.value.include? '::'
|
335
259
|
unless variables_in_scope.include? token.value
|
336
|
-
unless token.value =~ /\d
|
260
|
+
unless token.value =~ /\A\d+\Z/
|
337
261
|
notify :warning, {
|
338
|
-
:message
|
339
|
-
:
|
340
|
-
:column
|
262
|
+
:message => msg,
|
263
|
+
:line => token.line,
|
264
|
+
:column => token.column,
|
341
265
|
}
|
342
266
|
end
|
343
267
|
end
|