User:Egingell/Fix deprecated variables

From Warcraft Wiki
Jump to navigation Jump to search

Fixing addons after the removal of the magic global variables this and argX and replacing the removed getglobal function.

Details

As you may know, these variables and function have been removed as of patch 4.0.1. Here are some details on how to fix your addon (or someone else's).

Errors Messages

1. There will be an error message to the effect of "Attempt to reference global variable "this" a nil value" or "Attempt to call global function "getglobal" a nil value." These errors will come with line numbers; as with the error, "[AddOn\Addon.lua:59] Attempt to call global function "getglobal" a nil value," which is directing you to line 59 of the file "AddOn\Addon.lua").
2. If your addon doesn't throw errors, then you don't need this.
3. Just because you get only one error, doesn't mean you only have one line to fix. Conversely, 900 errors doesn't necessarily mean there are 900 lines to fix. 4. Just because you don't get any error messages, doesn't necessarily mean you don't need to fix it.

getglobal

There are two ways to approach this fix:
1. Create a local function named getglobal and return the entry from the _G table.

local function getglobal(var)
    return _G[var]
end

2. Replace all instances of getglobal("var name") with _G["var name"].

  • Note: getglobal is defined by Blizzard in the file FrameXML/UIParent.lua, so there's no need to fix it; however, it's more efficient to use the _G table directly than call a function that does the same thing.

this

There are numerous renditions of this variable:
1. Look in any XML files for the <Scripts>...</Scripts> section (there may be many).
1a. If the script in question looks like this ("Before"), alter it to look like it does in "After" and find the matching function header in the Lua file adding "this" as the first parameter.

Before

<Scripts>
    <OnLoad>
        FunctionName()
    </OnLoad>
</Scripts>

After

<Scripts>
    <OnLoad>
        FunctionName(self)
    </OnLoad>
</Scripts>

1b. If it looks like this, then you don't need to do anything in the XML file.

<Scripts>
    <OnLoad function="FunctionName" />
</Scripts>

2. Look in any Lua files for functions that use this in them and add it to the functions parameter list. There are various other ways to do it, but this is the simplest and easiest to explain.

Before

function FunctionName()
    this:MethodName()
    this.MemberName = "stuff"
end

After

function FunctionName(this)
    this:MethodName()
    this.MemberName = "stuff"
end

3. If the XML contains this, change them to self.

Before

<Scripts>
    <OnLoad>
        this:FunctionName()
    </OnLoad>
</Scripts>

After

<Scripts>
    <OnLoad>
        self:FunctionName()
    </OnLoad>
</Scripts>

argX

This is a pain in the butt because not all argX variables were removed, just the global ones (nice, huh?).

1. Look in any XML files for references to argX (arg1, arg2, etc.) and replace them all with the appropriate variable name. To find out what that variable name is, this article lists many of them. For example, OnClick uses button and down (arg1 and arg2 respectively).
2. OnEvent now uses local argX variables as opposed to previously using the globals, so there's no need to change them other than following the steps below.
3. Follow the steps in the #this section to fix stray argX variables. These parameters must come after this or event, if applicable, as in the following example.

In the XML - Before

<Scripts>
    <OnClick>
        FunctionName(self, arg1, arg2)
    </OnClick>
</Scripts>

After

<Scripts>
    <OnClick>
        FunctionName(self, button, down)
    </OnClick>
</Scripts>

If not an OnEvent handler

function FunctionName(this, arg1, arg2, arg3, arg4, _, arg6) -- one for every one needed in sequence including ''_'' for unused ones.
    this:MethodName(arg2, arg3, arg4, arg6)
    this.MemberName = arg1
end

If an OnEvent handler

function FunctionName(this, event, arg1, arg2, arg3, arg4, _, arg6) -- one for every one needed in sequence including ''_'' for unused ones.
    if event == "EVENT" then
        this:MethodName(arg2, arg3, arg4, arg6)
        this.MemberName = arg1
    end
end

Other things you can do

varargs

varargs are a construct that makes a list of values in the order they were passed to a function. You can change every function header in your Lua files (or XML files if you declared functions in them) to use the vararg expression.

If not an OnEvent handler

function FunctionName(...)
    local this, arg1, arg2, arg3, arg4, _, arg6 = ...
    this:MethodName(arg2, arg3, arg4, arg6)
    this.MemberName = arg1
end

If an OnEvent handler

function FunctionName(...)
    local this, event, arg1, arg2, arg3, arg4, _, arg6 = ...
    if event == "EVENT" then
        this:MethodName(arg2, arg3, arg4, arg6)
        this.MemberName = arg1
    end
end

However, it is common practice and good form to only use vararg for argX. Like the following.

If not an OnEvent handler

function FunctionName(this, ...)
    local arg1, arg2, arg3, arg4, _, arg6 = ...
    this:MethodName(arg2, arg3, arg4, arg6)
    this.MemberName = arg1
end

If an OnEvent handler

function FunctionName(this, event, ...)
    local arg1, arg2, arg3, arg4, _, arg6 = ...
    if event == "EVENT" then
        this:MethodName(arg2, arg3, arg4, arg6)
        this.MemberName = arg1
    end
end