Skip to content

Commit

Permalink
Implement separate limits for line length based on line type
Browse files Browse the repository at this point in the history
Like for trailing whitespace warnings, separate
lines with line endings within a comment, a string, or normal code lines.
Add separate limits for line length for these three types.
Main option (max_line_length) sets max length for all three types.

Ref #100.
  • Loading branch information
mpeterv committed May 6, 2017
1 parent 8094be0 commit 7980866
Show file tree
Hide file tree
Showing 10 changed files with 153 additions and 36 deletions.
3 changes: 2 additions & 1 deletion spec/check_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,8 @@ return foo;
per_line_options = {
[2] = {{options = {ignore = {"foo"}}, line = 2, column = 16, end_column = 38}}
},
line_lengths = {28, 38, 16, 17, 19, 17, 32, 16, 3}
line_lengths = {28, 38, 16, 17, 19, 17, 32, 16, 3},
line_endings = {"comment", "comment", "comment", nil, "comment", "comment", nil, "comment", nil}
}, check_full[[
-- luacheck: push ignore bar
local foo, bar -- luacheck: ignore foo
Expand Down
65 changes: 45 additions & 20 deletions spec/cli_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -550,33 +550,58 @@ Total: 6 warnings / 0 errors in 1 file

it("detects lines that are too long", function()
assert.equal([[
Checking spec/samples/line_length.lua 4 warnings
Checking spec/samples/line_length.lua 8 warnings
spec/samples/line_length.lua:2:1: line is too long (123 > 120)
spec/samples/line_length.lua:3:1: line is too long (164 > 120)
spec/samples/line_length.lua:8:1: line is too long (132 > 120)
spec/samples/line_length.lua:10:1: line is too long (85 > 80)
Total: 4 warnings / 0 errors in 1 file
spec/samples/line_length.lua:8:1: line is too long (134 > 120)
spec/samples/line_length.lua:13:1: line is too long (47 > 40)
spec/samples/line_length.lua:18:1: line is too long (132 > 120)
spec/samples/line_length.lua:22:1: line is too long (85 > 80)
spec/samples/line_length.lua:26:1: line is too long (104 > 100)
spec/samples/line_length.lua:29:1: line is too long (125 > 120)
Total: 8 warnings / 0 errors in 1 file
]], get_output "spec/samples/line_length.lua --no-config")

assert.equal([[
Checking spec/samples/line_length.lua 3 warnings
Checking spec/samples/line_length.lua 7 warnings
spec/samples/line_length.lua:3:1: line is too long (164 > 130)
spec/samples/line_length.lua:8:1: line is too long (132 > 130)
spec/samples/line_length.lua:10:1: line is too long (85 > 80)
spec/samples/line_length.lua:8:1: line is too long (134 > 130)
spec/samples/line_length.lua:13:1: line is too long (47 > 40)
spec/samples/line_length.lua:18:1: line is too long (132 > 130)
spec/samples/line_length.lua:22:1: line is too long (85 > 80)
spec/samples/line_length.lua:26:1: line is too long (104 > 100)
spec/samples/line_length.lua:29:1: line is too long (125 > 120)
Total: 3 warnings / 0 errors in 1 file
Total: 7 warnings / 0 errors in 1 file
]], get_output "spec/samples/line_length.lua --no-config --max-line-length=130")

assert.equal([[
Checking spec/samples/line_length.lua 1 warning
Checking spec/samples/line_length.lua 4 warnings
spec/samples/line_length.lua:10:1: line is too long (85 > 80)
spec/samples/line_length.lua:13:1: line is too long (47 > 40)
spec/samples/line_length.lua:22:1: line is too long (85 > 80)
spec/samples/line_length.lua:26:1: line is too long (104 > 100)
spec/samples/line_length.lua:29:1: line is too long (125 > 120)
Total: 1 warning / 0 errors in 1 file
Total: 4 warnings / 0 errors in 1 file
]], get_output "spec/samples/line_length.lua --no-config --no-max-line-length")

assert.equal([[
Checking spec/samples/line_length.lua 7 warnings
spec/samples/line_length.lua:2:1: line is too long (123 > 120)
spec/samples/line_length.lua:3:1: line is too long (164 > 120)
spec/samples/line_length.lua:13:1: line is too long (47 > 40)
spec/samples/line_length.lua:18:1: line is too long (132 > 120)
spec/samples/line_length.lua:22:1: line is too long (85 > 80)
spec/samples/line_length.lua:26:1: line is too long (104 > 100)
spec/samples/line_length.lua:29:1: line is too long (125 > 120)
Total: 7 warnings / 0 errors in 1 file
]], get_output "spec/samples/line_length.lua --no-config --no-max-string-line-length")
end)

it("detects issues related to read-only globals", function()
Expand Down Expand Up @@ -884,10 +909,10 @@ Total: 16 warnings / 1 error in 4 files
(%d+)
spec/samples/good_code.lua
(%d+)
return {{},{},{19,0,23,17,3,0,30,25,26,3,0,15}}
return {{},{},{19,0,23,17,3,0,30,25,26,3,0,15},{[4]="comment"}}
spec/samples/bad_code.lua
(%d+)
local A,B,C="package","embrace","hepler";return {{{"112",A,1,1,7,[23]={A,"loaded",true}},{"211","helper",3,16,21,[10]=true},{"212","...",3,23,25},{"111",B,7,10,16,[11]=true,[23]={B}},{"412","opt",8,10,12,7,18},{"113",C,9,11,16,[23]={C}}},{},{24,0,26,9,3,0,21,31,26,3,0}}
local A,B,C="package","embrace","hepler";return {{{"112",A,1,1,7,[23]={A,"loaded",true}},{"211","helper",3,16,21,[10]=true},{"212","...",3,23,25},{"111",B,7,10,16,[11]=true,[23]={B}},{"412","opt",8,10,12,7,18},{"113",C,9,11,16,[23]={C}}},{},{24,0,26,9,3,0,21,31,26,3,0},{[4]="comment"}}
spec/samples/python_code.lua
(%d+)
return {{{"011",[3]=1,[4]=6,[5]=15,[12]="expected '=' near '__future__'"}},{},{}}
Expand Down Expand Up @@ -1209,15 +1234,15 @@ Checking spec/samples/global_inline_options.lua 3 warnings
Checking spec/samples/globals.lua 2 warnings
Checking spec/samples/indirect_globals.lua 3 warnings
Checking spec/samples/inline_options.lua 7 warnings / 2 errors
Checking spec/samples/line_length.lua 4 warnings
Checking spec/samples/line_length.lua 8 warnings
Checking spec/samples/python_code.lua 1 error
Checking spec/samples/read_globals.lua 5 warnings
Checking spec/samples/read_globals_inline_options.lua 3 warnings
Checking spec/samples/redefined.lua 7 warnings
Checking spec/samples/unused_code.lua 9 warnings
Checking spec/samples/unused_secondaries.lua 4 warnings
Total: 63 warnings / 4 errors in 16 files
Total: 67 warnings / 4 errors in 16 files
]]):gsub("(spec/samples)/", "%1"..package.config:sub(1, 1)),
get_output "spec/samples --config=spec/configs/exclude_files_config.luacheckrc -qq --exclude-files spec/samples/global_fields.lua")
end)
Expand All @@ -1231,15 +1256,15 @@ Checking global_inline_options.lua 3 warnings
Checking globals.lua 2 warnings
Checking indirect_globals.lua 3 warnings
Checking inline_options.lua 7 warnings / 2 errors
Checking line_length.lua 4 warnings
Checking line_length.lua 8 warnings
Checking python_code.lua 1 error
Checking read_globals.lua 5 warnings
Checking read_globals_inline_options.lua 3 warnings
Checking redefined.lua 7 warnings
Checking unused_code.lua 9 warnings
Checking unused_secondaries.lua 4 warnings
Total: 63 warnings / 4 errors in 16 files
Total: 67 warnings / 4 errors in 16 files
]], get_output(". --config=spec/configs/exclude_files_config.luacheckrc -qq --exclude-files global_fields.lua", "spec/samples/"))
end)

Expand All @@ -1252,13 +1277,13 @@ Checking global_inline_options.lua 3 warnings
Checking globals.lua 2 warnings
Checking indirect_globals.lua 3 warnings
Checking inline_options.lua 7 warnings / 2 errors
Checking line_length.lua 4 warnings
Checking line_length.lua 8 warnings
Checking python_code.lua 1 error
Checking redefined.lua 7 warnings
Checking unused_code.lua 9 warnings
Checking unused_secondaries.lua 4 warnings
Total: 55 warnings / 4 errors in 14 files
Total: 59 warnings / 4 errors in 14 files
]], get_output(". --config=spec/configs/exclude_files_config.luacheckrc -qq --exclude-files global_fields.lua --exclude-files " .. quote("./read*"), "spec/samples/"))
end)

Expand Down
6 changes: 4 additions & 2 deletions spec/filter_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -638,16 +638,18 @@ describe("filter", function()
assert.same({
{
{code = "631", line = 2, column = 1, end_column = 121, max_length = 120},
{code = "631", line = 5, column = 1, end_column = 21, max_length = 20}
{code = "631", line = 5, column = 1, end_column = 18, line_ending = "string", max_length = 15}
}
}, filter_full({
{
events = {
{options = {max_line_length = 20}, line = 3, column = 1},
{options = {max_string_line_length = 15}, line = 4, column = 1},
{options = {max_line_length = false}, line = 6, column = 1}
},
per_line_options = {},
line_lengths = {120, 121, 15, 20, 21, 15, 200}
line_lengths = {120, 121, 15, 20, 18, 15, 200},
line_endings = {[5] = "string"}
}
}, {}))
end)
Expand Down
21 changes: 20 additions & 1 deletion spec/samples/line_length.lua
Original file line number Diff line number Diff line change
@@ -1,11 +1,30 @@
-- luacheck: only 63
local aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
------------------------------------------------------------------------------------------------------------------------------------------ comments can be long, too
-- luacheck: push no max line length

-- luacheck: push no max code line length
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = "readable code"
string = [[
looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong
]]
normal = "still normal"

-- luacheck: push max line length 40
this_overrides_code_line_specific_option = true
-- luacheck: pop

-- luacheck: pop

aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa = "unreadable"
-- luacheck: max line length 80
-- luacheck: max string line length 100
-- luacheck: max comment line length 120
local i_code_in_ed_in_a_terminal_with_default_width_and_i_dont_like_long_lines = true
local really = false
string2 = [[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk94
]]
string3 = [[kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk105
]]
code() -- comment kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk105
--[[ comment kkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkkk125
]]
6 changes: 4 additions & 2 deletions src/luacheck/cache.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@ local cache = {}
-- third is check result in lua table format.
-- String fields are compressed into array indexes.

cache.format_version = 19
cache.format_version = 20

local option_fields = {
"ignore", "std", "globals", "unused_args", "self", "compat", "global", "unused", "redefined",
"unused_secondaries", "allow_defined", "allow_defined_top", "module",
"read_globals", "new_globals", "new_read_globals", "enable", "only", "not_globals",
"max_line_length"
"max_line_length", "max_code_line_length", "max_string_line_length", "max_comment_line_length"
}

local event_fields = {
Expand Down Expand Up @@ -55,6 +55,7 @@ local function compress_report(report)
end

res[3] = report.line_lengths
res[4] = report.line_endings
return res
end

Expand Down Expand Up @@ -88,6 +89,7 @@ local function decompress_report(compressed)
end

report.line_lengths = compressed[3]
report.line_endings = compressed[4]
return report
end

Expand Down
2 changes: 1 addition & 1 deletion src/luacheck/check.lua
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ local function check_or_throw(src)
reachability(chstate, line)
detect_globals(chstate, line)
local events, per_line_opts = inline_options.get_events(ast, comments, code_lines, chstate.warnings)
return {events = events, per_line_options = per_line_opts, line_lengths = line_lengths}
return {events = events, per_line_options = per_line_opts, line_lengths = line_lengths, line_endings = line_endings}
end

--- Checks source.
Expand Down
15 changes: 12 additions & 3 deletions src/luacheck/filter.lua
Original file line number Diff line number Diff line change
Expand Up @@ -259,9 +259,17 @@ local function get_field_status(opts, warning, depth)
return defined and (read_only and "read_only" or "global") or "undefined"
end

local function get_max_line_length(opts, warning)
return opts["max_" .. (warning.line_ending or "code") .. "_line_length"]
end

local function filters(opts, warning)
if warning.code == "631" and (not opts.max_line_length or warning.end_column <= opts.max_line_length) then
return true
if warning.code == "631" then
local max_line_length = get_max_line_length(opts, warning)

if (not max_line_length or warning.end_column <= max_line_length) then
return true
end
end

if warning.code:match("[234]..") and warning.name == "_" and not warning.useless then
Expand Down Expand Up @@ -309,7 +317,7 @@ local function filter_file_report(report)
else
if not filters(opts, issue) then
if issue.code == "631" then
issue.max_length = opts.max_line_length
issue.max_length = get_max_line_length(opts, issue)
end

if issue.code:match("1[24][23]") then
Expand Down Expand Up @@ -420,6 +428,7 @@ local function add_long_line_warnings(report)
code = "631",
line = line_number,
column = 1,
line_ending = file_report.line_endings[line_number],
end_column = length
})
end
Expand Down
11 changes: 7 additions & 4 deletions src/luacheck/inline_options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ local function add_closure_boundaries(ast, events)
end
end

local max_line_length_opts = utils.array_to_set({
"max_line_length", "max_code_line_length", "max_string_line_length", "max_comment_line_length"})

-- Parses inline option body, returns options or nil.
local function get_options(body)
local opts = {}
Expand Down Expand Up @@ -70,13 +73,13 @@ local function get_options(body)
-- Array option with 'no' prefix is invalid.
return
end
elseif name == "max_line_length" then
-- Either `max line length <number>` or `no max line length`.
elseif max_line_length_opts[name] then
-- Either `max [type] line length <number>` or `no max [type] line length`.
if flag and #args == 1 and tonumber(args[1]) then
opts.max_line_length = tonumber(args[1])
opts[name] = tonumber(args[1])
break
elseif not flag and #args == 0 then
opts.max_line_length = false
opts[name] = false
break
else
return
Expand Down
24 changes: 24 additions & 0 deletions src/luacheck/main.lua
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,30 @@ their files.]])
:action "store_false"
:target "max_line_length"

parser:option("--max-code-line-length", [[Set maximum allowed length for lines
ending with code (default: 120).]])
:argname "<length>"
:convert(tonumber)
parser:flag("--no-max-code-line-length", "Do not limit code line length.")
:action "store_false"
:target "max_code_line_length"

parser:option("--max-string-line-length", [[Set maximum allowed length for lines
within a string (default: 120).]])
:argname "<length>"
:convert(tonumber)
parser:flag("--no-max-string-line-length", "Do not limit string line length.")
:action "store_false"
:target "max_string_line_length"

parser:option("--max-comment-line-length", [[Set maximum allowed length for
comment lines (default: 120).]])
:argname "<length>"
:convert(tonumber)
parser:flag("--no-max-comment-line-length", "Do not limit comment line length.")
:action "store_false"
:target "max_comment_line_length"

parser:option("--ignore -i", [[Filter out warnings matching these patterns.
If a pattern contains slash, part before slash matches
warning code and part after it matches name of related
Expand Down
36 changes: 34 additions & 2 deletions src/luacheck/options.lua
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ options.variadic_inline_options = {
options.all_options = {
std = std_or_array_of_strings,
max_line_length = number_or_false,
max_code_line_length = number_or_false,
max_string_line_length = number_or_false,
max_comment_line_length = number_or_false,
inline = boolean
}

Expand Down Expand Up @@ -259,6 +262,34 @@ local function get_scalar_opt(opts_stack, option, default)
return default
end

local line_length_suboptions = {"max_code_line_length", "max_string_line_length", "max_comment_line_length"}

local function get_max_line_opts(opts_stack)
local res = {max_line_length = 120}

for _, opt_name in ipairs(line_length_suboptions) do
res[opt_name] = res.max_line_length
end

for _, opts in ipairs(opts_stack) do
if opts.max_line_length ~= nil then
res.max_line_length = opts.max_line_length

for _, opt_name in ipairs(line_length_suboptions) do
res[opt_name] = opts.max_line_length
end
end

for _, opt_name in ipairs(line_length_suboptions) do
if opts[opt_name] ~= nil then
res[opt_name] = opts[opt_name]
end
end
end

return res
end

local function anchor_pattern(pattern, only_start)
if not pattern then
return
Expand Down Expand Up @@ -361,8 +392,7 @@ local scalar_options = {
inline = true,
module = false,
allow_defined = false,
allow_defined_top = false,
max_line_length = 120
allow_defined_top = false
}

-- Returns normalized options.
Expand All @@ -379,6 +409,8 @@ function options.normalize(opts_stack)
res[option] = get_scalar_opt(opts_stack, option, default)
end

local max_line_opts = get_max_line_opts(opts_stack)
utils.update(res, max_line_opts)
res.rules = normalize_patterns(get_rules(opts_stack))
return res
end
Expand Down

0 comments on commit 7980866

Please sign in to comment.