diff --git a/selene-lib/src/lints/test_util.rs b/selene-lib/src/lints/test_util.rs index 7a218994..f56e1a52 100644 --- a/selene-lib/src/lints/test_util.rs +++ b/selene-lib/src/lints/test_util.rs @@ -11,7 +11,8 @@ use std::{ }; use codespan_reporting::{ - diagnostic::Severity as CodespanSeverity, term::Config as CodespanConfig, + diagnostic::{self, Severity as CodespanSeverity}, + term::Config as CodespanConfig, }; use serde::de::DeserializeOwned; @@ -93,23 +94,53 @@ fn apply_diagnostics_fixes(code: &str, diagnostics: &[&Diagnostic]) -> String { } /// Returns empty string if there are no diffs -fn generate_diff(source1: &str, source2: &str) -> String { +fn generate_diff(source1: &str, source2: &str, diagnostics: &[&Diagnostic]) -> String { let mut result = String::new(); let mut has_changes = false; + let mut byte_offset = 0; + let mut prev_non_insert_applicability_prefix = " "; for change in TextDiff::from_lines(source1, source2).iter_all_changes() { + let change_length = change.value().len() as u32; + + let change_end_byte = byte_offset + change_length as u32; + + let mut applicability_prefix = " "; + for diagnostic in diagnostics { + let (start, end) = diagnostic.primary_label.range; + if start < change_end_byte && end > byte_offset { + if diagnostic.applicability == Applicability::MachineApplicable { + applicability_prefix = "MA"; + break; + } else if diagnostic.applicability == Applicability::MaybeIncorrect { + applicability_prefix = "MI"; + break; + } + } + } + + if change.tag() == ChangeTag::Insert { + applicability_prefix = prev_non_insert_applicability_prefix; + } + let sign = match change.tag() { ChangeTag::Delete => { has_changes = true; - "-" + format!("-{}", applicability_prefix) } ChangeTag::Insert => { has_changes = true; - "+" + format!("+{}", applicability_prefix) } - ChangeTag::Equal => " ", + ChangeTag::Equal => " ".to_string(), }; - result.push_str(&format!("{}{}", sign, change.value())); + + result.push_str(&format!("{} {}", sign, change.value())); + + if change.tag() != ChangeTag::Insert { + byte_offset = change_end_byte; + prev_non_insert_applicability_prefix = applicability_prefix; + } } if has_changes { @@ -195,7 +226,11 @@ pub fn test_lint_config_with_output< fixed_diagnostics.sort_by_key(|diagnostic| diagnostic.start_position()); } - let fixed_diff = generate_diff(&lua_source, &fixed_code); + let fixed_diff = generate_diff( + &lua_source, + &fixed_code, + &diagnostics.iter().collect::>(), + ); let diff_output_path = path_base.with_extension("fixed.diff"); if let Ok(expected) = fs::read_to_string(&diff_output_path) { diff --git a/selene-lib/tests/lints/compare_nan/compare_nan_if.fixed.diff b/selene-lib/tests/lints/compare_nan/compare_nan_if.fixed.diff index 9f868d40..e11f1451 100644 --- a/selene-lib/tests/lints/compare_nan/compare_nan_if.fixed.diff +++ b/selene-lib/tests/lints/compare_nan/compare_nan_if.fixed.diff @@ -1,34 +1,34 @@ --if x == 0/0 then -+if x ~= x then - end - --if x ~= 0/0 then -+if x == x then - end - - if x ~= x then - end - - if x >= 0/0 then - end - - if 1 == 0/0 then - end - - if 1 ~= 0/0 then - end - - if 1 + 0/0 then - end - - if y.foo() == 0/0 then - end - - if y.bar() ~= 0/0 then - end - - if x == 1 then - end - - if 1 == 0 then - end \ No newline at end of file +-MI if x == 0/0 then ++MI if x ~= x then + end + +-MI if x ~= 0/0 then ++MI if x == x then + end + + if x ~= x then + end + + if x >= 0/0 then + end + + if 1 == 0/0 then + end + + if 1 ~= 0/0 then + end + + if 1 + 0/0 then + end + + if y.foo() == 0/0 then + end + + if y.bar() ~= 0/0 then + end + + if x == 1 then + end + + if 1 == 0 then + end \ No newline at end of file diff --git a/selene-lib/tests/lints/compare_nan/compare_nan_variables.fixed.diff b/selene-lib/tests/lints/compare_nan/compare_nan_variables.fixed.diff index 59b83e46..cc51c712 100644 --- a/selene-lib/tests/lints/compare_nan/compare_nan_variables.fixed.diff +++ b/selene-lib/tests/lints/compare_nan/compare_nan_variables.fixed.diff @@ -1,15 +1,15 @@ - local _ = 0/0 - local _ = 1 ~= 0/0 - local _ = 2 == 0/0 - local _ = 3 + 0/0 - local _ = 4 >= 0/0 --local _ = x ~= 0/0 --local _ = x == 0/0 -+local _ = x == x -+local _ = x ~= x - local _ = x >= 0/0 - local _ = y.foo() == 0/0 - local _ = y.bar() ~= 0/0 - - local _ = x == 1 - local _ = 1 == 0 \ No newline at end of file + local _ = 0/0 + local _ = 1 ~= 0/0 + local _ = 2 == 0/0 + local _ = 3 + 0/0 + local _ = 4 >= 0/0 +-MI local _ = x ~= 0/0 +-MI local _ = x == 0/0 ++MI local _ = x == x ++MI local _ = x ~= x + local _ = x >= 0/0 + local _ = y.foo() == 0/0 + local _ = y.bar() ~= 0/0 + + local _ = x == 1 + local _ = 1 == 0 \ No newline at end of file diff --git a/selene-lib/tests/lints/constant_table_comparison/constant_table_comparison.fixed.diff b/selene-lib/tests/lints/constant_table_comparison/constant_table_comparison.fixed.diff index b1004f99..3824402a 100644 --- a/selene-lib/tests/lints/constant_table_comparison/constant_table_comparison.fixed.diff +++ b/selene-lib/tests/lints/constant_table_comparison/constant_table_comparison.fixed.diff @@ -1,20 +1,20 @@ - print(x == { "a", "b", "c" }) - print({ "a", "b", "c" } == x) - --print(x == {}) --print({} == x) --print(x ~= {}) --print({} ~= x) -+print(next(x) == nil) -+print(next(x) == nil) -+print(next(x) ~= nil) -+print(next(x) ~= nil) - - print({ "a", "b", "c" } == { "a", "b", "c" }) - print({ "a", "b", "c" } == {}) - print({} == {}) - - print( -- my cool table -- t == {} -+ next(t) == nil - ) + print(x == { "a", "b", "c" }) + print({ "a", "b", "c" } == x) + +-MI print(x == {}) +-MI print({} == x) +-MI print(x ~= {}) +-MI print({} ~= x) ++MI print(next(x) == nil) ++MI print(next(x) == nil) ++MI print(next(x) ~= nil) ++MI print(next(x) ~= nil) + + print({ "a", "b", "c" } == { "a", "b", "c" }) + print({ "a", "b", "c" } == {}) + print({} == {}) + + print( -- my cool table +-MI t == {} ++MI next(t) == nil + ) diff --git a/selene-lib/tests/lints/deprecated/deprecated_functions.fixed.diff b/selene-lib/tests/lints/deprecated/deprecated_functions.fixed.diff index 11fc9787..0add791a 100644 --- a/selene-lib/tests/lints/deprecated/deprecated_functions.fixed.diff +++ b/selene-lib/tests/lints/deprecated/deprecated_functions.fixed.diff @@ -1,5 +1,5 @@ - table.foreach({}, function(k, v) end) --print(table.getn(x)) -+print(#x) - - table.foreach({}, 3) + table.foreach({}, function(k, v) end) +-MA print(table.getn(x)) ++MA print(#x) + + table.foreach({}, 3) diff --git a/selene-lib/tests/lints/empty_loop/empty_loop.fixed.diff b/selene-lib/tests/lints/empty_loop/empty_loop.fixed.diff index 0edc5d4a..872cdbcb 100644 --- a/selene-lib/tests/lints/empty_loop/empty_loop.fixed.diff +++ b/selene-lib/tests/lints/empty_loop/empty_loop.fixed.diff @@ -1,73 +1,73 @@ - for _ = 1, 10 do - return "Should not warn" - end - - for _ = 1, 10 do - print("Should not warn") - end - --for _ = 1, 10 do -- -- Should warn --end - --for _ = 1, 10 do -- --[[ -- Should warn -- ]] --end - --for _ = 1, 10 do - - -- --end - -+ - for _ in pairs({}) do - return "Should not warn" - end - --for _ in pairs({}) do --end - -+ - for _ in ipairs({}) do - return "Should not warn" - end - --for _ in ipairs({}) do --end - -+ - for _ in {} do - return "Should not warn" - end - --for _ in {} do --end - -+ - for _ in a() do - return "Should not warn" - end - --for _ in a() do --end - -+ - while true do - return "Should not warn" - end - --while true do --end - -+ - repeat - return "Should not warn" - until true - --repeat --until true -+ - -- comment here shouldn't break anything + for _ = 1, 10 do + return "Should not warn" + end + + for _ = 1, 10 do + print("Should not warn") + end + +-MI for _ = 1, 10 do +-MI -- Should warn +-MI end + +-MI for _ = 1, 10 do +-MI --[[ +-MI Should warn +-MI ]] +-MI end + +-MI for _ = 1, 10 do + + +-MI +-MI end + ++ + for _ in pairs({}) do + return "Should not warn" + end + +-MI for _ in pairs({}) do +-MI end + ++ + for _ in ipairs({}) do + return "Should not warn" + end + +-MI for _ in ipairs({}) do +-MI end + ++ + for _ in {} do + return "Should not warn" + end + +-MI for _ in {} do +-MI end + ++ + for _ in a() do + return "Should not warn" + end + +-MI for _ in a() do +-MI end + ++ + while true do + return "Should not warn" + end + +-MI while true do +-MI end + ++ + repeat + return "Should not warn" + until true + +-MI repeat +-MI until true ++MI + -- comment here shouldn't break anything diff --git a/selene-lib/tests/lints/empty_loop/empty_loop_comments.fixed.diff b/selene-lib/tests/lints/empty_loop/empty_loop_comments.fixed.diff index 498d8198..fcc581e2 100644 --- a/selene-lib/tests/lints/empty_loop/empty_loop_comments.fixed.diff +++ b/selene-lib/tests/lints/empty_loop/empty_loop_comments.fixed.diff @@ -1,72 +1,72 @@ - for _ = 1, 10 do - return "Should not warn" - end - - for _ = 1, 10 do - print("Should not warn") - end - - for _ = 1, 10 do - -- Should not warn - end - - for _ = 1, 10 do - --[[ - Should not warn - ]] - end - --for _ = 1, 10 do -- -- - --end - - for _ in pairs({}) do - return "Should not warn" - end - --for _ in pairs({}) do --end - -+ - for _ in ipairs({}) do - return "Should not warn" - end - --for _ in ipairs({}) do --end - -+ - for _ in {} do - return "Should not warn" - end - --for _ in {} do --end - -+ - for _ in a() do - return "Should not warn" - end - --for _ in a() do --end - -+ - while true do - return "Should not warn" - end - --while true do --end - -+ - repeat - return "Should not warn" - until true - --repeat --until true -+ - -- comment here shouldn't break anything + for _ = 1, 10 do + return "Should not warn" + end + + for _ = 1, 10 do + print("Should not warn") + end + + for _ = 1, 10 do + -- Should not warn + end + + for _ = 1, 10 do + --[[ + Should not warn + ]] + end + +-MI for _ = 1, 10 do +-MI +-MI + +-MI end + + for _ in pairs({}) do + return "Should not warn" + end + +-MI for _ in pairs({}) do +-MI end + ++ + for _ in ipairs({}) do + return "Should not warn" + end + +-MI for _ in ipairs({}) do +-MI end + ++ + for _ in {} do + return "Should not warn" + end + +-MI for _ in {} do +-MI end + ++ + for _ in a() do + return "Should not warn" + end + +-MI for _ in a() do +-MI end + ++ + while true do + return "Should not warn" + end + +-MI while true do +-MI end + ++ + repeat + return "Should not warn" + until true + +-MI repeat +-MI until true ++MI + -- comment here shouldn't break anything diff --git a/selene-lib/tests/lints/parenthese_conditions/parenthese_conditions.fixed.diff b/selene-lib/tests/lints/parenthese_conditions/parenthese_conditions.fixed.diff index 71268175..c1ecbc29 100644 --- a/selene-lib/tests/lints/parenthese_conditions/parenthese_conditions.fixed.diff +++ b/selene-lib/tests/lints/parenthese_conditions/parenthese_conditions.fixed.diff @@ -1,27 +1,27 @@ - if x then end --if (x) then end -+if x then end - --if (x) then -+if x then - elseif y then --elseif (z) then -+elseif z then - end - - while true do end --while (true) do end -+while true do end - - repeat until false --repeat until (false) -+repeat until false - - while (true) and false do end - --if ((function() -- if (x) then end --end)()) then end -+if (function() -+ if x then end -+end)() then end + if x then end +-MA if (x) then end ++MA if x then end + +-MA if (x) then ++MA if x then + elseif y then +-MA elseif (z) then ++MA elseif z then + end + + while true do end +-MA while (true) do end ++MA while true do end + + repeat until false +-MA repeat until (false) ++MA repeat until false + + while (true) and false do end + +-MA if ((function() +-MA if (x) then end +-MA end)()) then end ++MA if (function() ++MA if x then end ++MA end)() then end diff --git a/selene-lib/tests/lints/unused_variable/blocks.fixed.diff b/selene-lib/tests/lints/unused_variable/blocks.fixed.diff index 5308ebc1..6e85cca6 100644 --- a/selene-lib/tests/lints/unused_variable/blocks.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/blocks.fixed.diff @@ -1,25 +1,25 @@ - -- Functions --local function unusedFunction() -- local unusedVariableA = 1 -- local unusedVariableB = 1 -+local function _unusedFunction() -+ local _unusedVariableA = 1 -+ local _unusedVariableB = 1 - end - - print(unusedVariableB) --local overidden = true -+local _overidden = true - - local function overridesIt() - local overidden = false - print(overidden) - end - - overridesIt() - - -- Anonymous functions - local a = 1 - print(function() - _G.foo = a - end) + -- Functions +-MA local function unusedFunction() +-MA local unusedVariableA = 1 +-MA local unusedVariableB = 1 ++MA local function _unusedFunction() ++MA local _unusedVariableA = 1 ++MA local _unusedVariableB = 1 + end + + print(unusedVariableB) +-MA local overidden = true ++MA local _overidden = true + + local function overridesIt() + local overidden = false + print(overidden) + end + + overridesIt() + + -- Anonymous functions + local a = 1 + print(function() + _G.foo = a + end) diff --git a/selene-lib/tests/lints/unused_variable/edge_cases.fixed.diff b/selene-lib/tests/lints/unused_variable/edge_cases.fixed.diff index 414306c0..2451f300 100644 --- a/selene-lib/tests/lints/unused_variable/edge_cases.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/edge_cases.fixed.diff @@ -1,10 +1,10 @@ - local foo = 1 --local foo = foo + 1 --local bar = bar -+local _foo = foo + 1 -+local _bar = bar - - -- The variables inside of a repeat...until are accessible from the until statement - repeat - local baz - until baz + local foo = 1 +-MA local foo = foo + 1 +-MA local bar = bar ++MA local _foo = foo + 1 ++MA local _bar = bar + + -- The variables inside of a repeat...until are accessible from the until statement + repeat + local baz + until baz diff --git a/selene-lib/tests/lints/unused_variable/explicit_self.fixed.diff b/selene-lib/tests/lints/unused_variable/explicit_self.fixed.diff index 437f1f7b..6e60342c 100644 --- a/selene-lib/tests/lints/unused_variable/explicit_self.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/explicit_self.fixed.diff @@ -1,5 +1,5 @@ --local function foo(self) -+local function foo(_self) - end - - foo() +-MA local function foo(self) ++MA local function foo(_self) + end + + foo() diff --git a/selene-lib/tests/lints/unused_variable/if.fixed.diff b/selene-lib/tests/lints/unused_variable/if.fixed.diff index 70f902f4..3b47e37b 100644 --- a/selene-lib/tests/lints/unused_variable/if.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/if.fixed.diff @@ -1,18 +1,18 @@ - if 1 then -- local localA -+ local _localA - elseif 2 then -- local localB -+ local _localB - print(localA) - elseif 3 then -- local localC -+ local _localC - print(localB) - else -- local localD -+ local _localD - print(localC) - end - - print(localA, localB, localC, localD) + if 1 then +-MA local localA ++MA local _localA + elseif 2 then +-MA local localB ++MA local _localB + print(localA) + elseif 3 then +-MA local localC ++MA local _localC + print(localB) + else +-MA local localD ++MA local _localD + print(localC) + end + + print(localA, localB, localC, localD) diff --git a/selene-lib/tests/lints/unused_variable/locals.fixed.diff b/selene-lib/tests/lints/unused_variable/locals.fixed.diff index b5522fcd..23c369be 100644 --- a/selene-lib/tests/lints/unused_variable/locals.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/locals.fixed.diff @@ -1,32 +1,32 @@ - -- Unused --local localA, localB -+local _localA, _localB - - -- Used - local localC = 1 - print(localC) - - -- Mutated, but never read - local localD = 1 - localD = 2 - localD = 3 - - -- Read, mutated, read - local localE = 1 - print(localE) - localE = 2 - print(localE) - - -- Read, mutated, unread - local localF = 1 - print(localF) - localF = 2 - - -- Called function - local localG = function() end - localG() - - -- Put into a table - local localH = 1 --local localI = { localH } -+local _localI = { localH } + -- Unused +-MA local localA, localB ++MA local _localA, _localB + + -- Used + local localC = 1 + print(localC) + + -- Mutated, but never read + local localD = 1 + localD = 2 + localD = 3 + + -- Read, mutated, read + local localE = 1 + print(localE) + localE = 2 + print(localE) + + -- Read, mutated, unread + local localF = 1 + print(localF) + localF = 2 + + -- Called function + local localG = function() end + localG() + + -- Put into a table + local localH = 1 +-MA local localI = { localH } ++MA local _localI = { localH } diff --git a/selene-lib/tests/lints/unused_variable/overriding.fixed.diff b/selene-lib/tests/lints/unused_variable/overriding.fixed.diff index 0c85012a..a123944a 100644 --- a/selene-lib/tests/lints/unused_variable/overriding.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/overriding.fixed.diff @@ -1,28 +1,28 @@ - local a = 1 - - -- Variables defined inside the function should still lint --local function foo() -+local function _foo() - local b = 1 - if true then - b = b + 1 - - local c = 1 - if true then - c = c + 1 - end - end - - local d = 1 - return function() - return d - end, function() - d = d + 1 - end - end - - return function() - return a - end, function(arg) - a = arg - end + local a = 1 + + -- Variables defined inside the function should still lint +-MA local function foo() ++MA local function _foo() + local b = 1 + if true then + b = b + 1 + + local c = 1 + if true then + c = c + 1 + end + end + + local d = 1 + return function() + return d + end, function() + d = d + 1 + end + end + + return function() + return a + end, function(arg) + a = arg + end diff --git a/selene-lib/tests/lints/unused_variable/types.fixed.diff b/selene-lib/tests/lints/unused_variable/types.fixed.diff index 6774b006..6b2b1367 100644 --- a/selene-lib/tests/lints/unused_variable/types.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/types.fixed.diff @@ -1,4 +1,4 @@ - local types = require(script.types) - --local value: types.something -+local _value: types.something + local types = require(script.types) + +-MA local value: types.something ++MA local _value: types.something diff --git a/selene-lib/tests/lints/unused_variable/varargs.fixed.diff b/selene-lib/tests/lints/unused_variable/varargs.fixed.diff index a492f9dc..6de494b0 100644 --- a/selene-lib/tests/lints/unused_variable/varargs.fixed.diff +++ b/selene-lib/tests/lints/unused_variable/varargs.fixed.diff @@ -1,10 +1,10 @@ - local function foo(...) - call(...) - end - --local function bar(...) -+local function _bar(...) - call(...) - end - - foo() + local function foo(...) + call(...) + end + +-MA local function bar(...) ++MA local function _bar(...) + call(...) + end + + foo()