puppet-lint 0.2.0.pre1 → 0.2.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/.gitignore +1 -0
- data/.travis.yml +1 -14
- data/Gemfile +2 -0
- data/Rakefile +5 -0
- data/bin/puppet-lint +1 -99
- data/lib/puppet-lint.rb +4 -12
- data/lib/puppet-lint/bin.rb +115 -0
- data/lib/puppet-lint/configuration.rb +6 -2
- data/lib/puppet-lint/lexer.rb +135 -83
- data/lib/puppet-lint/lexer/token.rb +62 -0
- data/lib/puppet-lint/plugin.rb +57 -51
- data/lib/puppet-lint/plugins.rb +2 -0
- data/lib/puppet-lint/plugins/check_classes.rb +161 -45
- data/lib/puppet-lint/plugins/check_comments.rb +33 -0
- data/lib/puppet-lint/plugins/check_conditionals.rb +8 -10
- data/lib/puppet-lint/plugins/check_documentation.rb +41 -0
- data/lib/puppet-lint/plugins/check_resources.rb +28 -2
- data/lib/puppet-lint/plugins/check_strings.rb +6 -4
- data/lib/puppet-lint/plugins/check_variables.rb +1 -1
- data/lib/puppet-lint/plugins/check_whitespace.rb +26 -49
- data/lib/puppet-lint/tasks/puppet-lint.rb +2 -1
- data/lib/puppet-lint/version.rb +1 -1
- data/puppet-lint.gemspec +1 -0
- data/spec/fixtures/test/manifests/fail.pp +2 -0
- data/spec/fixtures/test/manifests/init.pp +3 -0
- data/spec/fixtures/test/manifests/warning.pp +2 -0
- data/spec/puppet-lint/bin_spec.rb +266 -0
- data/spec/puppet-lint/configuration_spec.rb +51 -0
- data/spec/puppet-lint/lexer/token_spec.rb +18 -0
- data/spec/puppet-lint/lexer_spec.rb +738 -0
- data/spec/puppet-lint/{check_classes_spec.rb → plugins/check_classes_spec.rb} +74 -7
- data/spec/puppet-lint/plugins/check_comments_spec.rb +40 -0
- data/spec/puppet-lint/{check_conditionals_spec.rb → plugins/check_conditionals_spec.rb} +19 -0
- data/spec/puppet-lint/plugins/check_documentation_spec.rb +55 -0
- data/spec/puppet-lint/{check_resources_spec.rb → plugins/check_resources_spec.rb} +65 -0
- data/spec/puppet-lint/{check_strings_spec.rb → plugins/check_strings_spec.rb} +18 -1
- data/spec/puppet-lint/{check_variables_spec.rb → plugins/check_variables_spec.rb} +0 -0
- data/spec/puppet-lint/plugins/check_whitespace_spec.rb +291 -0
- data/spec/puppet-lint_spec.rb +10 -0
- data/spec/spec_helper.rb +5 -0
- metadata +58 -24
- data/spec/puppet-lint/check_whitespace_spec.rb +0 -120
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -5,20 +5,7 @@ rvm:
|
|
5
5
|
branches:
|
6
6
|
only:
|
7
7
|
- master
|
8
|
+
- dust_bunny
|
8
9
|
notifications:
|
9
10
|
email:
|
10
11
|
- tim@github.com
|
11
|
-
env:
|
12
|
-
- PUPPET_VERSION=2.6.13
|
13
|
-
- PUPPET_VERSION=2.7.9
|
14
|
-
- PUPPET_VERSION=0.25.4
|
15
|
-
matrix:
|
16
|
-
exclude:
|
17
|
-
- rvm: 1.9.2
|
18
|
-
env: PUPPET_VERSION=2.6.13
|
19
|
-
- rvm: 1.9.3
|
20
|
-
env: PUPPET_VERSION=2.6.13
|
21
|
-
- rvm: 1.9.2
|
22
|
-
env: PUPPET_VERSION=0.25.4
|
23
|
-
- rvm: 1.9.3
|
24
|
-
env: PUPPET_VERSION=0.25.4
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
@@ -6,6 +6,11 @@ task :default => :test
|
|
6
6
|
|
7
7
|
RSpec::Core::RakeTask.new(:test)
|
8
8
|
|
9
|
+
RSpec::Core::RakeTask.new(:cov) do |t|
|
10
|
+
t.rcov = true
|
11
|
+
t.rcov_opts = '--exclude "spec" --xrefs'
|
12
|
+
end
|
13
|
+
|
9
14
|
### RDOC Tasks ###
|
10
15
|
require 'rdoc'
|
11
16
|
if (RDoc::VERSION.split('.') <=> ['2','4','2']) >= 0
|
data/bin/puppet-lint
CHANGED
@@ -2,104 +2,6 @@
|
|
2
2
|
|
3
3
|
$:.unshift File.join(File.dirname(__FILE__), *%w[.. lib])
|
4
4
|
|
5
|
-
help = <<HELP
|
6
|
-
Puppet-lint
|
7
|
-
|
8
|
-
Basic Command Line Usage:
|
9
|
-
puppet-lint [OPTIONS] [PATH]
|
10
|
-
|
11
|
-
PATH The path to the Puppet manifest.
|
12
|
-
|
13
|
-
Options:
|
14
|
-
HELP
|
15
|
-
|
16
|
-
require 'optparse'
|
17
|
-
require 'rubygems'
|
18
5
|
require 'puppet-lint'
|
19
6
|
|
20
|
-
|
21
|
-
opts.banner = help
|
22
|
-
|
23
|
-
opts.on("--version", "Display current version.") do
|
24
|
-
puts "Puppet-lint " + PuppetLint::VERSION
|
25
|
-
exit 0
|
26
|
-
end
|
27
|
-
|
28
|
-
opts.on("--with-filename", "Display the filename before the warning") do
|
29
|
-
PuppetLint.configuration.with_filename = true
|
30
|
-
end
|
31
|
-
|
32
|
-
opts.on("--error-level LEVEL", [:all, :warning, :error], "The level of error to return.", "(warning, error, all)") do |el|
|
33
|
-
PuppetLint.configuration.error_level = el
|
34
|
-
end
|
35
|
-
|
36
|
-
opts.on("--fail-on-warnings", "Return a non-zero exit status for warnings.") do
|
37
|
-
PuppetLint.configuration.fail_on_warnings = true
|
38
|
-
end
|
39
|
-
|
40
|
-
opts.on("--log-format FORMAT",
|
41
|
-
"Change the log format.", "Overrides --with-filename.",
|
42
|
-
"The following placeholders can be used:",
|
43
|
-
"%{filename} - Filename without path.",
|
44
|
-
"%{path} - Path as provided.",
|
45
|
-
"%{fullpath} - Full path.",
|
46
|
-
"%{linenumber} - Line number.",
|
47
|
-
"%{kind} - The kind of message.",
|
48
|
-
" - (warning, error)",
|
49
|
-
"%{KIND} - Uppercase version of %{kind}",
|
50
|
-
"%{check} - Name of the check.",
|
51
|
-
"%{message} - The message."
|
52
|
-
) do |format|
|
53
|
-
PuppetLint.configuration.log_format = format
|
54
|
-
end
|
55
|
-
|
56
|
-
opts.separator ""
|
57
|
-
opts.separator " Disable checks:"
|
58
|
-
|
59
|
-
PuppetLint.configuration.checks.each do |check|
|
60
|
-
opts.on("--no-#{check}-check", "Skip the #{check} check") do
|
61
|
-
PuppetLint.configuration.send("disable_#{check}")
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
opts.load(File.expand_path("~/.puppet-lintrc")) unless opts.load(".puppet-lintrc")
|
66
|
-
end
|
67
|
-
|
68
|
-
begin
|
69
|
-
opts.parse!
|
70
|
-
rescue OptionParser::InvalidOption
|
71
|
-
puts "puppet-lint: #{$!.message}"
|
72
|
-
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
73
|
-
exit
|
74
|
-
end
|
75
|
-
|
76
|
-
if ARGV[0].nil?
|
77
|
-
puts "puppet-lint: no file specified"
|
78
|
-
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
79
|
-
exit
|
80
|
-
end
|
81
|
-
|
82
|
-
begin
|
83
|
-
path = ARGV[0]
|
84
|
-
if File.directory?(path)
|
85
|
-
Dir.chdir(path)
|
86
|
-
path = Dir.glob('**/*.pp')
|
87
|
-
else
|
88
|
-
path = [path]
|
89
|
-
end
|
90
|
-
|
91
|
-
path.each do |f|
|
92
|
-
l = PuppetLint.new
|
93
|
-
l.file = f
|
94
|
-
l.run
|
95
|
-
if l.errors? or (l.warnings? and PuppetLint.configuration.fail_on_warnings)
|
96
|
-
exit 1
|
97
|
-
end
|
98
|
-
end
|
99
|
-
|
100
|
-
rescue PuppetLint::NoCodeError
|
101
|
-
puts "puppet-lint: no file specified or specified file does not exist"
|
102
|
-
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
103
|
-
exit
|
104
|
-
end
|
105
|
-
|
7
|
+
PuppetLint::Bin.new(ARGV).run
|
data/lib/puppet-lint.rb
CHANGED
@@ -2,6 +2,7 @@ require 'puppet-lint/version'
|
|
2
2
|
require 'puppet-lint/lexer'
|
3
3
|
require 'puppet-lint/configuration'
|
4
4
|
require 'puppet-lint/plugin'
|
5
|
+
require 'puppet-lint/bin'
|
5
6
|
|
6
7
|
unless String.respond_to?('prepend')
|
7
8
|
class String
|
@@ -67,7 +68,7 @@ end
|
|
67
68
|
class PuppetLint::NoCodeError < StandardError; end
|
68
69
|
|
69
70
|
class PuppetLint
|
70
|
-
attr_reader :
|
71
|
+
attr_reader :data
|
71
72
|
|
72
73
|
def initialize
|
73
74
|
@data = nil
|
@@ -125,7 +126,7 @@ class PuppetLint
|
|
125
126
|
end
|
126
127
|
end
|
127
128
|
end
|
128
|
-
|
129
|
+
|
129
130
|
def errors?
|
130
131
|
@statistics[:error] != 0
|
131
132
|
end
|
@@ -134,12 +135,6 @@ class PuppetLint
|
|
134
135
|
@statistics[:warning] != 0
|
135
136
|
end
|
136
137
|
|
137
|
-
def checks
|
138
|
-
PuppetLint::CheckPlugin.repository.map do |plugin|
|
139
|
-
plugin.new.checks
|
140
|
-
end.flatten
|
141
|
-
end
|
142
|
-
|
143
138
|
def run
|
144
139
|
if @data.nil?
|
145
140
|
raise PuppetLint::NoCodeError
|
@@ -152,9 +147,6 @@ class PuppetLint
|
|
152
147
|
end
|
153
148
|
|
154
149
|
# Default configuration options
|
155
|
-
PuppetLint.configuration.
|
156
|
-
PuppetLint.configuration.error_level = :all
|
157
|
-
PuppetLint.configuration.with_filename = false
|
158
|
-
PuppetLint.configuration.log_format = ''
|
150
|
+
PuppetLint.configuration.defaults
|
159
151
|
|
160
152
|
require 'puppet-lint/plugins'
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
|
3
|
+
class PuppetLint::Bin
|
4
|
+
def initialize(args)
|
5
|
+
@args = args
|
6
|
+
end
|
7
|
+
|
8
|
+
def run
|
9
|
+
help = <<-EOHELP
|
10
|
+
Puppet-lint
|
11
|
+
|
12
|
+
Basic Command Line Usage:
|
13
|
+
puppet-lint [OPTIONS] [PATH]
|
14
|
+
|
15
|
+
PATH The path to the Puppet manifest.
|
16
|
+
|
17
|
+
Options:
|
18
|
+
EOHELP
|
19
|
+
|
20
|
+
opts = OptionParser.new do |opts|
|
21
|
+
opts.banner = help
|
22
|
+
|
23
|
+
opts.on("--version", "Display current version.") do
|
24
|
+
puts "Puppet-lint " + PuppetLint::VERSION
|
25
|
+
return 0
|
26
|
+
end
|
27
|
+
|
28
|
+
opts.on("--with-filename", "Display the filename before the warning") do
|
29
|
+
PuppetLint.configuration.with_filename = true
|
30
|
+
end
|
31
|
+
|
32
|
+
opts.on("--fail-on-warnings", "Return a non-zero exit status for warnings.") do
|
33
|
+
PuppetLint.configuration.fail_on_warnings = true
|
34
|
+
end
|
35
|
+
|
36
|
+
opts.on("--error-level LEVEL", [:all, :warning, :error], "The level of error to return.", "(warning, error, all)") do |el|
|
37
|
+
PuppetLint.configuration.error_level = el
|
38
|
+
end
|
39
|
+
|
40
|
+
opts.on("--log-format FORMAT",
|
41
|
+
"Change the log format.", "Overrides --with-filename.",
|
42
|
+
"The following placeholders can be used:",
|
43
|
+
"%{filename} - Filename without path.",
|
44
|
+
"%{path} - Path as provided.",
|
45
|
+
"%{fullpath} - Full path.",
|
46
|
+
"%{linenumber} - Line number.",
|
47
|
+
"%{kind} - The kind of message.",
|
48
|
+
" - (warning, error)",
|
49
|
+
"%{KIND} - Uppercase version of %{kind}",
|
50
|
+
"%{check} - Name of the check.",
|
51
|
+
"%{message} - The message."
|
52
|
+
) do |format|
|
53
|
+
PuppetLint.configuration.log_format = format
|
54
|
+
end
|
55
|
+
|
56
|
+
opts.separator ""
|
57
|
+
opts.separator " Disable checks:"
|
58
|
+
|
59
|
+
PuppetLint.configuration.checks.each do |check|
|
60
|
+
opts.on("--no-#{check}-check", "Skip the #{check} check") do
|
61
|
+
PuppetLint.configuration.send("disable_#{check}")
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
opts.load('/etc/puppet-lint.rc')
|
66
|
+
opts.load(File.expand_path('~/.puppet-lint.rc'))
|
67
|
+
if opts.load(File.expand_path('~/.puppet-lintrc'))
|
68
|
+
$stderr.puts 'Depreciated: Found ~/.puppet-lintrc instead of ~/.puppet-lint.rc'
|
69
|
+
end
|
70
|
+
opts.load('.puppet-lint.rc')
|
71
|
+
if opts.load('.puppet-lintrc')
|
72
|
+
$stderr.puts 'Depreciated: Read .puppet-lintrc instead of .puppet-lint.rc'
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
begin
|
77
|
+
opts.parse!(@args)
|
78
|
+
rescue OptionParser::InvalidOption
|
79
|
+
puts "puppet-lint: #{$!.message}"
|
80
|
+
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
81
|
+
return 1
|
82
|
+
end
|
83
|
+
|
84
|
+
if @args[0].nil?
|
85
|
+
puts "puppet-lint: no file specified"
|
86
|
+
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
87
|
+
return 1
|
88
|
+
end
|
89
|
+
|
90
|
+
begin
|
91
|
+
path = @args[0]
|
92
|
+
if File.directory?(path)
|
93
|
+
path = Dir.glob("#{path}/**/*.pp")
|
94
|
+
else
|
95
|
+
path = @args
|
96
|
+
end
|
97
|
+
|
98
|
+
return_val = 0
|
99
|
+
path.each do |f|
|
100
|
+
l = PuppetLint.new
|
101
|
+
l.file = f
|
102
|
+
l.run
|
103
|
+
if l.errors? or (l.warnings? and PuppetLint.configuration.fail_on_warnings)
|
104
|
+
return_val = 1
|
105
|
+
end
|
106
|
+
end
|
107
|
+
return return_val
|
108
|
+
|
109
|
+
rescue PuppetLint::NoCodeError
|
110
|
+
puts "puppet-lint: no file specified or specified file does not exist"
|
111
|
+
puts "puppet-lint: try 'puppet-lint --help' for more information"
|
112
|
+
return 1
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -54,8 +54,12 @@ class PuppetLint
|
|
54
54
|
}
|
55
55
|
end
|
56
56
|
|
57
|
-
def
|
58
|
-
settings
|
57
|
+
def defaults
|
58
|
+
settings.clear
|
59
|
+
self.with_filename = false
|
60
|
+
self.fail_on_warnings = false
|
61
|
+
self.error_level = :all
|
62
|
+
self.log_format = ''
|
59
63
|
end
|
60
64
|
end
|
61
65
|
end
|
data/lib/puppet-lint/lexer.rb
CHANGED
@@ -1,31 +1,43 @@
|
|
1
1
|
require 'pp'
|
2
2
|
require 'strscan'
|
3
|
+
require 'puppet-lint/lexer/token'
|
4
|
+
require 'set'
|
3
5
|
|
4
6
|
class PuppetLint
|
7
|
+
class LexerError < RuntimeError; end
|
5
8
|
class Lexer
|
6
|
-
KEYWORDS =
|
7
|
-
'class',
|
8
|
-
'case',
|
9
|
-
'default',
|
10
|
-
'define',
|
11
|
-
'import',
|
12
|
-
'if',
|
13
|
-
'else',
|
14
|
-
'elsif',
|
15
|
-
'inherits',
|
16
|
-
'node',
|
17
|
-
'and',
|
18
|
-
'or',
|
19
|
-
'undef',
|
20
|
-
'true',
|
21
|
-
'false',
|
22
|
-
'in',
|
23
|
-
'unless',
|
24
|
-
|
9
|
+
KEYWORDS = {
|
10
|
+
'class' => true,
|
11
|
+
'case' => true,
|
12
|
+
'default' => true,
|
13
|
+
'define' => true,
|
14
|
+
'import' => true,
|
15
|
+
'if' => true,
|
16
|
+
'else' => true,
|
17
|
+
'elsif' => true,
|
18
|
+
'inherits' => true,
|
19
|
+
'node' => true,
|
20
|
+
'and' => true,
|
21
|
+
'or' => true,
|
22
|
+
'undef' => true,
|
23
|
+
'true' => true,
|
24
|
+
'false' => true,
|
25
|
+
'in' => true,
|
26
|
+
'unless' => true,
|
27
|
+
}
|
28
|
+
|
29
|
+
REGEX_PREV_TOKENS = {
|
30
|
+
:NODE => true,
|
31
|
+
:LBRACE => true,
|
32
|
+
:RBRACE => true,
|
33
|
+
:MATCH => true,
|
34
|
+
:NOMATCH => true,
|
35
|
+
:COMMA => true,
|
36
|
+
}
|
25
37
|
|
26
38
|
KNOWN_TOKENS = [
|
27
39
|
[:CLASSREF, /\A(((::){0,1}[A-Z][-\w]*)+)/],
|
28
|
-
[:NUMBER, /\A(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b/],
|
40
|
+
[:NUMBER, /\A\b((?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?))\b/],
|
29
41
|
[:NAME, /\A(((::)?[a-z0-9][-\w]*)(::[a-z0-9][-\w]*)*)/],
|
30
42
|
[:LBRACK, /\A(\[)/],
|
31
43
|
[:RBRACK, /\A(\])/],
|
@@ -65,10 +77,18 @@ class PuppetLint
|
|
65
77
|
[:SEMIC, /\A(;)/],
|
66
78
|
[:QMARK, /\A(\?)/],
|
67
79
|
[:BACKSLASH, /\A(\\)/],
|
68
|
-
[:DIV, /\A(\/)/],
|
69
80
|
[:TIMES, /\A(\*)/],
|
70
81
|
]
|
71
82
|
|
83
|
+
FORMATTING_TOKENS = {
|
84
|
+
:WHITESPACE => true,
|
85
|
+
:NEWLINE => true,
|
86
|
+
:COMMENT => true,
|
87
|
+
:MLCOMMENT => true,
|
88
|
+
:SLASH_COMMENT => true,
|
89
|
+
:INDENT => true,
|
90
|
+
}
|
91
|
+
|
72
92
|
def tokens
|
73
93
|
@tokens ||= []
|
74
94
|
end
|
@@ -87,12 +107,12 @@ class PuppetLint
|
|
87
107
|
if value = chunk[regex, 1]
|
88
108
|
if type == :NAME
|
89
109
|
if KEYWORDS.include? value
|
90
|
-
tokens << new_token(value.upcase.to_sym, value, code[0..i])
|
110
|
+
tokens << new_token(value.upcase.to_sym, value, :chunk => code[0..i])
|
91
111
|
else
|
92
|
-
tokens << new_token(type, value, code[0..i])
|
112
|
+
tokens << new_token(type, value, :chunk => code[0..i])
|
93
113
|
end
|
94
114
|
else
|
95
|
-
tokens << new_token(type, value, code[0..i])
|
115
|
+
tokens << new_token(type, value, :chunk => code[0..i])
|
96
116
|
end
|
97
117
|
i += value.size
|
98
118
|
found = true
|
@@ -101,65 +121,67 @@ class PuppetLint
|
|
101
121
|
end
|
102
122
|
|
103
123
|
unless found
|
104
|
-
if
|
105
|
-
tokens << new_token(:
|
106
|
-
i += identifier.size
|
107
|
-
|
108
|
-
elsif var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+)/, 1]
|
109
|
-
tokens << new_token(:VARIABLE, var_name, code[0..i])
|
124
|
+
if var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+)/, 1]
|
125
|
+
tokens << new_token(:VARIABLE, var_name, :chunk => code[0..i])
|
110
126
|
i += var_name.size + 1
|
111
127
|
|
112
|
-
elsif
|
113
|
-
|
114
|
-
|
128
|
+
elsif chunk.match(/\A'(.*?)'/m)
|
129
|
+
str_content = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])'/m)
|
130
|
+
tokens << new_token(:SSTRING, str_content[0..-2], :chunk => code[0..i])
|
131
|
+
i += str_content.size + 1
|
115
132
|
|
116
133
|
elsif chunk.match(/\A"/)
|
117
|
-
str_contents = StringScanner.new(code[i+1..-1]).scan_until(/[^\\]"/m)
|
134
|
+
str_contents = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])"/m)
|
118
135
|
_ = code[0..i].split("\n")
|
119
136
|
interpolate_string(str_contents, _.count, _.last.length)
|
120
137
|
i += str_contents.size + 1
|
121
138
|
|
122
|
-
elsif chunk.match(/\A\//)
|
123
|
-
str_content = StringScanner.new(code[i+1..-1]).scan_until(/[^\\]\//m)
|
124
|
-
tokens << new_token(:REGEX, str_content, code[0..i])
|
125
|
-
i += str_content.size + 1
|
126
|
-
|
127
139
|
elsif comment = chunk[/\A(#.*)/, 1]
|
128
140
|
comment_size = comment.size
|
129
141
|
comment.sub!(/# ?/, '')
|
130
|
-
tokens << new_token(:COMMENT, comment, code[0..i])
|
142
|
+
tokens << new_token(:COMMENT, comment, :chunk => code[0..i])
|
131
143
|
i += comment_size
|
132
144
|
|
133
145
|
elsif slash_comment = chunk[/\A(\/\/.*)/, 1]
|
134
146
|
slash_comment_size = slash_comment.size
|
135
147
|
slash_comment.sub!(/\/\/ ?/, '')
|
136
|
-
tokens << new_token(:SLASH_COMMENT, slash_comment, code[0..i])
|
148
|
+
tokens << new_token(:SLASH_COMMENT, slash_comment, :chunk => code[0..i])
|
137
149
|
i += slash_comment_size
|
138
150
|
|
139
151
|
elsif mlcomment = chunk[/\A(\/\*.*?\*\/)/m, 1]
|
140
|
-
mlcomment_size =
|
141
|
-
mlcomment.sub!(
|
142
|
-
mlcomment.sub!(/
|
143
|
-
|
152
|
+
mlcomment_size = mlcomment.size
|
153
|
+
mlcomment.sub!(/\A\/\* ?/, '')
|
154
|
+
mlcomment.sub!(/ ?\*\/\Z/, '')
|
155
|
+
mlcomment.gsub!(/^ ?\* ?/, '')
|
156
|
+
mlcomment.gsub!(/\n/, ' ')
|
157
|
+
mlcomment.strip!
|
158
|
+
tokens << new_token(:MLCOMMENT, mlcomment, :chunk => code[0..i])
|
144
159
|
i += mlcomment_size
|
145
160
|
|
161
|
+
elsif chunk.match(/\A\/.*?\//) && possible_regex?
|
162
|
+
str_content = StringScanner.new(code[i+1..-1]).scan_until(/(\A|[^\\])\//m)
|
163
|
+
tokens << new_token(:REGEX, str_content[0..-2], :chunk => code[0..i])
|
164
|
+
i += str_content.size + 1
|
165
|
+
|
146
166
|
elsif indent = chunk[/\A\n([ \t]+)/m, 1]
|
147
|
-
tokens << new_token(:NEWLINE, '\n', code[0..i])
|
148
|
-
tokens << new_token(:INDENT, indent, code[0..i+1])
|
167
|
+
tokens << new_token(:NEWLINE, '\n', :chunk => code[0..i])
|
168
|
+
tokens << new_token(:INDENT, indent, :chunk => code[0..i+1])
|
149
169
|
i += indent.size + 1
|
150
170
|
|
151
171
|
elsif whitespace = chunk[/\A([ \t]+)/, 1]
|
152
|
-
tokens << new_token(:WHITESPACE, whitespace, code[0..i])
|
172
|
+
tokens << new_token(:WHITESPACE, whitespace, :chunk => code[0..i])
|
153
173
|
i += whitespace.size
|
154
174
|
|
155
175
|
elsif chunk.match(/\A\n/)
|
156
|
-
tokens << new_token(:NEWLINE, '\n', code[0..i])
|
176
|
+
tokens << new_token(:NEWLINE, '\n', :chunk => code[0..i])
|
157
177
|
i += 1
|
158
178
|
|
159
|
-
|
160
|
-
|
161
|
-
tokens << new_token(value, value, code[0..i])
|
179
|
+
elsif chunk.match(/\A\//)
|
180
|
+
tokens << new_token(:DIV, '/', :chunk => code[0..i])
|
162
181
|
i += 1
|
182
|
+
|
183
|
+
else
|
184
|
+
raise PuppetLint::LexerError, chunk
|
163
185
|
end
|
164
186
|
end
|
165
187
|
end
|
@@ -167,16 +189,54 @@ class PuppetLint
|
|
167
189
|
tokens
|
168
190
|
end
|
169
191
|
|
170
|
-
def
|
171
|
-
|
172
|
-
|
173
|
-
|
192
|
+
def possible_regex?
|
193
|
+
prev_token = tokens.reject { |r|
|
194
|
+
FORMATTING_TOKENS.include? r.type
|
195
|
+
}.last
|
196
|
+
|
197
|
+
return true if prev_token.nil?
|
198
|
+
|
199
|
+
if REGEX_PREV_TOKENS.include? prev_token.type
|
200
|
+
true
|
201
|
+
else
|
202
|
+
false
|
203
|
+
end
|
204
|
+
end
|
205
|
+
|
206
|
+
def new_token(type, value, opts = {})
|
207
|
+
if opts[:chunk]
|
208
|
+
line_no = opts[:chunk].count("\n") + 1
|
209
|
+
if line_no == 1
|
210
|
+
column = opts[:chunk].length
|
211
|
+
else
|
212
|
+
column = opts[:chunk].length - opts[:chunk].rindex("\n") - 1
|
213
|
+
end
|
214
|
+
column += 1 if column == 0
|
215
|
+
else
|
216
|
+
column = opts[:column]
|
217
|
+
line_no = opts[:line]
|
218
|
+
end
|
219
|
+
|
220
|
+
token = Token.new(type, value, line_no, column)
|
221
|
+
unless tokens.last.nil?
|
222
|
+
token.prev_token = tokens.last
|
223
|
+
tokens.last.next_token = token
|
224
|
+
|
225
|
+
unless FORMATTING_TOKENS.include?(token.type)
|
226
|
+
prev_nf_idx = tokens.rindex { |r| ! FORMATTING_TOKENS.include? r.type }
|
227
|
+
unless prev_nf_idx.nil?
|
228
|
+
prev_nf_token = tokens[prev_nf_idx]
|
229
|
+
prev_nf_token.next_code_token = token
|
230
|
+
token.prev_code_token = prev_nf_token
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
174
234
|
|
175
|
-
|
235
|
+
token
|
176
236
|
end
|
177
237
|
|
178
238
|
def get_string_segment(string, terminators)
|
179
|
-
str = string.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]
|
239
|
+
str = string.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]+/)
|
180
240
|
begin
|
181
241
|
[str[0..-2], str[-1,1]]
|
182
242
|
rescue
|
@@ -191,34 +251,41 @@ class PuppetLint
|
|
191
251
|
until value.nil?
|
192
252
|
if terminator == "\""
|
193
253
|
if first
|
194
|
-
tokens <<
|
254
|
+
tokens << new_token(:STRING, value, :line => line, :column => column)
|
195
255
|
first = false
|
196
256
|
else
|
197
257
|
line += value.count("\n")
|
198
258
|
token_column = column + (ss.pos - value.size)
|
199
|
-
tokens <<
|
259
|
+
tokens << new_token(:DQPOST, value, :line => line, :column => token_column)
|
200
260
|
end
|
201
261
|
else
|
202
262
|
if first
|
203
|
-
tokens <<
|
263
|
+
tokens << new_token(:DQPRE, value, :line => line, :column => column)
|
204
264
|
first = false
|
205
265
|
else
|
206
266
|
line += value.count("\n")
|
207
267
|
token_column = column + (ss.pos - value.size)
|
208
|
-
tokens <<
|
268
|
+
tokens << new_token(:DQMID, value, :line => line, :column => token_column)
|
209
269
|
end
|
210
270
|
if ss.scan(/\{/).nil?
|
211
271
|
var_name = ss.scan(/(::)?([\w-]+::)*[\w-]+/)
|
212
272
|
unless var_name.nil?
|
213
273
|
token_column = column + (ss.pos - var_name.size)
|
214
|
-
tokens <<
|
274
|
+
tokens << new_token(:UNENC_VARIABLE, var_name, :line => line, :column => token_column)
|
215
275
|
end
|
216
276
|
else
|
217
|
-
|
218
|
-
|
219
|
-
token_column = column + (ss.pos -
|
220
|
-
tokens <<
|
221
|
-
|
277
|
+
contents = ss.scan_until(/\}/)[0..-2]
|
278
|
+
if contents.match(/\A(::)?([\w-]+::)*[\w-]+\Z/)
|
279
|
+
token_column = column + (ss.pos - contents.size - 1)
|
280
|
+
tokens << new_token(:VARIABLE, contents, :line => line, :column => token_column)
|
281
|
+
else
|
282
|
+
lexer = PuppetLint::Lexer.new
|
283
|
+
lexer.tokenise(contents)
|
284
|
+
lexer.tokens.each do |token|
|
285
|
+
tok_col = column + token.column + (ss.pos - contents.size - 1)
|
286
|
+
tok_line = token.line + line - 1
|
287
|
+
tokens << new_token(token.type, token.value, :line => tok_line, :column => tok_col)
|
288
|
+
end
|
222
289
|
end
|
223
290
|
end
|
224
291
|
end
|
@@ -226,19 +293,4 @@ class PuppetLint
|
|
226
293
|
end
|
227
294
|
end
|
228
295
|
end
|
229
|
-
|
230
|
-
class Token
|
231
|
-
attr_reader :type, :value, :line, :column
|
232
|
-
|
233
|
-
def initialize(type, value, line, column)
|
234
|
-
@value = value
|
235
|
-
@type = type
|
236
|
-
@line = line
|
237
|
-
@column = column
|
238
|
-
end
|
239
|
-
|
240
|
-
def inspect
|
241
|
-
"<Token #{@type.inspect} (#{@value}) @#{@line}:#{@column}>"
|
242
|
-
end
|
243
|
-
end
|
244
296
|
end
|