Skip to content

XML Frame Scanning ​

wowlua-ls automatically scans .xml files in your addon workspace, extracting frame and template definitions so the type system understands XML-defined globals and fields.

What it does ​

WoW addon XML files define UI frames, templates, and child elements. Without XML scanning, the language server would report false undefined-global diagnostics for frames created in XML and miss field completions for template-defined children.

When wowlua-ls scans an XML file, it extracts:

  • Virtual templates (virtual="true") become @class declarations: available for @type annotations and inheritance
  • Non-virtual named frames become both a class and a global variable: no undefined-global warning
  • parentKey children become typed fields on the parent frame's class
  • KeyValue elements become fields with their declared types (string, the default, number, boolean, and int as number). With type="global", the field takes the type of the global it names (e.g. value="MyAddon.FormatName")
  • inherits, mixin, and secureMixin attributes populate the parent class chain. Each mixin table also picks up the element type and parentKey children of the frames that use it, named or not
  • Mixin(self, MyMixin) calls in a frame's inline <OnLoad> handler count the same as a mixin attribute
  • Mixin names and handler functions (<OnClick function="MyAddon_OnClick"/>) are allowed globals: defining or reading them in Lua doesn't trigger create-global or undefined-global

Example ​

Given this XML:

xml
<Frame name="MyAddonFrame" virtual="true" mixin="MyAddonMixin">
    <Layers>
        <Layer level="BACKGROUND">
            <Texture parentKey="Background" />
        </Layer>
        <Layer level="ARTWORK">
            <FontString parentKey="Title" />
        </Layer>
    </Layers>
    <KeyValues>
        <KeyValue key="label" value="default" type="string" />
        <KeyValue key="count" value="0" type="number" />
    </KeyValues>
</Frame>

In your Lua code:

lua
---@type MyAddonFrame
local frame
frame.Background  -- Texture
frame.Title       -- FontString
frame.label       -- string
frame.count       -- number

Supported features ​

Template inheritance ​

Templates can inherit from other templates via inherits. The child gets all parent fields:

xml
<Button name="MyButton" virtual="true" inherits="MyAddonFrame">
    <HighlightTexture parentKey="Glow" />
</Button>

MyButton inherits Background, Title, label, and count from MyAddonFrame, plus its own Glow field.

$parent name resolution ​

Frame names containing $parent are resolved using the nearest named parent frame:

xml
<Frame name="PlayerFrame" parent="UIParent">
    <Frames>
        <Frame name="$parentText" parentKey="Text" />
    </Frames>
</Frame>

This creates a global PlayerFrameText and a Text field on PlayerFrame.

Intrinsic elements ​

Frames with intrinsic="true" define custom XML element types:

xml
<Button name="ActionButton" intrinsic="true" mixin="ActionButtonMixin" />

<!-- Usage creates a global with the ActionButton type -->
<ActionButton name="MainActionButton" parent="UIParent" />

Blizzard's own intrinsic elements (ItemButton, EventFrame, EventButton, DropDownToggleButton, ...) are recognized without a declaration in your XML.

parentArray fields ​

Child frames with parentArray create array-typed fields:

xml
<Frame name="ListFrame" virtual="true">
    <Frames>
        <Frame parentArray="Items" />
        <Frame parentArray="Items" />
    </Frames>
</Frame>
lua
---@type ListFrame
local list
list.Items  -- Frame[]

Supported element types ​

The scanner recognizes every frame, region, and animation element in the WoW UI schema and types it with its widget type, so a <PlayerModel parentKey="Portrait"> field is a PlayerModel with methods such as SetUnit:

CategoryElements
FramesFrame, Button, CheckButton, EditBox, ScrollFrame, StatusBar, Slider, Cooldown, GameTooltip, MessageFrame, ScrollingMessageFrame, Minimap, ColorSelect, SimpleHTML, Browser, MovieFrame, DropdownButton, and the other frame types in the schema
ModelsModel, ModelScene, ModelFFX, CinematicModel, DressUpModel, PlayerModel, TabardModel
TexturesTexture, MaskTexture, Line, and the widget textures (NormalTexture, PushedTexture, DisabledTexture, HighlightTexture, CheckedTexture, BarTexture, ThumbTexture, ...)
TextFontString, ButtonText, and header variants
AnimationAnimationGroup, Animation, Alpha, Scale, Translation, Rotation, Path, FlipBook, VertexColor, ...
FontFontFamily

Limitations ​

  • Dotted parentKey paths: A parentKey like "IconHitBox.IconBorder" sets a field on a nested child frame rather than the direct parent. These are silently skipped.
  • childKey: The childKey attribute (the inverse of parentKey - sets a field on the child pointing back to the parent) is not currently supported.
  • Inline <Script> code: Lua code embedded inside XML <Script> blocks is not parsed. Globals defined there (e.g. STANDARD_TEXT_FONT) won't be discovered unless they also appear in a .lua file.
  • <FontFamily> details: <FontFamily> elements create a Font class, but their <Member> children and font file references are not modeled.

No configuration needed ​

XML scanning is enabled by default. Any .xml files in your workspace are scanned automatically alongside .lua files.