Skip to content
Renaud "Ellypse" Parize edited this page Mar 14, 2018 · 5 revisions

My setup to work on add-ons for World of Warcraft

Here's how I setup my computer and my development environment to work on my add-ons for World of Warcraft. Use the informations in this document as you see fit, this is in no way a one solution fit all thing and there surely are ways to improve this.

Note: This document was made on macOS. While the tools I use are cross platformed (mainly because I have to use Windows from time to time), some menu names or shortcut may differ on Windows.

IntelliJ IDEA

First, I use IntelliJ IDEA by JetBrains as my IDE. It is a big ass IDE that eats a lot of RAM and will use a lot of CPU when it parses many files, in exchange for a buttload of nice features and helper thingies.

I use the ultimate edition of IntelliJ IDEA to get all the advanced integration that I also use for work, but the free community edition should work exactly the same. Both are available on IntelliJ IDEA's download page.

Note: I'm gonna use "IntelliJ" to refer to "IntelliJ IDEA" as it is shorter and is often called that way anyway.

IntelliJ's initial setup

I like to disable everything in IntelliJ when I first install it on a computer. It comes with a lot of useless plugins enabled by default. During the setup process I disable the offered plugins, but it still has a bunch of them enabled by default that we will want to disable manually. You can access IntelliJ's plugins preferences using the Configure menu in the bottom right corner on the launch screen.

I uncheck everything in the Plugins preferences to start fresh. You can make it show only enabled plugins using the Show menu next to the search bar, making it easy to disable all plugins as you can just spam unchecking the first plugin in the list until there are no plugins left.

The IntelliJ plugins we do want

To work on World of Warcraft add-ons, we need a Lua and XML plugins, and we also want the Git integration and some other nice plugins to help use code. All the plugins I will list are available either as a built-in module in the list or via the "Browse repositories…" button in the Plugins preferences.

EmmyLua

EmmyLua is the main plugin we will be using. Unlike Sylvanaar's Lua plugin it is recent and frequently updated, and is amazing at parsing all project files and libraries to offer code completion. If your own code is well documented, it helps a lot in getting parameters hint and auto-completion too. Search for "EmmyLua" in the repositories of plugins.

Git Integration

The Git Integration built-in module will show lines modified since the last commit in a different color in the gutter, color modified and added files in the project files view, even allows advanced workflow like selecting a few lines of code and right-click to get the Git history of these specific lines of code, to see when and who changed them.

IntelliLang

IntelliLang is a built-in module used to "inject" other languages into string. For example, in our XML files we will have script handlers that will contain Lua code. IntelliLang will allow us to hit Alt + Enter when inside the text to inject (tell IntelliJ to use) the Lua language. All the features for that specific language will be available inside the fragment of text (syntax color, code completion, etc.). It is also great when you have strings that are actually HTML or Markdown (note: you need to have the plugins for HTML or Markdown for them to be used in this case).

Project setup

To get correct code completion of the game's API and UI functions, we need to setup the API and the UI source code export as libraries for our projects.

Open the folder for your add-on in IntelliJ using the Open option from the launch screen. (Do not create a new project, unless you actually want to start a new add-on from scratch)

Then navigate to the "Project Structure…" menu.

In the Project Structure window go to the SDKs tab and select the Lua SDK that came with EmmyLua. We will want to add the game's UI source code and the game's API as libraries of this SDK, by clicking on the little + button at the bottom of the frame and picking where those files are located on your machine.

To get the game's UI source code you can either export the files from your installation manually or clone an existing repository of the files maintained by someone else (like me or Gethe). This will give use code completion for the functions defines in the UI code, and the UI.xsd file exported will also provide completion and hints when writing XML files.

To get the game's API you can use my IntelliJ-IDEA-Lua-IDE-WoW-API. The files of this project globally declares the functions of the game, with some documentation. All was exported from the Wowprogramming website, and some informations may be out of date, but I try to maintain the project and improve it. The projects also defines the widgets are global objects, with their method, so that typing a variable as a specific widget will give method completion for that widget type.

Note: If you need help starting up with Git you can check this guide on how to use GitHub with SourceTree, one of the main Git client for Windows

You then have to indicate that this project uses the Lua SDK in the Project tab of the Project Structure window.

Validate the changes by clicking the OK button. The libraries should be visible in the Project side pannel.

Usage and specificities

Variables types

EmmyLua will try to guess the types of the variable. When using CreateFrame() for example, it will assume the variable that store the return value of the function call will be a Frame and offer method completion for the Frame widget. But if we created a Button using CreateFrame() we can indicate to EmmyLua the type of the variable using the ---@type Type annotation.

Note that the IntelliJ-IDEA-Lua-IDE-WoW-API uses the inheritance feature annotation provided by EmmyLua to offer method completion for all the types inherited by a widget type (like Frame, Region, ParentedObject etc. for a Button for example).

You can declare your own types using the ---@class MyClass to get your own code completion when dealing with mixins or classes. You can inherit one class (sad limitation of EmmyLua) by adding : InheritedClassName after your new class.

Use Command + Click or Ctrl + Click on a variable to jump to its declaration, and Command + Click or Ctrl + Click on its declaration to find its usage everywhere in the code.

Function documentation

EmmyLua uses some kind of LuaDoc tags (with some oddities) to comment functions parameters and return values. You can use ---@param optional parameterName parameterType @ Parameter documentation to document function parameters, and ---@return returnType1, returnType2, returnType3 variableName1, variableName2, variableName3 @ Return documentation to document return value (the variable names are used for code completion).

If you allow multiple usage of your function, like completely different arguments, you can overload the function to get code completion for every possible usage of the function using the ---@overload fun(arg1:arg1Type, arg2:arg2Type):returnType tag.

Table fields completion

EmmyLua will look for the usage of global and local tables accross your entire project to offer code completion for its fields.

However, it will fail to pick up tables in multiple levels deep if the field is first declared in the table and then imported locally. New fields added to this local reference will not picked up. It is better to declare locally the table first and then add it as a field of the shared table.

XML completion

The XSD is read to provide completion for new XML elements and for some of the element's attribute values.

Because the XSD is complex and not always up to date, be aware that you might get errors indicating that some elements cannot be place under some elements. Some of these errors can be ignored (especially if it actually works anyway).

To inject the Lua language in the Script handlers inside the XML files, have the text cursor in the text and use the Alt + Enter shortcut to show the Intentions popup and choose the "Insert language or reference" option and pick Lua.

Navigate IntelliJ IDEA

Here are some quick tips to quickly navigate IntelliJ IDEA:

  • The one you should absolutely remember: Command + Shift + A (or Ctrl + Shift + A) to search for an action/menu in the programm it self. Don't remember the keyboard shortcut to replace all occurences of a text in the entire project and don't know where to look in the menus? Hit Command + Shift + A and use fuzzy search to find it, like typing rep in p.
  • Quickly look for a file/class: hit the Shift key twice quickly to open the Search Everywhere window. The first file in the search results will be the files recently opened.
  • Act upon something: if you see something that is underliend in red or yellow, or highlighted, or in grey text, you can use the Alt + Enter shortcut to open the Intentions popup that will show actions you might want to take upon the text (remove unused variable, rename a duplicate variable).
  • When you have an error you don't want to see ever again (for example, by default IntelliJ will try to guess typoes in words and underline the), you can use the Intentions popup using Alt + Enter, but instead of picking an option, use the right arrow key to open the option's sub-menu and choose Disable inspection.
  • Refactor a variable name: instead of changing a variable name and looking for every places it was use, you can refactor variable names using the Shift + F6 key. IntelliJ will look for all usage of the variable name (even in comments if you check the box for it) and change the name everywhere.