Diagnostics
wowlua-ls ships 55+ diagnostics covering type safety, annotation correctness, code quality, and WoW-specific checks. Each one is individually suppressible and configurable.
How diagnostics work
Diagnostics run automatically as you type. They're grouped by severity:
- Warning — likely a bug or an annotation problem
- Hint — code quality suggestions, unused variables, style issues
Each diagnostic has a code (like type-mismatch or unused-local) that you use to suppress or configure it.
Suppressing diagnostics
Inline
Suppress a diagnostic on the same line by appending disable-line at the end:
local unused = computeSomething() ---@diagnostic disable-line: unused-localPrevious line
---@diagnostic disable-next-line: unused-local
local unused = computeSomething()Per-block
---@diagnostic disable: undefined-global
MY_GLOBAL = true
OTHER_GLOBAL = false
---@diagnostic enable: undefined-globalPer-project
In .wowluarc.json:
{
"diagnostics": {
"disable": ["inject-field", "unused-local"]
}
}LuaLS compatibility aliases
For compatibility with LuaLS suppress comments, these aliases are accepted:
| Alias | Maps to |
|---|---|
invisible | access-private, access-protected |
param-type-mismatch | type-mismatch |
return-type-mismatch | return-mismatch |
Type safety diagnostics
These catch type errors — the most valuable diagnostics for finding real bugs.
type-mismatch Warning
Argument type doesn't match the function's @param annotation:
---@param name string
function greet(name) end
greet(42) -- type-mismatch: expected string, got numberreturn-mismatch Warning
Return type doesn't match the function's @return annotation:
---@return string
function getName()
return 42 -- return-mismatch
endfield-type-mismatch Warning
Assignment to a field doesn't match its @field type:
---@class Config
---@field name string
---@type Config
local cfg = {}
cfg.name = 42 -- field-type-mismatchassign-type-mismatch Warning
Reassignment doesn't match the variable's @type annotation:
---@type string
local x = "hello"
x = 42 -- assign-type-mismatchgeneric-constraint-mismatch Warning
Generic argument doesn't satisfy the class constraint:
---@class Box<T: number|string>
---@type Box<boolean> -- generic-constraint-mismatch
local b = {}need-check-nil Warning Off by default
Field/method access on a possibly-nil value:
---@param name string?
function greet(name)
print(name:upper()) -- need-check-nil
endEnable in .wowluarc.json: "diagnostics": { "enable": ["need-check-nil"] }
grouped-return-mismatch Warning
Return values don't match any declared tuple-union case:
---@return (string, number) | (nil, nil)
function example()
return "hello", nil -- grouped-return-mismatch
endArgument diagnostics
missing-parameter Warning
Required argument not provided:
---@param a number
---@param b number
function add(a, b) end
add(1) -- missing-parameter: bredundant-parameter Warning
Extra arguments beyond what the function accepts:
---@param x number
function single(x) end
single(1, 2) -- redundant-parameterReturn diagnostics
missing-return-value Warning
Return with fewer values than declared:
---@return string, number
function getInfo()
return "hello" -- missing-return-value
endmissing-return Warning
Function with @return but no return statement on some paths:
---@return string
function getName()
if self.name then
return self.name
end
-- missing-return (falls off without returning)
endredundant-return-value Warning
Returning more values than declared:
---@return string
function getName()
return "hello", 42 -- redundant-return-value
endimplicit-nil-return Hint Off by default
Bare return in a function with all-optional @return types:
---@return string?
function maybeName()
if not self.loaded then return end -- implicit-nil-return
return self.name
endGlobal and field diagnostics
undefined-global Warning
Reference to an unresolved global name:
print(MyUnknownGlobal) -- undefined-globalSuppress with globals.read in .wowluarc.json for known external globals.
undefined-field Warning
Accessing a field that doesn't exist on a @class:
---@class Player
---@field name string
---@type Player
local p = {}
print(p.level) -- undefined-fieldinject-field Hint
Setting a field not declared on a @class:
---@class Player
---@field name string
---@type Player
local p = {}
p.level = 10 -- inject-fieldcreate-global Hint
Creating a global variable (assignment or function definition without local):
MyGlobal = true -- create-global
function GlobalFunc() end -- create-globalSuppress with globals.write in .wowluarc.json.
missing-fields Warning
Missing required fields when constructing a @class table:
---@class Config
---@field name string
---@field debug boolean
---@type Config
local cfg = { name = "test" } -- missing-fields: debugAnnotation diagnostics
undefined-doc-class Warning
Undefined parent in @class Foo : Parent:
---@class Child : NonexistentParent -- undefined-doc-classundefined-doc-name Warning
Undefined type name in any annotation:
---@param x NonexistentType -- undefined-doc-name
function foo(x) endundefined-doc-param Warning
@param name doesn't match any function parameter:
---@param nme string -- undefined-doc-param (typo: should be 'name')
function greet(name) endduplicate-doc-param / duplicate-doc-field / duplicate-doc-alias Warning
Duplicate annotation declarations.
circle-doc-class Warning
Circular inheritance chain:
---@class A : B
---@class B : A -- circle-doc-classmalformed-annotation Warning
Unknown or incomplete ---@ annotation.
unknown-diag-code Warning
Unknown code in @diagnostic directives.
Code quality diagnostics
unused-local Hint
Unreferenced local variable.
unused-function Hint
Unused function definition.
redefined-local Hint
Same-scope local variable redefinition.
unreachable-code / code-after-break Hint
Code after return or break.
deprecated Warning
Usage of a symbol marked @deprecated.
discard-returns Warning
Ignoring the return value of a @nodiscard function.
not-precedence Hint
not x < y parses as (not x) < y, which is almost certainly not what you meant.
count-down-loop Warning
Numeric for-loop step direction doesn't match start/end:
for i = 10, 1 do -- count-down-loop: needs step -1
print(i)
endStyle diagnostics
empty-block Hint
Empty if/while/for/repeat body. Suppressed if the body contains a comment.
redundant-return Hint
Bare return as the last statement of a function's top block.
trailing-space Hint
Line ends with whitespace.
WoW-specific diagnostics
wrong-flavor-api Warning
API call not available in all declared project flavors. See Flavor Filtering.
access-private / access-protected Warning
Accessing a private or protected field from outside its visibility scope.
Strict typing diagnostics Hint
These are off by default. They fire when the LS can't determine a type — enable them to find gaps in your annotation coverage:
| Code | Fires when |
|---|---|
unknown-param-type | Function parameter type can't be inferred |
unknown-return-type | Return value has no resolvable type |
unknown-local-type | local x = expr where expr type is unknown |
unknown-field-type | Field assignment with unknown RHS type |
Enable in .wowluarc.json:
{
"diagnostics": {
"enable": ["unknown-param-type", "unknown-return-type"]
}
}