English | Русский | Українська | 简体中文 | 繁體中文
Yes, the name literally describes the stack — a Tree-sitter grammar written in Rust.
We put JASS front and center to draw attention (and nostalgia), and of course, we fully support it.
The plugin collects various tools for working with classic WarCraft III content, offering syntax support, editor features, and a few modern conveniences along the way.
JASS — .j, .pld, .ai
The primary language of WarCraft III scripting. Full support based on a dedicated tree-sitter-jass grammar.
AngelScript — .as
AngelScript support for UJAPI-based WarCraft III modding. Grammar — tree-sitter-as.
BNI — .bni
BNI (Blizzard Notation Ini) — a structured configuration format used in Warcraft III modding.
Grammar — tree-sitter-bni.
Built-in image viewer for the BLP texture format used by WarCraft III.
Built-in table editor for the SLK (SYLK) spreadsheet format used by WarCraft III for game data. Displays the data in an interactive canvas-based grid with resizable columns, sorting, and configurable hidden columns. Settings (column widths, hidden columns, etc.) are persisted directly in the file. Switching between table view and text view is available via the editor title bar.
Built-in viewer for DOO placement files (war3map.doo, war3mapUnits.doo).
Displays unit/doodad placements, positions, rawcodes, and cliff decorations in a structured table.
Built-in viewer for W3E terrain files (war3map.w3e).
Renders the terrain heightmap with 3D preview (Three.js), texture transitions, layer heights, water/blight/boundary/ramp overlays, wireframe grid, and cursor-info bar.
Supports both palette-based and real texture rendering (when game path is configured).
See docs/w3e/terrain.md for format details.
Built-in viewer for W3I map information files (war3map.w3i).
Displays map metadata: name, author, players, forces, camera bounds, fog/weather settings, random groups, and more.
Built-in archive viewer/browser for MPQ archives, including WarCraft III map (.w3x, .w3m) and campaign (.w3n) files.
Provides a virtual file system to browse and open files inside the archive directly from the VS Code explorer.
Syntax support for WTS (WarCraft III Trigger Strings) files used for localization.
The extension ships a standalone Rust-based LSP server (Linux, macOS, Windows) that provides:
| Feature | JASS | AngelScript | BNI |
|---|---|---|---|
| Semantic highlighting | ✅ | ✅ | ✅ |
| Folding ranges | ✅ | ✅ | ✅ |
| Document symbols | ✅ | ✅ | ✅ |
| Diagnostics | ✅ | ✅ | — |
| Go to definition | ✅ | ✅ | — |
| Find all references | ✅ | ✅ | — |
| Document highlight | ✅ | ✅ | — |
| Rename | ✅ | ✅ | — |
| Hover | ✅ | ✅ | — |
| Completion | ✅ | ✅ | — |
| Inlay hints | ✅ | ✅ | — |
| Document links | ✅ | ✅ | — |
| Code actions | ✅ | — | — |
| Formatting | ✅ | — | — |
| Color picker | ✅ | — | — |
JASS files can be linked together using special comment-based directives:
//import path/to/file.j
//import! blizzard/common.j
//import-ujapi! ujapi/common.j
//import— links another file into a shared scope. All top-level declarations (functions, globals, types, natives) become available.//import!— frozen import. Same as//import, but the target file is treated as read-only and will not be modified by refactoring or auto-rename.//import-ujapi!— UjAPI frozen import. Downloads and imports a UjAPI file. If the file does not exist locally, a code action is offered to download it.
Directives must appear at the very beginning of the file, before any language statements.
- Path completion — autocomplete for file paths after
//import. - Ctrl+Click — opens the imported file in the editor.
- Invalid path diagnostics — non-existent paths are highlighted as errors.
- Auto-update on rename/move — when an imported file is renamed or moved, paths in all referencing files are automatically rewritten.
- Cross-platform paths —
/and\are interchangeable; supports relative, absolute, and Windows-style (C://) paths. - Cycle detection — circular imports are detected and reported.
//set hint ref type
//set build-jass ./out/war3map.j
//set build-as ./out/war3map.as
//set backup ./backup
| Key | Values | Description |
|---|---|---|
hint |
ref type |
Inlay hints to display. ref — reference-ID hints (debug symbol resolution), type — type-annotation hints (e.g. : integer, : constant real array). Without the directive only ujapi hints are shown. |
build-jass |
<path> |
Output path for the JASS build. Merges the entire import tree into a single .j file. If the path is a directory, war3map.j is appended. When the path points to a .w3x / .w3m archive, the script is injected directly into the map. |
build-as |
<path> |
Output path for the AngelScript build. Same merge logic, but emits .as syntax. Reserved-word conflicts are resolved by appending a numeric suffix. When the path points to a .w3x / .w3m archive, the script is injected directly into the map. |
backup |
<path> |
Backup directory for the map archive before build injection. A date-prefixed copy (YYYY_MM_DD_FileName.w3x) is saved before modifying the archive. |
//entry
//import common/natives.j
//set build-jass ./out/war3map.j
The //entry directive marks a file as the root of the build and tree-shaking scope.
- The build starts from an
//entryfile. The//set build-jass///set build-asdirectives are only honoured in entry files. - Only files transitively reachable via
//importfrom an entry point are included in the build output. - Only
main/configfunctions declared in entry-point files are considered live roots for unused-function analysis. - If no
//entrydirectives exist in the project, the old behaviour is preserved: allmain/configfunctions are treated as entry points everywhere.
//ignore unused leak
The //ignore directive suppresses entire categories of diagnostics for the whole file. It must appear at the beginning of the file, alongside //import and //set.
Multiple tags can be listed on one line, separated by spaces. Supported tags are the same as for //@ignore (see below).
Lines starting with //* directly above a declaration are treated as doc comments (Markdown). They appear in hover tooltips and completion details.
//* Spawns a unit at the given position.
//* Returns the created unit handle.
function SpawnUnit takes integer id, real x, real y returns unit
// ...
endfunction
Multiple consecutive //* lines are joined. The prefix //* (with a trailing space) is stripped; //*text is also accepted.
A //@ignore comment placed directly above a function, variable, type, or native declaration suppresses the listed diagnostic tags for that specific declaration.
//@ignore unused
function HelperFunc takes nothing returns nothing
// No "Unused function" diagnostic will be reported for HelperFunc.
endfunction
//@ignore tag1 tag2 ...
Tags are space-separated. Currently supported tags:
| Tag | Suppresses |
|---|---|
unused |
"Unused function" hint |
leak |
Handle-leak diagnostic — local handle-type variables not nullified before function exit |
cycle |
Cyclic call chain diagnostic |
//@ignore can be combined with //* doc comments in any order:
//* Internal helper — not called directly.
//@ignore unused
function InternalHelper takes nothing returns nothing
endfunction
All files linked by //import form a connected component — a shared global scope:
- Scope resolver — persistent O(1) name lookup across all imported files, preserved between server restarts.
- Two-phase resolution — Phase 1 resolves symbols locally; Phase 2 links unresolved references against imported symbols.
- Export diffing — only re-parses dependent files when the set of exported declarations actually changes.
- Push diagnostics — errors are reported for affected files immediately, even if they are not open in the editor.
The server builds a function call graph across the connected component:
- Unused function detection — functions not reachable from
main/configentry points are flagged. - Cycle detection — cyclic call chains are reported via diagnostics.
- Topological sort — used by the build system to ensure callees appear before callers (required by JASS).
A D3.js-powered Call Graph panel is available via the editor title bar button.
JASS does not run destructors on local variables. If a local handle-type variable holds a non-null reference when the function exits, the underlying object is never released — a handle leak.
The server performs data-flow analysis on every function body to detect handle variables not nullified (set v = null) before every exit point (return and implicit endfunction).
- Per-variable quick fix — a code action inserts
set v = nullbefore the return. - Fix all leaks — a single code action fixes all handle leaks in the file.
- Suppressed with
//@ignore leak(per-function) or//ignore leak(whole file).
A D3.js-powered Import Graph panel shows the dependency tree of the current file. Available via the editor title bar button. All visualization assets are bundled — no internet connection required.
The //set build-jass <path> and //set build-as <path> directives trigger a build that:
- Collects all files in the import tree.
- Performs topological sort on functions.
- Merges everything into a single output file: types → globals → functions →
main. - Skips
nativedeclarations and type definitions (they are engine-provided). - Bare top-level call expressions are folded into
main.
All heavy data structures are serialized to disk via bincode and restored on server restart:
- Import graph — file dependency graph (petgraph-based).
- Scope resolver — global symbol index.
- Symbol cache — per-file function/variable/type declarations.
- Reference cache — per-file reference maps.
This means near-instant startup even for large projects.
- Tree-sitter — incremental parsing for all supported grammars.
ParseSnapshot— atomic immutable snapshot of all LSP data per file, stored inArc<ParseSnapshot>for lock-free concurrent reads.CancellationToken— per-file cancellation: new edits abort stale parse tasks immediately.- DashMap — concurrent file store for all snapshots.
- petgraph — import graph and call graph analysis.
All commands are available via the editor title bar buttons, but you can also assign custom keyboard shortcuts.
Open Keyboard Shortcuts (Ctrl+K Ctrl+S / ⌘K ⌘S), search for the command name, and bind any key combination.
| Command ID | Description |
|---|---|
importGraph.show |
Show Import Graph |
callGraph.show |
Show Call Graph |
typeGraph.show |
Show Type Graph |
rescan.execute |
Rescan All Files |
build.execute |
Build (JASS / AngelScript) |
ujapi.download |
Download UjAPI common.j |
jass.restartServer |
Restart JASS LSP Server |
mpq.browse |
Browse MPQ Archive |
mpq.openFile |
Open File from MPQ Archive |
slk.openTable |
Open SLK as Table |
slk.openText |
Open SLK as Text |
Alternatively, add bindings directly to keybindings.json (Ctrl+Shift+P → Preferences: Open Keyboard Shortcuts (JSON)):
[
{ "key": "ctrl+shift+i", "command": "importGraph.show", "when": "resourceLangId == jass || resourceLangId == angelscript" },
{ "key": "ctrl+shift+g", "command": "callGraph.show", "when": "resourceLangId == jass || resourceLangId == angelscript" },
{ "key": "ctrl+shift+t", "command": "typeGraph.show", "when": "resourceLangId == jass || resourceLangId == angelscript" },
{ "key": "ctrl+shift+r", "command": "rescan.execute", "when": "resourceLangId == jass || resourceLangId == angelscript" },
{ "key": "ctrl+shift+b", "command": "build.execute", "when": "resourceLangId == jass || resourceLangId == angelscript" }
]