puppet-lint 0.1.13 → 0.2.0.pre1
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 +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
|