puppet-lint 2.3.6 → 2.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.rubocop_todo.yml +2 -2
- data/.travis.yml +7 -5
- data/CHANGELOG.md +53 -0
- data/README.md +18 -0
- data/appveyor.yml +2 -0
- data/lib/puppet-lint/data.rb +17 -2
- data/lib/puppet-lint/lexer.rb +90 -204
- data/lib/puppet-lint/lexer/string_slurper.rb +157 -0
- data/lib/puppet-lint/lexer/token.rb +2 -0
- data/lib/puppet-lint/optparser.rb +4 -5
- data/lib/puppet-lint/plugins/check_conditionals/case_without_default.rb +15 -1
- data/lib/puppet-lint/plugins/check_resources/ensure_first_param.rb +4 -1
- data/lib/puppet-lint/plugins/check_strings/quoted_booleans.rb +1 -0
- data/lib/puppet-lint/plugins/check_strings/variables_not_enclosed.rb +71 -0
- data/lib/puppet-lint/plugins/check_whitespace/arrow_alignment.rb +1 -1
- data/lib/puppet-lint/version.rb +1 -1
- data/spec/fixtures/test/manifests/two_warnings.pp +5 -0
- data/spec/puppet-lint/bin_spec.rb +41 -0
- data/spec/puppet-lint/data_spec.rb +12 -0
- data/spec/puppet-lint/lexer/string_slurper_spec.rb +407 -0
- data/spec/puppet-lint/lexer_spec.rb +1097 -590
- data/spec/puppet-lint/plugins/check_classes/variable_scope_spec.rb +1 -1
- data/spec/puppet-lint/plugins/check_conditionals/case_without_default_spec.rb +39 -0
- data/spec/puppet-lint/plugins/check_resources/ensure_first_param_spec.rb +16 -0
- data/spec/puppet-lint/plugins/check_strings/only_variable_string_spec.rb +6 -6
- data/spec/puppet-lint/plugins/check_strings/variables_not_enclosed_spec.rb +32 -0
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: b67dfbcf1aff9be2449b52eb8ff66db18cf025ad69ce6dee4f3e8a7ae4155980
|
4
|
+
data.tar.gz: 2eec8d5d37d1deeaaf9e26ca6ad24e7f841e137bb9de99e61736675862f6bffc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 80e81796c7aa00827859e45f6586105bbeb1c16c5a813e3130e8ff1fa11272c012dd86563d21172862a00852f49c0b0df2015881c83e15b62e208e117c85e938
|
7
|
+
data.tar.gz: f21481a188185489015c3fa7dff8bd3d00e5eec505a547abc4c7633805c41e275f311eec37f5c4a93899ea77fb43a530ba25588fdbb0f78dc043f904d6716c1b
|
data/.rubocop_todo.yml
CHANGED
@@ -45,7 +45,7 @@ Metrics/BlockNesting:
|
|
45
45
|
# Offense count: 2
|
46
46
|
# Configuration parameters: CountComments.
|
47
47
|
Metrics/ClassLength:
|
48
|
-
Max:
|
48
|
+
Max: 384
|
49
49
|
|
50
50
|
# Offense count: 20
|
51
51
|
Metrics/CyclomaticComplexity:
|
@@ -64,7 +64,7 @@ Metrics/MethodLength:
|
|
64
64
|
|
65
65
|
# Offense count: 18
|
66
66
|
Metrics/PerceivedComplexity:
|
67
|
-
Max:
|
67
|
+
Max: 28
|
68
68
|
|
69
69
|
# Offense count: 1
|
70
70
|
# Cop supports --auto-correct.
|
data/.travis.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
language: ruby
|
3
|
+
dist: trusty
|
3
4
|
sudo: false
|
4
|
-
before_install: gem update --system && gem install bundler
|
5
5
|
branches:
|
6
6
|
only:
|
7
7
|
- master
|
@@ -15,10 +15,12 @@ rvm:
|
|
15
15
|
- 1.9.3
|
16
16
|
- 2.0.0
|
17
17
|
- 2.1.10
|
18
|
-
- 2.2.
|
19
|
-
- 2.3.
|
20
|
-
- 2.4.
|
18
|
+
- 2.2.10
|
19
|
+
- 2.3.8
|
20
|
+
- 2.4.7
|
21
|
+
- 2.5.6
|
22
|
+
- 2.6.4
|
21
23
|
matrix:
|
22
24
|
include:
|
23
|
-
- rvm: 2.4
|
25
|
+
- rvm: 2.6.4
|
24
26
|
env: CHECK=rubocop
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,58 @@
|
|
1
1
|
# Change Log
|
2
2
|
|
3
|
+
## [2.4.0](https://github.com/rodjek/puppet-lint/tree/2.4.0) (2019-10-08)
|
4
|
+
[Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.6...2.4.0)
|
5
|
+
|
6
|
+
**Fixed bugs:**
|
7
|
+
|
8
|
+
- Command line options do not override options from config files [\#879](https://github.com/rodjek/puppet-lint/issues/879)
|
9
|
+
- Fix for variables\_not\_enclosed incorrectly handles variables followed by a dash [\#836](https://github.com/rodjek/puppet-lint/issues/836)
|
10
|
+
- Syntax error on Pattern data type [\#833](https://github.com/rodjek/puppet-lint/issues/833)
|
11
|
+
- Error with puppet-lint --fix: NoMethodError: undefined method `next\_token' for nil:NilClass [\#831](https://github.com/rodjek/puppet-lint/issues/831)
|
12
|
+
- TypeError: no implicit conversion of nil into String [\#830](https://github.com/rodjek/puppet-lint/issues/830)
|
13
|
+
- Selector with 'default' case disables check for missing default in outer case statement [\#829](https://github.com/rodjek/puppet-lint/issues/829)
|
14
|
+
- undefined method `next\_token' for nil:NilClass [\#824](https://github.com/rodjek/puppet-lint/issues/824)
|
15
|
+
- NoMethodError: undefined method `next\_token' for nil:NilClass [\#790](https://github.com/rodjek/puppet-lint/issues/790)
|
16
|
+
- Puppet-lint --fix silently removes necessary $ inside double quoted strings [\#773](https://github.com/rodjek/puppet-lint/issues/773)
|
17
|
+
- It looks like puppet-lint has encountered an error that it doesn't know how to handle [\#768](https://github.com/rodjek/puppet-lint/issues/768)
|
18
|
+
- puppet-lint lexer string interpolation needs to be updated to match PUP-5887 changes [\#747](https://github.com/rodjek/puppet-lint/issues/747)
|
19
|
+
- Syntax error causes 'Whoops!' [\#740](https://github.com/rodjek/puppet-lint/issues/740)
|
20
|
+
- "quoted boolean value found" in hash value should not raise a warning. [\#474](https://github.com/rodjek/puppet-lint/issues/474)
|
21
|
+
|
22
|
+
**Closed issues:**
|
23
|
+
|
24
|
+
- Error when running puppet-lint [\#862](https://github.com/rodjek/puppet-lint/issues/862)
|
25
|
+
- puppet-lint crashes with mispelled namespace seperators [\#853](https://github.com/rodjek/puppet-lint/issues/853)
|
26
|
+
- NoMethodError: undefined method `prev\_token' for nil:NilClass [\#845](https://github.com/rodjek/puppet-lint/issues/845)
|
27
|
+
- Lint incorrectly errors on quoted bool [\#844](https://github.com/rodjek/puppet-lint/issues/844)
|
28
|
+
- Type\[\]\] raises NoMethodError [\#843](https://github.com/rodjek/puppet-lint/issues/843)
|
29
|
+
- Whoops! It looks like puppet-lint has encountered an error that it doesn't know how to handle. [\#842](https://github.com/rodjek/puppet-lint/issues/842)
|
30
|
+
- Whoops! It looks like puppet-lint has encountered an error that it doesn't [\#838](https://github.com/rodjek/puppet-lint/issues/838)
|
31
|
+
- Incorrectly wrapped hash variable inside double quotes [\#826](https://github.com/rodjek/puppet-lint/issues/826)
|
32
|
+
- Test puppet-lint against Ruby 2.5.x [\#818](https://github.com/rodjek/puppet-lint/issues/818)
|
33
|
+
- nested ensure misdetected as not coming first. [\#410](https://github.com/rodjek/puppet-lint/issues/410)
|
34
|
+
|
35
|
+
**Merged pull requests:**
|
36
|
+
|
37
|
+
- Handle unenclosed variables followed by dashes when fixing [\#881](https://github.com/rodjek/puppet-lint/pull/881) ([rodjek](https://github.com/rodjek))
|
38
|
+
- Let command line args override config from files [\#880](https://github.com/rodjek/puppet-lint/pull/880) ([usev6](https://github.com/usev6))
|
39
|
+
- Ignore hash keys when checking resource parameter order [\#877](https://github.com/rodjek/puppet-lint/pull/877) ([rodjek](https://github.com/rodjek))
|
40
|
+
- Only look for 'default' at first level of 'case' statement [\#876](https://github.com/rodjek/puppet-lint/pull/876) ([usev6](https://github.com/usev6))
|
41
|
+
- Report syntax error on unbalanced braces [\#875](https://github.com/rodjek/puppet-lint/pull/875) ([rodjek](https://github.com/rodjek))
|
42
|
+
- Include hash/array references when enclosing variables [\#874](https://github.com/rodjek/puppet-lint/pull/874) ([rodjek](https://github.com/rodjek))
|
43
|
+
- Disable quoted\_booleans check by default [\#873](https://github.com/rodjek/puppet-lint/pull/873) ([rodjek](https://github.com/rodjek))
|
44
|
+
- Test against Ruby 2.5 & 2.6 [\#872](https://github.com/rodjek/puppet-lint/pull/872) ([rodjek](https://github.com/rodjek))
|
45
|
+
- README - Add GitHub Actions action [\#868](https://github.com/rodjek/puppet-lint/pull/868) ([ScottBrenner](https://github.com/ScottBrenner))
|
46
|
+
- Update TravisCI config to use trusty image [\#867](https://github.com/rodjek/puppet-lint/pull/867) ([rodjek](https://github.com/rodjek))
|
47
|
+
- Use the default travis rubygems & bundler [\#860](https://github.com/rodjek/puppet-lint/pull/860) ([rodjek](https://github.com/rodjek))
|
48
|
+
- Add `Sensitive` to the list of KNOWN\_TOKEN TYPES [\#858](https://github.com/rodjek/puppet-lint/pull/858) ([alexjfisher](https://github.com/alexjfisher))
|
49
|
+
- Avoid internal error for typoed namespace [\#855](https://github.com/rodjek/puppet-lint/pull/855) ([usev6](https://github.com/usev6))
|
50
|
+
- Use lookahead assertion for matching function name [\#854](https://github.com/rodjek/puppet-lint/pull/854) ([usev6](https://github.com/usev6))
|
51
|
+
- Resource: fix nested ensure error. [\#848](https://github.com/rodjek/puppet-lint/pull/848) ([keur](https://github.com/keur))
|
52
|
+
- Rewrite double quoted string handling for nested interpolation [\#846](https://github.com/rodjek/puppet-lint/pull/846) ([rodjek](https://github.com/rodjek))
|
53
|
+
- Allow for spaces in the heredoc tag [\#841](https://github.com/rodjek/puppet-lint/pull/841) ([jarretlavallee](https://github.com/jarretlavallee))
|
54
|
+
- Recognizes multiline regexes [\#835](https://github.com/rodjek/puppet-lint/pull/835) ([jcbollinger](https://github.com/jcbollinger))
|
55
|
+
|
3
56
|
## [2.3.6](https://github.com/rodjek/puppet-lint/tree/2.3.6) (2018-07-09)
|
4
57
|
[Full Changelog](https://github.com/rodjek/puppet-lint/compare/2.3.5...2.3.6)
|
5
58
|
|
data/README.md
CHANGED
@@ -120,6 +120,18 @@ Or to specify a whitelist of allowed checks, include a line like:
|
|
120
120
|
--only-checks=trailing_whitespace,hard_tabs,duplicate_params,double_quoted_strings,unquoted_file_mode,only_variable_string,variables_not_enclosed,single_quote_string_with_variables,variable_contains_dash,ensure_not_symlink_target,unquoted_resource_title,relative_classname_inclusion,file_mode,resource_reference_without_title_capital,leading_zero,arrow_alignment,variable_is_lowercase,ensure_first_param,resource_reference_without_whitespace,file_ensure,trailing_comma,leading_zero
|
121
121
|
```
|
122
122
|
|
123
|
+
Please note that there is an important difference between reading options from the command line and reading options from a configuration file: In the former case the shell interprets one level of quotes. That does not happen in the latter case. So, it would make sense to quote some configuration values on the command line, like so:
|
124
|
+
|
125
|
+
```
|
126
|
+
$ puppet-lint --ignore-paths 'modules/stdlib/*' modules/
|
127
|
+
```
|
128
|
+
|
129
|
+
When reading from a configuration file those quotes would be passed on to the option parser -- probably not giving the expected result. Instead the line should read
|
130
|
+
|
131
|
+
```
|
132
|
+
--ignore-paths=modules/stdlib/*
|
133
|
+
```
|
134
|
+
|
123
135
|
## Testing with Puppet Lint as a Rake task
|
124
136
|
|
125
137
|
To test your entire Puppet manifest directory, add `require 'puppet-lint/tasks/puppet-lint'` to your Rakefile and then run:
|
@@ -195,6 +207,12 @@ You can also disable checks when running Puppet Lint through the supplied Rake t
|
|
195
207
|
PuppetLint.configuration.pattern = "modules"
|
196
208
|
```
|
197
209
|
|
210
|
+
## Testing with Puppet Lint as a GitHub Action
|
211
|
+
|
212
|
+
There is a GitHub Actions action available to get linter feedback in workflows:
|
213
|
+
|
214
|
+
* [puppet-lint-action](https://github.com/marketplace/actions/puppet-lint-action)
|
215
|
+
|
198
216
|
## Options
|
199
217
|
|
200
218
|
See `puppet-lint --help` for a full list of command line options and checks.
|
data/appveyor.yml
CHANGED
data/lib/puppet-lint/data.rb
CHANGED
@@ -201,6 +201,9 @@ class PuppetLint::Data
|
|
201
201
|
lbrace_idx = tokens[0..index].rindex do |token|
|
202
202
|
token.type == :LBRACE && token.prev_code_token.type != :QMARK
|
203
203
|
end
|
204
|
+
|
205
|
+
raise PuppetLint::SyntaxError, tokens[index] if lbrace_idx.nil?
|
206
|
+
|
204
207
|
tokens[lbrace_idx].prev_code_token
|
205
208
|
end
|
206
209
|
|
@@ -212,9 +215,21 @@ class PuppetLint::Data
|
|
212
215
|
#
|
213
216
|
# Returns an Array of Token objects.
|
214
217
|
def find_resource_param_tokens(resource_tokens)
|
215
|
-
|
216
|
-
|
218
|
+
param_tokens = []
|
219
|
+
|
220
|
+
iter_token = resource_tokens.first.prev_token
|
221
|
+
|
222
|
+
until iter_token.nil?
|
223
|
+
iter_token = iter_token.next_token_of(:NAME)
|
224
|
+
|
225
|
+
break unless resource_tokens.include?(iter_token)
|
226
|
+
|
227
|
+
if iter_token && iter_token.next_code_token.type == :FARROW
|
228
|
+
param_tokens << iter_token
|
229
|
+
end
|
217
230
|
end
|
231
|
+
|
232
|
+
param_tokens
|
218
233
|
end
|
219
234
|
|
220
235
|
# Internal: Calculate the positions of all class definitions within the
|
data/lib/puppet-lint/lexer.rb
CHANGED
@@ -2,8 +2,9 @@
|
|
2
2
|
|
3
3
|
require 'pp'
|
4
4
|
require 'strscan'
|
5
|
-
require 'puppet-lint/lexer/token'
|
6
5
|
require 'set'
|
6
|
+
require 'puppet-lint/lexer/token'
|
7
|
+
require 'puppet-lint/lexer/string_slurper'
|
7
8
|
|
8
9
|
class PuppetLint
|
9
10
|
# Internal: A generic error thrown by the lexer when it encounters something
|
@@ -28,11 +29,15 @@ class PuppetLint
|
|
28
29
|
@column = column
|
29
30
|
@reason = reason
|
30
31
|
end
|
32
|
+
|
33
|
+
def to_s
|
34
|
+
"PuppetLint::LexerError: Line:#{line_no} Column: #{column} Reason: #{reason}"
|
35
|
+
end
|
31
36
|
end
|
32
37
|
|
33
38
|
# Internal: The puppet-lint lexer. Converts your manifest into its tokenised
|
34
39
|
# form.
|
35
|
-
class Lexer
|
40
|
+
class Lexer
|
36
41
|
def initialize
|
37
42
|
@line_no = 1
|
38
43
|
@column = 1
|
@@ -101,16 +106,27 @@ class PuppetLint
|
|
101
106
|
:LPAREN => true,
|
102
107
|
}.freeze
|
103
108
|
|
109
|
+
# Internal: some commonly used regular expressions
|
110
|
+
# \t == tab
|
111
|
+
# \v == vertical tab
|
112
|
+
# \f == form feed
|
113
|
+
# \p{Zs} == ASCII + Unicode non-linebreaking whitespace
|
114
|
+
WHITESPACE_RE = RUBY_VERSION == '1.8.7' ? %r{[\t\v\f ]} : %r{[\t\v\f\p{Zs}]}
|
115
|
+
|
116
|
+
LINE_END_RE = %r{(?:\r\n|\r|\n)}
|
117
|
+
|
118
|
+
NAME_RE = %r{\A((?:(?:::)?[_a-z0-9][-\w]*)(?:::[a-z0-9][-\w]*)*)}
|
119
|
+
|
104
120
|
# Internal: An Array of Arrays containing tokens that can be described by
|
105
121
|
# a single regular expression. Each sub-Array contains 2 elements, the
|
106
122
|
# name of the token as a Symbol and a regular expression describing the
|
107
123
|
# value of the token.
|
108
|
-
NAME_RE = %r{\A(((::)?[_a-z0-9][-\w]*)(::[a-z0-9][-\w]*)*)}
|
109
124
|
KNOWN_TOKENS = [
|
110
|
-
[:
|
125
|
+
[:WHITESPACE, %r{\A(#{WHITESPACE_RE}+)}],
|
126
|
+
[:TYPE, %r{\A(Integer|Float|Boolean|Regexp|String|Array|Hash|Resource|Class|Collection|Scalar|Numeric|CatalogEntry|Data|Tuple|Struct|Optional|NotUndef|Variant|Enum|Pattern|Any|Callable|Type|Runtime|Undef|Default|Sensitive)\b}], # rubocop:disable Metrics/LineLength
|
111
127
|
[:CLASSREF, %r{\A(((::){0,1}[A-Z][-\w]*)+)}],
|
112
128
|
[:NUMBER, %r{\A\b((?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?))\b}],
|
113
|
-
[:FUNCTION_NAME, %r{#{NAME_RE}
|
129
|
+
[:FUNCTION_NAME, %r{#{NAME_RE}(?=\()}],
|
114
130
|
[:NAME, NAME_RE],
|
115
131
|
[:LBRACK, %r{\A(\[)}],
|
116
132
|
[:RBRACK, %r{\A(\])}],
|
@@ -166,14 +182,6 @@ class PuppetLint
|
|
166
182
|
:INDENT => true,
|
167
183
|
}.freeze
|
168
184
|
|
169
|
-
# \t == tab
|
170
|
-
# \v == vertical tab
|
171
|
-
# \f == form feed
|
172
|
-
# \p{Zs} == ASCII + Unicode non-linebreaking whitespace
|
173
|
-
WHITESPACE_RE = RUBY_VERSION == '1.8.7' ? %r{[\t\v\f ]} : %r{[\t\v\f\p{Zs}]}
|
174
|
-
|
175
|
-
LINE_END_RE = %r{(?:\r\n|\r|\n)}
|
176
|
-
|
177
185
|
# Internal: Access the internal token storage.
|
178
186
|
#
|
179
187
|
# Returns an Array of PuppetLint::Lexer::Toxen objects.
|
@@ -200,13 +208,12 @@ class PuppetLint
|
|
200
208
|
value = chunk[regex, 1]
|
201
209
|
next if value.nil?
|
202
210
|
|
203
|
-
|
211
|
+
i += value.size
|
204
212
|
tokens << if type == :NAME && KEYWORDS.include?(value)
|
205
213
|
new_token(value.upcase.to_sym, value)
|
206
214
|
else
|
207
215
|
new_token(type, value)
|
208
216
|
end
|
209
|
-
i += length
|
210
217
|
found = true
|
211
218
|
break
|
212
219
|
end
|
@@ -215,7 +222,12 @@ class PuppetLint
|
|
215
222
|
|
216
223
|
if var_name = chunk[%r{\A\$((::)?(\w+(-\w+)*::)*\w+(-\w+)*(\[.+?\])*)}, 1]
|
217
224
|
length = var_name.size + 1
|
218
|
-
|
225
|
+
opts = if chunk.start_with?('$')
|
226
|
+
{ :raw => "$#{var_name}" }
|
227
|
+
else
|
228
|
+
{}
|
229
|
+
end
|
230
|
+
tokens << new_token(:VARIABLE, var_name, opts)
|
219
231
|
|
220
232
|
elsif chunk =~ %r{\A'.*?'}m
|
221
233
|
str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*'}m)
|
@@ -223,12 +235,16 @@ class PuppetLint
|
|
223
235
|
tokens << new_token(:SSTRING, str_content[0..-2])
|
224
236
|
|
225
237
|
elsif chunk.start_with?('"')
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
238
|
+
slurper = PuppetLint::Lexer::StringSlurper.new(code[i + 1..-1])
|
239
|
+
begin
|
240
|
+
string_segments = slurper.parse
|
241
|
+
process_string_segments(string_segments)
|
242
|
+
length = slurper.consumed_bytes + 1
|
243
|
+
rescue PuppetLint::Lexer::StringSlurper::UnterminatedStringError
|
244
|
+
raise PuppetLint::LexerError, @line_no, @column, 'unterminated string'
|
245
|
+
end
|
230
246
|
|
231
|
-
elsif heredoc_name = chunk[%r{\A@\(("?.+?"?(:.+?)
|
247
|
+
elsif heredoc_name = chunk[%r{\A@\(("?.+?"?(:.+?)?#{WHITESPACE_RE}*(/.*?)?)\)}, 1]
|
232
248
|
heredoc_queue << heredoc_name
|
233
249
|
tokens << new_token(:HEREDOC_OPEN, heredoc_name)
|
234
250
|
length = heredoc_name.size + 3
|
@@ -251,7 +267,7 @@ class PuppetLint
|
|
251
267
|
mlcomment.gsub!(%r{^ *\*}, '')
|
252
268
|
tokens << new_token(:MLCOMMENT, mlcomment, :raw => mlcomment_raw)
|
253
269
|
|
254
|
-
elsif chunk.match(%r{\A/.*?/}) && possible_regex?
|
270
|
+
elsif chunk.match(%r{\A/.*?/}m) && possible_regex?
|
255
271
|
str_content = StringScanner.new(code[i + 1..-1]).scan_until(%r{(\A|[^\\])(\\\\)*/}m)
|
256
272
|
length = str_content.size + 1
|
257
273
|
tokens << new_token(:REGEX, str_content[0..-2])
|
@@ -267,29 +283,16 @@ class PuppetLint
|
|
267
283
|
length += indent.size
|
268
284
|
else
|
269
285
|
heredoc_tag = heredoc_queue.shift
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
length +=
|
286
|
+
slurper = PuppetLint::Lexer::StringSlurper.new(code[i + length..-1])
|
287
|
+
heredoc_segments = slurper.parse_heredoc(heredoc_tag)
|
288
|
+
process_heredoc_segments(heredoc_segments)
|
289
|
+
length += slurper.consumed_bytes
|
274
290
|
end
|
275
291
|
|
276
|
-
elsif whitespace = chunk[%r{\A(#{WHITESPACE_RE}+)}, 1]
|
277
|
-
length = whitespace.size
|
278
|
-
tokens << new_token(:WHITESPACE, whitespace)
|
279
|
-
|
280
292
|
elsif eol = chunk[%r{\A(#{LINE_END_RE})}, 1]
|
281
293
|
length = eol.size
|
282
294
|
tokens << new_token(:NEWLINE, eol)
|
283
295
|
|
284
|
-
unless heredoc_queue.empty?
|
285
|
-
heredoc_tag = heredoc_queue.shift
|
286
|
-
heredoc_name = heredoc_tag[%r{\A"?(.+?)"?(:.+?)?(/.*)?\Z}, 1]
|
287
|
-
str_contents = StringScanner.new(code[(i + length)..-1]).scan_until(%r{\|?\s*-?\s*#{heredoc_name}})
|
288
|
-
_ = code[0..(i + length)].split(LINE_END_RE)
|
289
|
-
interpolate_heredoc(str_contents, heredoc_tag)
|
290
|
-
length += str_contents.size
|
291
|
-
end
|
292
|
-
|
293
296
|
elsif chunk.start_with?('/')
|
294
297
|
length = 1
|
295
298
|
tokens << new_token(:DIV, '/')
|
@@ -308,22 +311,6 @@ class PuppetLint
|
|
308
311
|
tokens
|
309
312
|
end
|
310
313
|
|
311
|
-
def slurp_string(string)
|
312
|
-
dq_str_regexp = %r{(\$\{|(\A|[^\\])(\\\\)*")}m
|
313
|
-
scanner = StringScanner.new(string)
|
314
|
-
contents = scanner.scan_until(dq_str_regexp)
|
315
|
-
|
316
|
-
if scanner.matched.nil?
|
317
|
-
raise LexerError.new(@line_no, @column, 'Double quoted string missing closing quote')
|
318
|
-
end
|
319
|
-
|
320
|
-
until scanner.matched.end_with?('"')
|
321
|
-
contents += scanner.scan_until(%r{\}}m)
|
322
|
-
contents += scanner.scan_until(dq_str_regexp)
|
323
|
-
end
|
324
|
-
contents
|
325
|
-
end
|
326
|
-
|
327
314
|
# Internal: Given the tokens already processed, determine if the next token
|
328
315
|
# could be a regular expression.
|
329
316
|
#
|
@@ -403,167 +390,66 @@ class PuppetLint
|
|
403
390
|
token
|
404
391
|
end
|
405
392
|
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
#
|
413
|
-
# Returns an Array consisting of two Strings, the String up to the first
|
414
|
-
# terminator and the terminator that was found.
|
415
|
-
def get_string_segment(string, terminators)
|
416
|
-
str = string.scan_until(%r{([^\\]|^|[^\\])([\\]{2})*[#{terminators}]+})
|
417
|
-
begin
|
418
|
-
[str[0..-2], str[-1, 1]]
|
419
|
-
rescue
|
420
|
-
[nil, nil]
|
393
|
+
def process_string_segments(segments)
|
394
|
+
return if segments.empty?
|
395
|
+
|
396
|
+
if segments.length == 1
|
397
|
+
tokens << new_token(:STRING, segments[0][1])
|
398
|
+
return
|
421
399
|
end
|
422
|
-
end
|
423
400
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
if terminator == '"'
|
437
|
-
if first
|
438
|
-
tokens << new_token(:STRING, value, :line => line, :column => column)
|
439
|
-
first = false
|
440
|
-
else
|
441
|
-
token_column = column + (ss.pos - value.size)
|
442
|
-
tokens << new_token(:DQPOST, value, :line => line, :column => token_column)
|
443
|
-
line += value.scan(LINE_END_RE).size
|
444
|
-
@column = column + ss.pos + 1
|
445
|
-
@line_no = line
|
401
|
+
pre_segment = segments.delete_at(0)
|
402
|
+
post_segment = segments.delete_at(-1)
|
403
|
+
|
404
|
+
tokens << new_token(:DQPRE, pre_segment[1])
|
405
|
+
segments.each do |segment|
|
406
|
+
case segment[0]
|
407
|
+
when :INTERP
|
408
|
+
lexer = PuppetLint::Lexer.new
|
409
|
+
lexer.tokenise(segment[1])
|
410
|
+
lexer.tokens.each_with_index do |t, i|
|
411
|
+
type = i.zero? && t.type == :NAME ? :VARIABLE : t.type
|
412
|
+
tokens << new_token(type, t.value, :raw => t.raw)
|
446
413
|
end
|
414
|
+
when :UNENC_VAR
|
415
|
+
tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, ''))
|
447
416
|
else
|
448
|
-
|
449
|
-
tokens << new_token(:DQPRE, value, :line => line, :column => column)
|
450
|
-
first = false
|
451
|
-
else
|
452
|
-
token_column = column + (ss.pos - value.size)
|
453
|
-
tokens << new_token(:DQMID, value, :line => line, :column => token_column)
|
454
|
-
line += value.scan(LINE_END_RE).size
|
455
|
-
end
|
456
|
-
if ss.scan(%r{\{}).nil?
|
457
|
-
var_name = ss.scan(%r{(::)?(\w+(-\w+)*::)*\w+(-\w+)*})
|
458
|
-
if var_name.nil?
|
459
|
-
token_column = column + ss.pos - 1
|
460
|
-
tokens << new_token(:DQMID, '$', :line => line, :column => token_column)
|
461
|
-
else
|
462
|
-
token_column = column + (ss.pos - var_name.size)
|
463
|
-
tokens << new_token(:UNENC_VARIABLE, var_name, :line => line, :column => token_column)
|
464
|
-
end
|
465
|
-
else
|
466
|
-
line += value.scan(LINE_END_RE).size
|
467
|
-
contents = ss.scan_until(%r{\}})[0..-2]
|
468
|
-
raw = contents.dup
|
469
|
-
if contents.match(%r{\A(::)?([\w-]+::)*[\w-]+(\[.+?\])*}) && !contents.match(%r{\A\w+\(})
|
470
|
-
contents = "$#{contents}"
|
471
|
-
end
|
472
|
-
lexer = PuppetLint::Lexer.new
|
473
|
-
lexer.tokenise(contents)
|
474
|
-
lexer.tokens.each do |token|
|
475
|
-
tok_col = column + token.column + (ss.pos - contents.size - 1)
|
476
|
-
tok_line = token.line + line - 1
|
477
|
-
tokens << new_token(token.type, token.value, :line => tok_line, :column => tok_col)
|
478
|
-
end
|
479
|
-
if lexer.tokens.length == 1 && lexer.tokens[0].type == :VARIABLE
|
480
|
-
tokens.last.raw = raw
|
481
|
-
end
|
482
|
-
end
|
417
|
+
tokens << new_token(:DQMID, segment[1])
|
483
418
|
end
|
484
|
-
value, terminator = get_string_segment(ss, '"$')
|
485
419
|
end
|
420
|
+
tokens << new_token(:DQPOST, post_segment[1])
|
486
421
|
end
|
487
422
|
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
423
|
+
def process_heredoc_segments(segments)
|
424
|
+
return if segments.empty?
|
425
|
+
|
426
|
+
end_tag = segments.delete_at(-1)
|
427
|
+
|
428
|
+
if segments.length == 1
|
429
|
+
tokens << new_token(:HEREDOC, segments[0][1], :raw => "#{segments[0][1]}#{end_tag[1]}")
|
430
|
+
return
|
431
|
+
end
|
432
|
+
|
433
|
+
pre_segment = segments.delete_at(0)
|
434
|
+
post_segment = segments.delete_at(-1)
|
435
|
+
|
436
|
+
tokens << new_token(:HEREDOC_PRE, pre_segment[1])
|
437
|
+
segments.each do |segment|
|
438
|
+
case segment[0]
|
439
|
+
when :INTERP
|
440
|
+
lexer = PuppetLint::Lexer.new
|
441
|
+
lexer.tokenise(segment[1])
|
442
|
+
lexer.tokens.each_with_index do |t, i|
|
443
|
+
type = i.zero? && t.type == :NAME ? :VARIABLE : t.type
|
444
|
+
tokens << new_token(type, t.value, :raw => t.raw)
|
507
445
|
end
|
446
|
+
when :UNENC_VAR
|
447
|
+
tokens << new_token(:UNENC_VARIABLE, segment[1].gsub(%r{\A\$}, ''))
|
508
448
|
else
|
509
|
-
|
510
|
-
tokens << new_token(:HEREDOC_PRE, value)
|
511
|
-
first = false
|
512
|
-
else
|
513
|
-
tokens << new_token(:HEREDOC_MID, value)
|
514
|
-
end
|
515
|
-
if ss.scan(%r{\{}).nil?
|
516
|
-
var_name = ss.scan(%r{(::)?(\w+(-\w+)*::)*\w+(-\w+)*})
|
517
|
-
tokens << if var_name.nil?
|
518
|
-
new_token(:HEREDOC_MID, '$')
|
519
|
-
else
|
520
|
-
new_token(:UNENC_VARIABLE, var_name)
|
521
|
-
end
|
522
|
-
else
|
523
|
-
contents = ss.scan_until(%r{\}})[0..-2]
|
524
|
-
raw = contents.dup
|
525
|
-
if contents.match(%r{\A(::)?([\w-]+::)*[\w-]|(\[.+?\])*}) && !contents.match(%r{\A\w+\(})
|
526
|
-
contents = "$#{contents}" unless contents.start_with?('$')
|
527
|
-
end
|
528
|
-
|
529
|
-
lexer = PuppetLint::Lexer.new
|
530
|
-
lexer.tokenise(contents)
|
531
|
-
lexer.tokens.each do |token|
|
532
|
-
tokens << new_token(token.type, token.value)
|
533
|
-
end
|
534
|
-
if lexer.tokens.length == 1 && lexer.tokens[0].type == :VARIABLE
|
535
|
-
tokens.last.raw = raw
|
536
|
-
end
|
537
|
-
end
|
449
|
+
tokens << new_token(:HEREDOC_MID, segment[1])
|
538
450
|
end
|
539
|
-
value, terminator = get_heredoc_segment(ss, eos_text, interpolate)
|
540
|
-
end
|
541
|
-
end
|
542
|
-
|
543
|
-
# Internal: Splits a heredoc String into segments if it is to be
|
544
|
-
# interpolated.
|
545
|
-
#
|
546
|
-
# string - The String heredoc.
|
547
|
-
# eos_text - The String endtext for the heredoc.
|
548
|
-
# interpolate - A Boolean that specifies whether this heredoc can contain
|
549
|
-
# interpolated values (defaults to True).
|
550
|
-
#
|
551
|
-
# Returns an Array consisting of two Strings, the String up to the first
|
552
|
-
# terminator and the terminator that was found.
|
553
|
-
def get_heredoc_segment(string, eos_text, interpolate = true)
|
554
|
-
regexp = if interpolate
|
555
|
-
%r{(([^\\]|^|[^\\])([\\]{2})*[$]+|\|?\s*-?#{Regexp.escape(eos_text)})}
|
556
|
-
else
|
557
|
-
%r{\|?\s*-?#{Regexp.escape(eos_text)}}
|
558
|
-
end
|
559
|
-
|
560
|
-
str = string.scan_until(regexp)
|
561
|
-
begin
|
562
|
-
str =~ %r{\A(.*?)([$]+|\|?\s*-?#{Regexp.escape(eos_text)})\Z}m
|
563
|
-
[Regexp.last_match(1), Regexp.last_match(2)]
|
564
|
-
rescue
|
565
|
-
[nil, nil]
|
566
451
|
end
|
452
|
+
tokens << new_token(:HEREDOC_POST, post_segment[1], :raw => "#{post_segment[1]}#{end_tag[1]}")
|
567
453
|
end
|
568
454
|
end
|
569
455
|
end
|