You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
132 lines
4.9 KiB
132 lines
4.9 KiB
|
|
local detailsFramework = DetailsFramework
|
|
|
|
if (not detailsFramework or not DetailsFrameworkCanLoad) then
|
|
return
|
|
end
|
|
|
|
local unpack = unpack
|
|
local CreateFrame = CreateFrame
|
|
local geterrorhandler = geterrorhandler
|
|
local wipe = wipe
|
|
|
|
local parseCodeForNamedLocalFunctions = function(codeBlock, startIndex, listOfFunctionsFound)
|
|
local nestedLevel = 0
|
|
local endIndex = startIndex
|
|
local currentQuote = ""
|
|
---@type number for the 'function' keyword, need to ignore the one that started the 'local function' capture
|
|
local ignoreFunctionIndex = startIndex + 6
|
|
|
|
---@type boolean
|
|
local bFoundEnd = false
|
|
---@type boolean
|
|
local bIsInString = false
|
|
---@type boolean
|
|
local bIsInComment = false
|
|
|
|
while (endIndex <= #codeBlock) do
|
|
local char = string.sub(codeBlock, endIndex, endIndex)
|
|
|
|
--check if the character is inside a comment
|
|
if (char == "-") then
|
|
local nextChar = string.sub(codeBlock, endIndex + 1, endIndex + 1)
|
|
if nextChar == "-" then
|
|
bIsInComment = true
|
|
end
|
|
|
|
elseif (char == "\n") then
|
|
bIsInComment = false
|
|
end
|
|
|
|
if (not bIsInComment) then
|
|
--check if it is inside a string
|
|
if (char == "'" or char == '"') then
|
|
if (not bIsInString) then
|
|
bIsInString = true
|
|
currentQuote = char
|
|
|
|
elseif (bIsInString and currentQuote == char) then
|
|
bIsInString = false
|
|
currentQuote = ""
|
|
end
|
|
end
|
|
|
|
if (not bIsInString) then
|
|
--check if the word starts with "i", "f", "d" or "e"
|
|
if (char == "i") then
|
|
local nextChars = string.sub(codeBlock, endIndex, endIndex + 1)
|
|
if (nextChars == "if") then
|
|
nestedLevel = nestedLevel + 1
|
|
end
|
|
|
|
elseif (char == "f") then
|
|
local nextChars = string.sub(codeBlock, endIndex, endIndex + 7)
|
|
--also check if the index isn't the one that started the 'local function' capture
|
|
if (nextChars == "function" and endIndex ~= ignoreFunctionIndex) then
|
|
nestedLevel = nestedLevel + 1
|
|
end
|
|
|
|
--for 'do' keyword, used by for and while and also by the 'do' keyword itself creating a block
|
|
elseif (char == "d") then
|
|
local nextChars = string.sub(codeBlock, endIndex, endIndex + 1)
|
|
if (nextChars == "do") then
|
|
nestedLevel = nestedLevel + 1
|
|
end
|
|
|
|
elseif (char == "e") then
|
|
local nextChars = string.sub(codeBlock, endIndex, endIndex + 2)
|
|
if (nextChars == "end") then
|
|
if (nestedLevel > 0) then
|
|
--reduce the nested level by 1
|
|
nestedLevel = nestedLevel - 1
|
|
else
|
|
--if the nested level is zero then the end of the function got found
|
|
bFoundEnd = true
|
|
endIndex = endIndex + 2 --adjust endIndex to include the 'end' keyword
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
endIndex = endIndex + 1
|
|
end
|
|
|
|
if (bFoundEnd) then
|
|
---@type string get the function body
|
|
local functionBody = string.sub(codeBlock, startIndex, endIndex)
|
|
table.insert(listOfFunctionsFound, functionBody)
|
|
return endIndex
|
|
end
|
|
end
|
|
|
|
---search a code block for named local functions and bring them to the top of the code block
|
|
---this is useful for when you want to call a function before it's defined
|
|
---same thing as been implemented in Lua 5.2 but not in WoW Lua
|
|
---@param codeBlock string
|
|
function detailsFramework:BringNamedLocalFunctionToTop(codeBlock)
|
|
---@type string[]
|
|
local listOfFunctionsFound = {}
|
|
---@type number|nil
|
|
local startIndex = string.find(codeBlock, "local function")
|
|
|
|
while startIndex do
|
|
startIndex = parseCodeForNamedLocalFunctions(codeBlock, startIndex, listOfFunctionsFound)
|
|
if (not startIndex) then
|
|
break
|
|
end
|
|
startIndex = string.find(codeBlock, "local function", startIndex + 1)
|
|
end
|
|
|
|
for i = #listOfFunctionsFound, 1, -1 do
|
|
local thisMatch = listOfFunctionsFound[i]
|
|
local blockStartIndex = thisMatch[2]
|
|
local blockEndIndex = thisMatch[3]
|
|
codeBlock = codeBlock:sub(1, blockStartIndex - 1) .. codeBlock:sub(blockEndIndex + 1)
|
|
end
|
|
|
|
for i = #listOfFunctionsFound, 1, -1 do
|
|
codeBlock = listOfFunctionsFound[i][1] .. "\n\n" .. codeBlock
|
|
end
|
|
end
|