WeakAuras

WeakAuras

206M Downloads

funky custom variable names aren't handled gracefully.

emptyrivers opened this issue ยท 0 comments

commented

Describe the bug

This breaks conditions :(
image

To Reproduce

The easy way: Import this aura, observe.

From scratch:

  1. Create any non-group aura, go to Trigger Tab.
  2. Create a TSU trigger.
  3. Add a custom variable with state key that starts with a number, contains a space, semicolon, parenthesis, or any other format that would require writing the key in quotes with brackets.
  4. Create a condition which checks the variable you created. Notice the compile error reported in the print stream.

Additional Info

The error looks to be sourced here - note that every use of condition.variable in the generated code uses dot notation, when to be fully general it should use bracket notation:

local function CreateTestForCondition(uid, input, allConditionsTemplate, usedStates)
local trigger = input and input.trigger;
local variable = input and input.variable;
local op = input and input.op;
local value = input and input.value;
local check = nil;
local recheckCode = nil;
if (variable == "AND" or variable == "OR") then
local test = {};
if (input.checks) then
for i, subcheck in ipairs(input.checks) do
local subtest, subrecheckCode = CreateTestForCondition(uid, subcheck, allConditionsTemplate, usedStates);
if (subtest) then
tinsert(test, "(" .. subtest .. ")");
end
if (subrecheckCode) then
recheckCode = recheckCode or "";
recheckCode = recheckCode .. subrecheckCode;
end
end
end
if (next(test)) then
if (variable == "AND") then
check = table.concat(test, " and ");
else
check = table.concat(test, " or ");
end
end
end
if (trigger and variable) then
usedStates[trigger] = true;
local conditionTemplate = allConditionsTemplate[trigger] and allConditionsTemplate[trigger][variable];
local cType = conditionTemplate and conditionTemplate.type;
local test = conditionTemplate and conditionTemplate.test;
local preamble = conditionTemplate and conditionTemplate.preamble;
local stateCheck = "state[" .. trigger .. "] and state[" .. trigger .. "].show and ";
local stateVariableCheck = "state[" .. trigger .. "]." .. variable .. "~= nil and ";
local preambleString
if preamble then
WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {}
WeakAuras.conditionHelpers[uid].preambles = WeakAuras.conditionHelpers[uid].preambles or {}
tinsert(WeakAuras.conditionHelpers[uid].preambles, preamble(value));
local preambleNumber = #WeakAuras.conditionHelpers[uid].preambles
preambleString = string.format("WeakAuras.conditionHelpers[%q].preambles[%s]", uid, preambleNumber)
end
if (test) then
if (value) then
WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {}
WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {}
tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, test);
local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions);
local valueString = type(value) == "string" and string.format("%q", value) or value;
local opString = type(op) == "string" and string.format("%q", op) or op;
check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state[%s], %s, %s, %s)",
uid, testFunctionNumber, trigger, valueString, (opString or "nil"), preambleString or "nil");
end
elseif (cType == "customcheck") then
if value then
local customCheck = WeakAuras.LoadFunction("return " .. value, "custom check")
if customCheck then
WeakAuras.conditionHelpers[uid] = WeakAuras.conditionHelpers[uid] or {}
WeakAuras.conditionHelpers[uid].customTestFunctions = WeakAuras.conditionHelpers[uid].customTestFunctions or {}
tinsert(WeakAuras.conditionHelpers[uid].customTestFunctions, customCheck);
local testFunctionNumber = #(WeakAuras.conditionHelpers[uid].customTestFunctions);
check = string.format("state and WeakAuras.CallCustomConditionTest(%q, %s, state)",
uid, testFunctionNumber, trigger);
end
end
elseif cType == "alwaystrue" then
check = "true"
elseif (cType == "number" and value and op) then
local v = tonumber(value)
if (v) then
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. op .. v;
end
elseif (cType == "timer" and value and op) then
if (op == "==") then
check = stateCheck .. stateVariableCheck .. "abs(state[" .. trigger .. "]." ..variable .. "- now -" .. value .. ") < 0.05";
else
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. "- now" .. op .. value;
end
elseif (cType == "select" and value and op) then
if (tonumber(value)) then
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. op .. tonumber(value);
else
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. op .. "'" .. value .. "'";
end
elseif (cType == "bool" and value) then
local rightSide = value == 0 and "false" or "true";
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. "==" .. rightSide
elseif (cType == "string" and value) then
if(op == "==") then
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. " == [[" .. value .. "]]";
elseif (op == "find('%s')") then
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. ":find([[" .. value .. "]], 1, true)";
elseif (op == "match('%s')") then
check = stateCheck .. stateVariableCheck .. "state[" .. trigger .. "]." .. variable .. ":match([[" .. value .. "]], 1, true)";
end
end
if (cType == "timer" and value) then
recheckCode = " nextTime = state[" .. trigger .. "] and state[" .. trigger .. "]." .. variable .. " and (state[" .. trigger .. "]." .. variable .. " -" .. value .. ")\n";
recheckCode = recheckCode .. " if (nextTime and (not recheckTime or nextTime < recheckTime) and nextTime >= now) then\n"
recheckCode = recheckCode .. " recheckTime = nextTime\n";
recheckCode = recheckCode .. " end\n"
end
end
return check, recheckCode;
end