puppet-lint 0.1.13 → 0.2.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +5 -0
- data/README.md +19 -5
- data/bin/puppet-lint +2 -0
- data/lib/puppet-lint.rb +2 -11
- data/lib/puppet-lint/configuration.rb +4 -0
- data/lib/puppet-lint/lexer.rb +244 -0
- data/lib/puppet-lint/plugin.rb +125 -54
- data/lib/puppet-lint/plugins/check_classes.rb +135 -49
- data/lib/puppet-lint/plugins/check_conditionals.rb +34 -23
- data/lib/puppet-lint/plugins/check_resources.rb +114 -28
- data/lib/puppet-lint/plugins/check_strings.rb +67 -79
- data/lib/puppet-lint/plugins/check_variables.rb +13 -18
- data/lib/puppet-lint/plugins/check_whitespace.rb +70 -40
- data/lib/puppet-lint/tasks/puppet-lint.rb +11 -3
- data/lib/puppet-lint/version.rb +3 -0
- data/puppet-lint.gemspec +8 -29
- data/spec/puppet-lint/check_classes_spec.rb +72 -23
- data/spec/puppet-lint/check_conditionals_spec.rb +19 -3
- data/spec/puppet-lint/check_resources_spec.rb +9 -16
- data/spec/puppet-lint/check_strings_spec.rb +94 -7
- data/spec/puppet-lint/check_variables_spec.rb +20 -10
- data/spec/puppet-lint/check_whitespace_spec.rb +13 -0
- data/spec/spec_helper.rb +15 -10
- metadata +30 -17
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -112,7 +112,7 @@ ERROR: mymodule::myclass not in autoload module layout on line X
|
|
112
112
|
|
113
113
|
Puppet attempts to autoload only the required manifests for the resources and
|
114
114
|
classes specified in your manifests. In order to do this, the autoloader
|
115
|
-
expects your manifests to be
|
115
|
+
expects your manifests to be laid out on disk in a particular format. For
|
116
116
|
example, when you use `mymodule::myclass` in your manifests, Puppet will
|
117
117
|
attempt to read `<modulepath>/mymodule/manifests/myclass.pp`. The only
|
118
118
|
exception to this is when you reference `mymodule` itself (without any
|
@@ -230,11 +230,11 @@ Placeholder
|
|
230
230
|
### puppet-lint
|
231
231
|
|
232
232
|
You can disable any of the checks when running the `puppet-lint` command by
|
233
|
-
adding a `--
|
233
|
+
adding a `--no-<check name>-check` flag to the command. For example, if you
|
234
234
|
wanted to skip the 80 character check, you would run
|
235
235
|
|
236
236
|
```
|
237
|
-
puppet-lint --
|
237
|
+
puppet-lint --no-80chars-check /path/to/my/manifest.pp
|
238
238
|
```
|
239
239
|
|
240
240
|
puppet-lint will also check for a `.puppet-lintrc` file in the current
|
@@ -243,9 +243,16 @@ wanted to always skip the hard tab character check, you could create
|
|
243
243
|
`~./puppet-lintrc` containing
|
244
244
|
|
245
245
|
```
|
246
|
-
--
|
246
|
+
--no-hard_tabs-check
|
247
247
|
```
|
248
248
|
|
249
|
+
For a list of all the flags just type:
|
250
|
+
|
251
|
+
```
|
252
|
+
puppet-lint --help
|
253
|
+
```
|
254
|
+
|
255
|
+
|
249
256
|
### Rake task
|
250
257
|
|
251
258
|
You can also disable checks when running puppet-lint through the supplied Rake
|
@@ -253,7 +260,7 @@ task. Simply add the following line after the `require` statement in your
|
|
253
260
|
`Rakefile`.
|
254
261
|
|
255
262
|
``` ruby
|
256
|
-
PuppetLint.configuration.send("disable_<check name")
|
263
|
+
PuppetLint.configuration.send("disable_<check name>")
|
257
264
|
```
|
258
265
|
|
259
266
|
So, to disable the 80 character check, you would add:
|
@@ -262,6 +269,13 @@ So, to disable the 80 character check, you would add:
|
|
262
269
|
PuppetLint.configuration.send("disable_80chars")
|
263
270
|
```
|
264
271
|
|
272
|
+
The Rake task also supports ignoring certain paths
|
273
|
+
from being linted:
|
274
|
+
|
275
|
+
``` ruby
|
276
|
+
PuppetLint.configuration.ignore_paths = ["vendor/**/*.pp"]
|
277
|
+
```
|
278
|
+
|
265
279
|
## Reporting bugs or incorrect results
|
266
280
|
|
267
281
|
If you find a bug in puppet-lint or its results, please create an issue in the
|
data/bin/puppet-lint
CHANGED
data/lib/puppet-lint.rb
CHANGED
@@ -1,12 +1,5 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
begin
|
4
|
-
require 'puppet'
|
5
|
-
rescue LoadError
|
6
|
-
puts 'Unable to require puppet. Please gem install puppet and try again.'
|
7
|
-
exit 1
|
8
|
-
end
|
9
|
-
|
1
|
+
require 'puppet-lint/version'
|
2
|
+
require 'puppet-lint/lexer'
|
10
3
|
require 'puppet-lint/configuration'
|
11
4
|
require 'puppet-lint/plugin'
|
12
5
|
|
@@ -74,8 +67,6 @@ end
|
|
74
67
|
class PuppetLint::NoCodeError < StandardError; end
|
75
68
|
|
76
69
|
class PuppetLint
|
77
|
-
VERSION = '0.1.12'
|
78
|
-
|
79
70
|
attr_reader :code, :file
|
80
71
|
|
81
72
|
def initialize
|
@@ -0,0 +1,244 @@
|
|
1
|
+
require 'pp'
|
2
|
+
require 'strscan'
|
3
|
+
|
4
|
+
class PuppetLint
|
5
|
+
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
|
+
]
|
25
|
+
|
26
|
+
KNOWN_TOKENS = [
|
27
|
+
[:CLASSREF, /\A(((::){0,1}[A-Z][-\w]*)+)/],
|
28
|
+
[:NUMBER, /\A(?:0[xX][0-9A-Fa-f]+|0?\d+(?:\.\d+)?(?:[eE]-?\d+)?)\b/],
|
29
|
+
[:NAME, /\A(((::)?[a-z0-9][-\w]*)(::[a-z0-9][-\w]*)*)/],
|
30
|
+
[:LBRACK, /\A(\[)/],
|
31
|
+
[:RBRACK, /\A(\])/],
|
32
|
+
[:LBRACE, /\A(\{)/],
|
33
|
+
[:RBRACE, /\A(\})/],
|
34
|
+
[:LPAREN, /\A(\()/],
|
35
|
+
[:RPAREN, /\A(\))/],
|
36
|
+
[:ISEQUAL, /\A(==)/],
|
37
|
+
[:MATCH, /\A(=~)/],
|
38
|
+
[:FARROW, /\A(=>)/],
|
39
|
+
[:EQUALS, /\A(=)/],
|
40
|
+
[:APPENDS, /\A(\+=)/],
|
41
|
+
[:PARROW, /\A(\+>)/],
|
42
|
+
[:PLUS, /\A(\+)/],
|
43
|
+
[:GREATEREQUAL, /\A(>=)/],
|
44
|
+
[:RSHIFT, /\A(>>)/],
|
45
|
+
[:GREATERTHAN, /\A(>)/],
|
46
|
+
[:LESSEQUAL, /\A(<=)/],
|
47
|
+
[:LLCOLLECT, /\A(<<\|)/],
|
48
|
+
[:OUT_EDGE, /\A(<-)/],
|
49
|
+
[:OUT_EDGE_SUB, /\A(<~)/],
|
50
|
+
[:LCOLLECT, /\A(<\|)/],
|
51
|
+
[:LSHIFT, /\A(<<)/],
|
52
|
+
[:LESSTHAN, /\A(<)/],
|
53
|
+
[:NOMATCH, /\A(!~)/],
|
54
|
+
[:NOTEQUAL, /\A(!=)/],
|
55
|
+
[:NOT, /\A(!)/],
|
56
|
+
[:RRCOLLECT, /\A(\|>>)/],
|
57
|
+
[:RCOLLECT, /\A(\|>)/],
|
58
|
+
[:IN_EDGE, /\A(->)/],
|
59
|
+
[:IN_EDGE_SUB, /\A(~>)/],
|
60
|
+
[:MINUS, /\A(-)/],
|
61
|
+
[:COMMA, /\A(,)/],
|
62
|
+
[:DOT, /\A(\.)/],
|
63
|
+
[:COLON, /\A(:)/],
|
64
|
+
[:AT, /\A(@)/],
|
65
|
+
[:SEMIC, /\A(;)/],
|
66
|
+
[:QMARK, /\A(\?)/],
|
67
|
+
[:BACKSLASH, /\A(\\)/],
|
68
|
+
[:DIV, /\A(\/)/],
|
69
|
+
[:TIMES, /\A(\*)/],
|
70
|
+
]
|
71
|
+
|
72
|
+
def tokens
|
73
|
+
@tokens ||= []
|
74
|
+
end
|
75
|
+
|
76
|
+
def tokenise(code)
|
77
|
+
code.chomp!
|
78
|
+
|
79
|
+
i = 0
|
80
|
+
|
81
|
+
while i < code.size
|
82
|
+
chunk = code[i..-1]
|
83
|
+
|
84
|
+
found = false
|
85
|
+
|
86
|
+
KNOWN_TOKENS.each do |type, regex|
|
87
|
+
if value = chunk[regex, 1]
|
88
|
+
if type == :NAME
|
89
|
+
if KEYWORDS.include? value
|
90
|
+
tokens << new_token(value.upcase.to_sym, value, code[0..i])
|
91
|
+
else
|
92
|
+
tokens << new_token(type, value, code[0..i])
|
93
|
+
end
|
94
|
+
else
|
95
|
+
tokens << new_token(type, value, code[0..i])
|
96
|
+
end
|
97
|
+
i += value.size
|
98
|
+
found = true
|
99
|
+
break
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
unless found
|
104
|
+
if identifier = chunk[/\A([a-z]\w*)/, 1]
|
105
|
+
tokens << new_token(:IDENTIFIER, identifier, code[0..i])
|
106
|
+
i += identifier.size
|
107
|
+
|
108
|
+
elsif var_name = chunk[/\A\$((::)?([\w-]+::)*[\w-]+)/, 1]
|
109
|
+
tokens << new_token(:VARIABLE, var_name, code[0..i])
|
110
|
+
i += var_name.size + 1
|
111
|
+
|
112
|
+
elsif sstring = chunk[/\A'(.*?)'/, 1]
|
113
|
+
tokens << new_token(:SSTRING, sstring, code[0..i])
|
114
|
+
i += sstring.size + 2
|
115
|
+
|
116
|
+
elsif chunk.match(/\A"/)
|
117
|
+
str_contents = StringScanner.new(code[i+1..-1]).scan_until(/[^\\]"/m)
|
118
|
+
_ = code[0..i].split("\n")
|
119
|
+
interpolate_string(str_contents, _.count, _.last.length)
|
120
|
+
i += str_contents.size + 1
|
121
|
+
|
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
|
+
elsif comment = chunk[/\A(#.*)/, 1]
|
128
|
+
comment_size = comment.size
|
129
|
+
comment.sub!(/# ?/, '')
|
130
|
+
tokens << new_token(:COMMENT, comment, code[0..i])
|
131
|
+
i += comment_size
|
132
|
+
|
133
|
+
elsif slash_comment = chunk[/\A(\/\/.*)/, 1]
|
134
|
+
slash_comment_size = slash_comment.size
|
135
|
+
slash_comment.sub!(/\/\/ ?/, '')
|
136
|
+
tokens << new_token(:SLASH_COMMENT, slash_comment, code[0..i])
|
137
|
+
i += slash_comment_size
|
138
|
+
|
139
|
+
elsif mlcomment = chunk[/\A(\/\*.*?\*\/)/m, 1]
|
140
|
+
mlcomment_size = mlcomment_size
|
141
|
+
mlcomment.sub!(/^\/\* ?/, '')
|
142
|
+
mlcomment.sub!(/ ?\*\/$/, '')
|
143
|
+
tokens << new_token(:MLCOMMENT, mlcomment, code[0..i])
|
144
|
+
i += mlcomment_size
|
145
|
+
|
146
|
+
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])
|
149
|
+
i += indent.size + 1
|
150
|
+
|
151
|
+
elsif whitespace = chunk[/\A([ \t]+)/, 1]
|
152
|
+
tokens << new_token(:WHITESPACE, whitespace, code[0..i])
|
153
|
+
i += whitespace.size
|
154
|
+
|
155
|
+
elsif chunk.match(/\A\n/)
|
156
|
+
tokens << new_token(:NEWLINE, '\n', code[0..i])
|
157
|
+
i += 1
|
158
|
+
|
159
|
+
else
|
160
|
+
value = chunk[0,1]
|
161
|
+
tokens << new_token(value, value, code[0..i])
|
162
|
+
i += 1
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
tokens
|
168
|
+
end
|
169
|
+
|
170
|
+
def new_token(type, value, chunk)
|
171
|
+
lines = chunk.split("\n")
|
172
|
+
line_no = lines.empty? ? 1 : lines.count
|
173
|
+
column = lines.empty? ? 1 : lines.last.length
|
174
|
+
|
175
|
+
PuppetLint::Token.new(type, value, line_no, column)
|
176
|
+
end
|
177
|
+
|
178
|
+
def get_string_segment(string, terminators)
|
179
|
+
str = string.scan_until(/([^\\]|^|[^\\])([\\]{2})*[#{terminators}]/)
|
180
|
+
begin
|
181
|
+
[str[0..-2], str[-1,1]]
|
182
|
+
rescue
|
183
|
+
[nil, nil]
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
def interpolate_string(string, line, column)
|
188
|
+
ss = StringScanner.new(string)
|
189
|
+
first = true
|
190
|
+
value, terminator = get_string_segment(ss, '"$')
|
191
|
+
until value.nil?
|
192
|
+
if terminator == "\""
|
193
|
+
if first
|
194
|
+
tokens << PuppetLint::Token.new(:STRING, value, line, column)
|
195
|
+
first = false
|
196
|
+
else
|
197
|
+
line += value.count("\n")
|
198
|
+
token_column = column + (ss.pos - value.size)
|
199
|
+
tokens << PuppetLint::Token.new(:DQPOST, value, line, token_column)
|
200
|
+
end
|
201
|
+
else
|
202
|
+
if first
|
203
|
+
tokens << PuppetLint::Token.new(:DQPRE, value, line, column)
|
204
|
+
first = false
|
205
|
+
else
|
206
|
+
line += value.count("\n")
|
207
|
+
token_column = column + (ss.pos - value.size)
|
208
|
+
tokens << PuppetLint::Token.new(:DQMID, value, line, token_column)
|
209
|
+
end
|
210
|
+
if ss.scan(/\{/).nil?
|
211
|
+
var_name = ss.scan(/(::)?([\w-]+::)*[\w-]+/)
|
212
|
+
unless var_name.nil?
|
213
|
+
token_column = column + (ss.pos - var_name.size)
|
214
|
+
tokens << PuppetLint::Token.new(:UNENC_VARIABLE, var_name, line, token_column)
|
215
|
+
end
|
216
|
+
else
|
217
|
+
var_name = ss.scan(/(::)?([\w-]+::)*[\w-]+/)
|
218
|
+
unless var_name.nil?
|
219
|
+
token_column = column + (ss.pos - var_name.size)
|
220
|
+
tokens << PuppetLint::Token.new(:VARIABLE, var_name, line, token_column)
|
221
|
+
ss.scan(/\}/)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
value, terminator = get_string_segment(ss, '"$')
|
226
|
+
end
|
227
|
+
end
|
228
|
+
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
|
+
end
|
data/lib/puppet-lint/plugin.rb
CHANGED
@@ -54,9 +54,8 @@ class PuppetLint::CheckPlugin
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def run(fileinfo, data)
|
57
|
-
lexer =
|
58
|
-
|
59
|
-
@tokens = lexer.fullscan
|
57
|
+
lexer = PuppetLint::Lexer.new
|
58
|
+
@tokens = lexer.tokenise(data)
|
60
59
|
@fileinfo = fileinfo
|
61
60
|
@data = data
|
62
61
|
|
@@ -71,49 +70,6 @@ class PuppetLint::CheckPlugin
|
|
71
70
|
@problems
|
72
71
|
end
|
73
72
|
|
74
|
-
def filter_tokens
|
75
|
-
@title_tokens = []
|
76
|
-
@resource_indexes = []
|
77
|
-
@class_indexes = []
|
78
|
-
@defined_type_indexes = []
|
79
|
-
|
80
|
-
@tokens.each_index do |token_idx|
|
81
|
-
if @tokens[token_idx].first == :COLON
|
82
|
-
# gather a list of tokens that are resource titles
|
83
|
-
if @tokens[token_idx-1].first == :RBRACK
|
84
|
-
title_array_tokens = @tokens[@tokens.rindex { |r| r.first == :LBRACK }+1..token_idx-2]
|
85
|
-
@title_tokens += title_array_tokens.select { |token| [:STRING, :NAME].include? token.first }
|
86
|
-
else
|
87
|
-
if @tokens[token_idx + 1].first != :LBRACE
|
88
|
-
@title_tokens << @tokens[token_idx-1]
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
# gather a list of start and end indexes for resource attribute blocks
|
93
|
-
if @tokens[token_idx+1].first != :LBRACE
|
94
|
-
@resource_indexes << {:start => token_idx+1, :end => @tokens[token_idx+1..-1].index { |r| [:SEMIC, :RBRACE].include? r.first }+token_idx}
|
95
|
-
end
|
96
|
-
elsif [:CLASS, :DEFINE].include? @tokens[token_idx].first
|
97
|
-
lbrace_count = 0
|
98
|
-
@tokens[token_idx+1..-1].each_index do |class_token_idx|
|
99
|
-
idx = class_token_idx + token_idx
|
100
|
-
if @tokens[idx].first == :LBRACE
|
101
|
-
lbrace_count += 1
|
102
|
-
elsif @tokens[idx].first == :RBRACE
|
103
|
-
lbrace_count -= 1
|
104
|
-
if lbrace_count == 0
|
105
|
-
if @tokens[token_idx].first == :CLASS and @tokens[token_idx + 1].first != :LBRACE
|
106
|
-
@class_indexes << {:start => token_idx, :end => idx}
|
107
|
-
end
|
108
|
-
@defined_type_indexes << {:start => token_idx, :end => idx} if @tokens[token_idx].first == :DEFINE
|
109
|
-
break
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|
113
|
-
end
|
114
|
-
end
|
115
|
-
end
|
116
|
-
|
117
73
|
def tokens
|
118
74
|
@tokens
|
119
75
|
end
|
@@ -131,23 +87,138 @@ class PuppetLint::CheckPlugin
|
|
131
87
|
end
|
132
88
|
|
133
89
|
def title_tokens
|
134
|
-
|
135
|
-
|
90
|
+
@title_tokens ||= Proc.new do
|
91
|
+
result = []
|
92
|
+
tokens.each_index do |token_idx|
|
93
|
+
if tokens[token_idx].type == :COLON
|
94
|
+
# gather a list of tokens that are resource titles
|
95
|
+
if tokens[token_idx-1].type == :RBRACK
|
96
|
+
array_start_idx = tokens.rindex { |r|
|
97
|
+
r.type == :LBRACK
|
98
|
+
}
|
99
|
+
title_array_tokens = tokens[(array_start_idx + 1)..(token_idx - 2)]
|
100
|
+
result += title_array_tokens.select { |token|
|
101
|
+
[:STRING, :NAME].include? token.type
|
102
|
+
}
|
103
|
+
else
|
104
|
+
if tokens[token_idx + 1].type != :LBRACE
|
105
|
+
result << tokens[token_idx - 1]
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
result
|
111
|
+
end.call
|
136
112
|
end
|
137
113
|
|
114
|
+
# Internal: Calculate the positions of all resource declarations within the
|
115
|
+
# tokenised manifest. These positions only point to the content of the
|
116
|
+
# resource declaration, they do not include resource types or
|
117
|
+
# titles/namevars.
|
118
|
+
#
|
119
|
+
# Returns an Array of Hashes, each containing:
|
120
|
+
# :start - An Integer position in the `tokens` Array pointing to the first
|
121
|
+
# Token of a resource declaration parameters (type :NAME).
|
122
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
123
|
+
# Token of a resource declaration parameters (type :RBRACE).
|
138
124
|
def resource_indexes
|
139
|
-
|
140
|
-
|
125
|
+
@resource_indexes ||= Proc.new do
|
126
|
+
result = []
|
127
|
+
tokens.each_index do |token_idx|
|
128
|
+
if tokens[token_idx].type == :COLON
|
129
|
+
next_tokens = tokens[(token_idx + 1)..-1].reject { |r|
|
130
|
+
formatting_tokens.include? r.type
|
131
|
+
}
|
132
|
+
if next_tokens.first.type != :LBRACE
|
133
|
+
end_idx = tokens[(token_idx + 1)..-1].index { |r|
|
134
|
+
[:SEMIC, :RBRACE].include? r.type
|
135
|
+
} + token_idx
|
136
|
+
|
137
|
+
result << {:start => token_idx + 1, :end => end_idx}
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
result
|
142
|
+
end.call
|
141
143
|
end
|
142
144
|
|
145
|
+
# Internal: Calculate the positions of all class definitions within the
|
146
|
+
# tokenised manifest.
|
147
|
+
#
|
148
|
+
# Returns an Array of Hashes, each containing:
|
149
|
+
# :start - An Integer position in the `tokens` Array pointing to the first
|
150
|
+
# token of a class (type :CLASS).
|
151
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
152
|
+
# token of a class (type :RBRACE).
|
143
153
|
def class_indexes
|
144
|
-
|
145
|
-
|
154
|
+
@class_indexes ||= Proc.new do
|
155
|
+
result = []
|
156
|
+
tokens.each_index do |token_idx|
|
157
|
+
if tokens[token_idx].type == :CLASS
|
158
|
+
depth = 0
|
159
|
+
tokens[token_idx+1..-1].each_index do |class_token_idx|
|
160
|
+
idx = class_token_idx + token_idx + 1
|
161
|
+
if tokens[idx].type == :LBRACE
|
162
|
+
depth += 1
|
163
|
+
elsif tokens[idx].type == :RBRACE
|
164
|
+
depth -= 1
|
165
|
+
if depth == 0
|
166
|
+
if tokens[token_idx..-1].reject { |r|
|
167
|
+
r.type == :WHITESPACE
|
168
|
+
}[1].type != :LBRACE
|
169
|
+
result << {:start => token_idx, :end => idx}
|
170
|
+
end
|
171
|
+
break
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
result
|
178
|
+
end.call
|
146
179
|
end
|
147
180
|
|
181
|
+
# Internal: Calculate the positions of all defined type definitions within
|
182
|
+
# the tokenised manifest.
|
183
|
+
#
|
184
|
+
# Returns an Array of Hashes, each containing:
|
185
|
+
# :start - An Integer position in the `tokens` Array pointing to the first
|
186
|
+
# token of a defined type (type :DEFINE).
|
187
|
+
# :end - An Integer position in the `tokens` Array pointing to the last
|
188
|
+
# token of a defined type (type :RBRACE).
|
148
189
|
def defined_type_indexes
|
149
|
-
|
150
|
-
|
190
|
+
@defined_type_indexes ||= Proc.new do
|
191
|
+
result = []
|
192
|
+
tokens.each_index do |token_idx|
|
193
|
+
if tokens[token_idx].type == :DEFINE
|
194
|
+
depth = 0
|
195
|
+
tokens[token_idx+1..-1].each_index do |define_token_idx|
|
196
|
+
idx = define_token_idx + token_idx + 1
|
197
|
+
if tokens[idx].type == :LBRACE
|
198
|
+
depth += 1
|
199
|
+
elsif tokens[idx].type == :RBRACE
|
200
|
+
depth -= 1
|
201
|
+
if depth == 0
|
202
|
+
result << {:start => token_idx, :end => idx}
|
203
|
+
break
|
204
|
+
end
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
208
|
+
end
|
209
|
+
result
|
210
|
+
end.call
|
211
|
+
end
|
212
|
+
|
213
|
+
def formatting_tokens
|
214
|
+
[
|
215
|
+
:COMMENT,
|
216
|
+
:MLCOMMENT,
|
217
|
+
:SLASH_COMENT,
|
218
|
+
:INDENT,
|
219
|
+
:WHITESPACE,
|
220
|
+
:NEWLINE,
|
221
|
+
]
|
151
222
|
end
|
152
223
|
|
153
224
|
def manifest_lines
|