@@ -50,6 +50,10 @@ local default_whitelist = Set({
5050 " true" ,
5151 " false"
5252})
53+ local default_stages = {
54+ globals = true ,
55+ unused = true
56+ }
5357local LinterBlock
5458do
5559 local _class_0
6569 end
6670 end ,
6771 lint_check_unused = function (self )
72+ if not (self .stages .unused ) then
73+ return
74+ end
6875 if not (self .lint_unused_names and next (self .lint_unused_names )) then
6976 return
7077 end
130137 _with_0 .block = self .block
131138 _with_0 .render = self .render
132139 _with_0 .get_root_block = self .get_root_block
140+ _with_0 .stages = self .stages
133141 _with_0 .lint_check_unused = self .lint_check_unused
134142 _with_0 .lint_mark_used = self .lint_mark_used
135143 _with_0 .value_compilers = self .value_compilers
141149 _base_0 .__index = _base_0
142150 setmetatable (_base_0 , _parent_0 .__base )
143151 _class_0 = setmetatable ({
144- __init = function (self , whitelist_globals , ...)
152+ __init = function (self , whitelist_globals , stages , ...)
145153 if whitelist_globals == nil then
146154 whitelist_globals = default_whitelist
147155 end
156+ if stages == nil then
157+ stages = default_stages
158+ end
148159 _class_0 .__parent .__init (self , ... )
149160 self .get_root_block = function ()
150161 return self
151162 end
163+ self .stages = stages
152164 self .lint_errors = { }
153165 local vc = self .value_compilers
154166 self .value_compilers = setmetatable ({
155167 ref = function (block , val )
156168 local name = val [2 ]
157- if not (block :has_name (name ) or whitelist_globals [name ] or name :match (" %." )) then
158- insert (self .lint_errors , {
159- " accessing global `" .. tostring (name ) .. " `" ,
160- val [- 1 ]
161- })
169+ if self .stages .globals then
170+ if not (block :has_name (name ) or whitelist_globals [name ] or name :match (" %." )) then
171+ insert (self .lint_errors , {
172+ " accessing global `" .. tostring (name ) .. " `" ,
173+ val [- 1 ]
174+ })
175+ end
176+ end
177+ if self .stages .unused then
178+ block :lint_mark_used (name )
162179 end
163- block :lint_mark_used (name )
164180 return vc .ref (block , val )
165181 end
166182 }, {
169185 local sc = self .statement_compilers
170186 self .statement_compilers = setmetatable ({
171187 assign = function (block , node )
172- local names = node [2 ]
173- for _index_0 = 1 , # names do
174- local _continue_0 = false
175- repeat
176- local name = names [_index_0 ]
177- if type (name ) == " table" and name [1 ] == " temp_name" then
178- _continue_0 = true
179- break
180- end
181- local real_name , is_local = block :extract_assign_name (name )
182- if not (is_local or real_name and not block :has_name (real_name , true )) then
183- _continue_0 = true
184- break
185- end
186- if real_name == " _" then
188+ if self .stages .unused then
189+ local names = node [2 ]
190+ for _index_0 = 1 , # names do
191+ local _continue_0 = false
192+ repeat
193+ local name = names [_index_0 ]
194+ if type (name ) == " table" and name [1 ] == " temp_name" then
195+ _continue_0 = true
196+ break
197+ end
198+ local real_name , is_local = block :extract_assign_name (name )
199+ if not (is_local or real_name and not block :has_name (real_name , true )) then
200+ _continue_0 = true
201+ break
202+ end
203+ if real_name == " _" then
204+ _continue_0 = true
205+ break
206+ end
207+ block .lint_unused_names = block .lint_unused_names or { }
208+ block .lint_unused_names [real_name ] = node [- 1 ] or 0
187209 _continue_0 = true
210+ until true
211+ if not _continue_0 then
188212 break
189213 end
190- block .lint_unused_names = block .lint_unused_names or { }
191- block .lint_unused_names [real_name ] = node [- 1 ] or 0
192- _continue_0 = true
193- until true
194- if not _continue_0 then
195- break
196214 end
197215 end
198216 return sc .assign (block , node )
@@ -270,14 +288,18 @@ format_lint = function(errors, code, header)
270288end
271289local whitelist_for_file
272290do
273- local lint_config
274- whitelist_for_file = function (fname )
275- if not (lint_config ) then
276- lint_config = { }
291+ local loaded_configs = { }
292+ whitelist_for_file = function (fname , config_module )
293+ if config_module == nil then
294+ config_module = " lint_config"
295+ end
296+ if not (loaded_configs [config_module ]) then
297+ loaded_configs [config_module ] = { }
277298 pcall (function ()
278- lint_config = require (" lint_config " )
299+ loaded_configs [ config_module ] = require (config_module )
279300 end )
280301 end
302+ local lint_config = loaded_configs [config_module ]
281303 if not (lint_config .whitelist_globals ) then
282304 return default_whitelist
283305 end
295317 })
296318 end
297319end
320+ local normalize_stages
321+ normalize_stages = function (stages )
322+ if not (stages ) then
323+ return default_stages
324+ end
325+ if stages .globals ~= nil or stages .unused ~= nil then
326+ return stages
327+ end
328+ local out = { }
329+ for _index_0 = 1 , # stages do
330+ local stage = stages [_index_0 ]
331+ out [stage ] = true
332+ end
333+ return out
334+ end
298335local lint_code
299- lint_code = function (code , name , whitelist_globals )
336+ lint_code = function (code , name , opts )
300337 if name == nil then
301338 name = " string input"
302339 end
340+ if opts == nil then
341+ opts = { }
342+ end
303343 local parse = require (" moonscript.parse" )
304344 local tree , err = parse .string (code )
305345 if not (tree ) then
306346 return nil , err
307347 end
308- local scope = LinterBlock (whitelist_globals )
348+ local whitelist_globals = opts .whitelist_globals or default_whitelist
349+ local stages = normalize_stages (opts .stages )
350+ local scope = LinterBlock (whitelist_globals , stages )
309351 scope :stms (tree )
310352 scope :lint_check_unused ()
311353 return format_lint (scope .lint_errors , code , name )
312354end
313355local lint_file
314- lint_file = function (fname )
356+ lint_file = function (fname , opts )
357+ if opts == nil then
358+ opts = { }
359+ end
315360 local f , err = io.open (fname )
316361 if not (f ) then
317362 return nil , err
318363 end
319- return lint_code (f :read (" *a" ), fname , whitelist_for_file (fname ))
364+ local config_module = opts .config_module or " lint_config"
365+ return lint_code (f :read (" *a" ), fname , {
366+ whitelist_globals = whitelist_for_file (fname , config_module ),
367+ stages = opts .stages
368+ })
320369end
321370return {
322371 lint_code = lint_code ,
0 commit comments