puppet-lint 0.4.0.pre1 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|