From 3a7aa91b33617bccf63e60de18e54f5fd068303b Mon Sep 17 00:00:00 2001 From: Mads Jans <90150876+ViTeXFTW@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:18:13 +0200 Subject: [PATCH 1/4] fix: flag unreachable upgraded locomotor sets (#39) --- crates/analysis/src/diagnostics.rs | 24 ++++++++++---- crates/analysis/tests/spec/DeadCodeTest.ini | 31 +++++++++++++++++++ .../tests/spec/DeadCodeTest.spec.toml | 23 ++++++++++++++ 3 files changed, 72 insertions(+), 6 deletions(-) diff --git a/crates/analysis/src/diagnostics.rs b/crates/analysis/src/diagnostics.rs index 4804115..0c46ee5 100644 --- a/crates/analysis/src/diagnostics.rs +++ b/crates/analysis/src/diagnostics.rs @@ -629,12 +629,10 @@ impl<'a> Ctx<'a> { false } - /// Block-local dead-code check: a `WeaponSet`/`ArmorSet` carrying the - /// `PLAYER_UPGRADE` condition is only ever selected after a module on the - /// *same* object sets that flag (WeaponSetUpgrade / the TransportContain - /// family with armed passengers; ArmorUpgrade for armor). Both sides live - /// in the same top-level block, so the check is sound under the per-block - /// diagnostics cache. Skipped for map.ini-style override blocks + /// Block-local dead-code check for conditional weapon, armor, and locomotor + /// sets. Both the set and its selecting module live in the same top-level + /// block, so the check is sound under the per-block diagnostics cache. + /// Skipped for map.ini-style override blocks /// (`AddModule`/`RemoveModule`/`ReplaceModule` present): those are /// partial definitions. fn check_set_reachability(&mut self, node: &SyntaxNode) { @@ -688,6 +686,20 @@ impl<'a> Ctx<'a> { if is_override_patch { return; } + if !module_names.iter().any(|m| m == "LocomotorSetUpgrade") { + for tok in Block(node.clone()) + .fields() + .filter(|f| f.key().is_some_and(|k| k.text() == "Locomotor")) + .filter_map(|f| f.value_tokens().first().cloned()) + .filter(|t| t.text().eq_ignore_ascii_case("SET_NORMAL_UPGRADED")) + { + self.warning( + &tok, + "unreachable-set", + "this locomotor set requires `LocomotorSetUpgrade` — the set can never be selected".to_string(), + ); + } + } let has_player_upgrade_weapon_set = player_upgrade_sets.iter().any(|(kw, _)| *kw == "WeaponSet"); if !has_player_upgrade_weapon_set { diff --git a/crates/analysis/tests/spec/DeadCodeTest.ini b/crates/analysis/tests/spec/DeadCodeTest.ini index f665baa..7118391 100644 --- a/crates/analysis/tests/spec/DeadCodeTest.ini +++ b/crates/analysis/tests/spec/DeadCodeTest.ini @@ -54,6 +54,31 @@ Object DeadCodeOverride End End +; SET_NORMAL_UPGRADED is selected only after LocomotorSetUpgrade calls +; setLocomotorUpgrade(true). Without that module, this field is dead. +Object DeadCodeBadLocomotor + Locomotor = SET_NORMAL DeadCodeNormalLocomotor + Locomotor = SET_NORMAL_UPGRADED DeadCodeUpgradedLocomotor + Behavior = AIUpdateInterface ModuleTag_AI + End +End + +Object DeadCodeGoodLocomotor + Locomotor = SET_NORMAL DeadCodeNormalLocomotor + Locomotor = SET_NORMAL_UPGRADED DeadCodeUpgradedLocomotor + Behavior = AIUpdateInterface ModuleTag_AI + End + Behavior = LocomotorSetUpgrade ModuleTag_LocomotorUpgrade + TriggeredBy = Upgrade_DeadCodeTest + End +End + +; map.ini-style override patches may inherit LocomotorSetUpgrade: never flagged. +Object DeadCodeLocomotorOverride + RemoveModule ModuleTag_99 + Locomotor = SET_NORMAL_UPGRADED DeadCodeUpgradedLocomotor +End + Weapon DeadCodeTestGun PrimaryDamage = 10.0 End @@ -65,3 +90,9 @@ End Upgrade Upgrade_DeadCodeTest BuildTime = 1.0 End + +Locomotor DeadCodeNormalLocomotor +End + +Locomotor DeadCodeUpgradedLocomotor +End diff --git a/crates/analysis/tests/spec/DeadCodeTest.spec.toml b/crates/analysis/tests/spec/DeadCodeTest.spec.toml index b1ccb79..3b81a9e 100644 --- a/crates/analysis/tests/spec/DeadCodeTest.spec.toml +++ b/crates/analysis/tests/spec/DeadCodeTest.spec.toml @@ -20,3 +20,26 @@ severity = "warning" code = "unreachable-set" on = "PLAYER_UPGRADE" nth = 3 + +# DeadCodeBadLocomotor's upgraded set has no LocomotorSetUpgrade module. +[[diag]] +severity = "warning" +code = "unreachable-set" +on = "SET_NORMAL_UPGRADED" +nth = 1 + +# A matching upgrade module makes the upgraded locomotor reachable. +[[diag]] +severity = "warning" +code = "unreachable-set" +on = "SET_NORMAL_UPGRADED" +nth = 2 +absent = true + +# Partial override definitions may inherit the module from their base object. +[[diag]] +severity = "warning" +code = "unreachable-set" +on = "SET_NORMAL_UPGRADED" +nth = 3 +absent = true From 2f531a3af750437081f18fc8e9e4aeb0b5409cdc Mon Sep 17 00:00:00 2001 From: Mads Jans <90150876+ViTeXFTW@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:20:26 +0200 Subject: [PATCH 2/4] docs: prepare release documentation (#43) --- .github/ISSUE_TEMPLATE/config.yml | 2 +- AGENTS.md | 10 +- CONTRIBUTING.md | 5 +- README.md | 244 ++++++++---------------------- SECURITY.md | 6 +- SUPPORT.md | 4 +- docs/README.md | 11 ++ docs/diagnostics.md | 67 ++++++++ docs/language-server.md | 68 +++++++++ docs/release.md | 14 +- docs/vscode-development.md | 44 ++++++ editors/vscode/README.md | 97 +++++++----- 12 files changed, 342 insertions(+), 230 deletions(-) create mode 100644 docs/README.md create mode 100644 docs/diagnostics.md create mode 100644 docs/language-server.md create mode 100644 docs/vscode-development.md diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index b762ff3..8ef8618 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,5 +1,5 @@ blank_issues_enabled: true contact_links: - name: Support - url: https://github.com/ViTeXFTW/ZeroSyntaxV2/blob/main/SUPPORT.md + url: https://github.com/ViTeXFTW/ZeroSyntaxV2/blob/dev/SUPPORT.md about: Read where to ask support questions before opening an issue. diff --git a/AGENTS.md b/AGENTS.md index dd8e2b9..f3f7033 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -195,14 +195,14 @@ take `absent = true` to pin that a diagnostic is *not* emitted. ### Editor client `editors/vscode/` is a thin reference LSP client (claims the `generals-ini` -language id). The server speaks stdio LSP, so Neovim/Helix/Zed configs are in -the README. `GeneralsCode/` is the engine source the schema is modeled on (a -reference for hand-authoring `schema.json`) — it is not part of any crate. +language id). The server speaks stdio LSP; client setup is documented in +`docs/language-server.md`. `GeneralsCode/` is the engine source the schema is +modeled on (a reference for hand-authoring `schema.json`) — it is not part of +any crate. ## Conventions -- License is **GPL-3.0-or-later** (matches the engine source the schema - derives from); keep crate headers consistent. +- License is **MIT**. - `schema.json` is hand-written — edit the JSON directly, modeling new entries on the engine's `FieldParse` tables in `GeneralsCode/`. Keep `value_type`s faithful and fall back to `Unknown { parse_fn }` when a type is unclear. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 3d2c084..4cc11cb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,7 +14,7 @@ cargo clippy --locked --all-targets --all-features -- -D warnings cd editors/vscode npm ci -npm run compile +npm test ``` The optional real-game corpus is not committed. Fetch it only when you need the @@ -43,4 +43,5 @@ describe the workflow the feature should improve. ## Releases -Maintainers release from tags. See [docs/release.md](docs/release.md). +Maintainers release from the `dev` and `prod` branches. See the +[release process](docs/release.md). diff --git a/README.md b/README.md index f44042e..111424c 100644 --- a/README.md +++ b/README.md @@ -4,201 +4,81 @@ [![Release](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/release.yml/badge.svg)](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/release.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) -ZeroSyntax v2 is a language server and VS Code extension for the INI files used by -*Command & Conquer: Generals - Zero Hour*. It gives modders and map authors -editor support for the game's object, weapon, upgrade, FX, audio, module, and -map override definitions. - -The project is built around an IDE-agnostic Language Server Protocol (LSP) -binary, `zerosyntax-lsp`, plus a reference VS Code extension. The analyzer uses a -hand-maintained schema modeled on the game's INI parsing tables, so diagnostics -and completions follow the structure the engine actually expects instead of -treating the files as generic INI. - -## Features - -- Diagnostics for unknown blocks, fields, modules, invalid values, - unterminated blocks, unresolved references, duplicate module tags, and - unreachable upgrade-conditioned sets. -- Context-aware completions for block names, field names, module slots, module - types, enum values, bitflags, and workspace definitions. -- Hover, go to definition, find references, rename, workspace symbol search, - document symbols, and folding ranges. -- Semantic highlighting for Generals INI syntax and schema-aware tokens. -- Quick fixes for common issues such as missing `End` statements, misspelled - enum values, unresolved references, and suppressing diagnostics. -- Optional formatter for indentation normalization. -- Incremental document updates and cached diagnostics for large game files. -- Reference VS Code extension with bundled syntax highlighting and LSP client - integration. - -## Supported platforms - -Release assets are built for Windows x64 and Linux x64. Other platforms can -build from source with Rust and Node.js. - -## Getting Started - -Install the latest platform-specific VS Code extension package from -[GitHub Releases](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases), then open a -Zero Hour `.ini` file. The extension activates for the `generals-ini` language -and starts the bundled language server automatically. - -Formatting is off by default. Enable it with `zerosyntax.format.enable` when you -want the server to advertise document formatting to VS Code. - -For map/solo.ini diagnostics and W3D model/bone completions, set -`zerosyntax.baseIniRoots` to game or mod directories and/or `.big` archives. -INI definitions are treated as already loaded before the map file; W3D assets -are indexed for model and bone checks. - -### Standalone language server - -Release assets also include the standalone `zerosyntax-lsp` binary. Any editor -with generic LSP support can run that binary over stdio for `.ini` files. Pass -these initialization options if you want formatting or base INI roots: +ZeroSyntax v2 brings modern editor support to the INI scripting files used by +*Command & Conquer: Generals – Zero Hour*. It helps modders and map authors find +mistakes early and navigate large game or mod workspaces. -```json -{ - "format": { "enable": true }, - "baseIniRoots": ["C:/Games/Zero Hour", "C:/Mods/MyMod/Data/INI", "C:/Mods/MyMod.big"] -} -``` +The project includes the IDE-independent `zerosyntax-lsp` language server and a +VS Code extension with the server bundled. -## Development +## What you get -```sh -cargo test --locked -cargo fmt --all --check -cargo clippy --locked --all-targets --all-features -- -D warnings +- Schema-aware diagnostics and quick fixes for blocks, fields, modules, values, + references, module tags, and missing `End` statements. +- Context-aware completion for INI keywords, enum values, flags, and definitions + in your workspace. +- Hover information, go to definition, find references, rename, workspace and + document symbols, and folding. +- Semantic highlighting for Generals INI files. +- Optional indentation formatting, disabled by default so existing files are + never reformatted without your consent. +- Base-game and mod indexing for `map.ini` and `solo.ini`, including W3D model + and bone checks. -cd editors/vscode -npm ci -npm run compile -``` +## Install the VS Code extension -The optional `GeneralsCode/`, `corpus/`, and `examples/` directories are local -inputs only and are intentionally not committed. Generated binaries, -`node_modules`, compiled extension output, and `.vsix` packages are also ignored. - -See [CONTRIBUTING.md](CONTRIBUTING.md) for pull request guidance and -[docs/release.md](docs/release.md) for the release process. - -## Common Editor Setup - -### Neovim - -```lua -local configs = require("lspconfig.configs") -local lspconfig = require("lspconfig") - -if not configs.zerosyntax then - configs.zerosyntax = { - default_config = { - cmd = { "zerosyntax-lsp" }, - filetypes = { "generals_ini" }, - root_dir = lspconfig.util.root_pattern(".git", "*.ini"), - single_file_support = true, - init_options = { - format = { enable = false }, - baseIniRoots = { "C:/Games/Zero Hour" }, - }, - }, - } -end - -lspconfig.zerosyntax.setup({}) -``` +ZeroSyntax supports Windows x64 and Linux x64 release builds. -## Diagnostic Suppression +1. Download the `.vsix` for your platform from the + [latest GitHub release](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases/latest). +2. In VS Code, open **Extensions**, choose **Views and More Actions …**, + select **Install from VSIX…**, and open the downloaded file. +3. Open your mod or map folder, then open an `.ini` file. -Suppress a diagnostic for one file with a file-scope comment: +The extension treats `.ini` files as **Generals INI**. If a workspace also +contains unrelated INI files, use VS Code's `files.associations` setting to +limit that language association to the appropriate folders. -```ini -; zerosyntax-disable: unresolved-reference, unreachable-set -``` +See the [VS Code extension guide](editors/vscode/README.md) for settings and +troubleshooting. + +## Use the standalone language server -Use the diagnostic code shown by your editor. Multiple codes can be separated by -spaces or commas, and multiple pragma lines accumulate. Unknown suppression codes -are reported so typos do not silently hide problems. The old -`; zerosyntax-disable:` spelling remains supported for existing files. - -## Feature Showcase - -### Diagnostic codes - -ZeroSyntax v2 reports stable diagnostic codes so warnings can be searched, -suppressed, or tracked consistently: - -| Code | Meaning | -| --- | --- | -| `syntax` | The file cannot be parsed cleanly, such as a missing `End`. | -| `stray-field` | A field appears outside a valid block or module. | -| `unknown-block` | A top-level block name is not known to the Generals INI schema. | -| `overrides` | A map override redefines an existing object-style definition. | -| `duplicate-definition` | The same definition is declared more than once. | -| `unreachable-set` | A `WeaponSet` or `ArmorSet` uses upgrade conditions without the trigger module needed to activate it. | -| `unknown-field` | A field is not valid in the current block or module. | -| `missing-module-tag` | A module is missing its required `ModuleTag_*` name. | -| `unknown-module` | A module type is not known for the current module slot. | -| `missing-condition` | A conditional state block is missing its condition token. | -| `missing-value` | A field requires a value but none was provided. | -| `bad-bool` | A boolean field is not `Yes` or `No`. | -| `non-positive` | A value must be greater than zero. | -| `bad-percent` | A percentage value is malformed or out of range. | -| `bad-color` | A color value is malformed. | -| `bad-coord` | A coordinate value is malformed. | -| `bad-number` | A numeric field does not contain a valid number. | -| `bad-enum` | A value is not a member of the expected enum set. | -| `bad-flag` | A bitflag value is not a member of the expected flag set. | -| `unresolved-reference` | A field references a definition that is not found in the workspace. | -| `unknown-suppression` | A `zerosyntax-disable` comment names a code that does not exist. | -| `module-wrong-slot` | A module type is used under the wrong slot. | -| `duplicate-module-tag` | Two modules in the same object use the same module tag. | -| `editor-default-module` | A placeholder/default module value should be replaced before shipping. | - -### Quick fixes - -Supported quick fixes appear in the editor's lightbulb/code action menu: - -| Quick fix | When it appears | -| --- | --- | -| Insert missing `End` | A block or module is unterminated. | -| Replace with `` | An enum or bitflag value is close to a known valid value. | -| Create stub ` ` | A reference points to a missing definition that can be scaffolded safely. | -| Remove unreachable `WeaponSet` / `ArmorSet` | An upgrade-conditioned set can never activate. | -| Insert `WeaponSetUpgrade` / `ArmorUpgrade` trigger module | An object has an unreachable upgrade-conditioned set and needs a trigger module. | -| Suppress `` in this file | A warning or hint is intentional for the current file. | - -### Example - -```ini -; zerosyntax-disable: unresolved-reference - -Weapon DemoCannon - PrimaryDamage = lots ; bad-number - DeathType = EXPLODDED ; quick fix: Replace with `EXPLODED` - FireFX = DemoMissingFX ; suppressed unresolved-reference -End - -Object DemoTank - Behavior = PhysicsBehavior ModuleTag_01 - End - - WeaponSet - Conditions = PLAYER_UPGRADE - Weapon = PRIMARY DemoCannon - End ; unreachable-set -End +Download the `zerosyntax-lsp` archive for your platform from the +[latest release](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases/latest), +extract it, and configure your editor to run the binary over stdio. + +See the [language server guide](docs/language-server.md) for initialization +options and editor integration details. + +## Configure map and model checks + +For complete `map.ini` and `solo.ini` diagnostics, set +`zerosyntax.baseIniRoots` in VS Code to the base game or mod directories and/or +`.big` archives that load before the map. The same setting also enables W3D +model and bone completion and validation. + +```json +{ + "zerosyntax.baseIniRoots": [ + "C:/Games/Zero Hour", + "C:/Mods/MyMod/Data/INI", + "C:/Mods/MyMod.big" + ] +} ``` -In this example, ZeroSyntax v2 can flag the invalid number, suggest the corrected -death flag, suppress the intentionally missing FX reference, and offer either to -remove the unreachable `WeaponSet` or insert the matching trigger module. +## Documentation + +- [Diagnostics, suppression, and quick fixes](docs/diagnostics.md) +- [Standalone language server setup](docs/language-server.md) +- [Contributing](CONTRIBUTING.md) +- [Support](SUPPORT.md) +- [Security policy](SECURITY.md) -## License +## License and trademarks -ZeroSyntax v2 is licensed under the MIT License. See [LICENSE](LICENSE). +ZeroSyntax v2 is available under the [MIT License](LICENSE). ZeroSyntax v2 is an unofficial community project and is not affiliated with, endorsed by, or sponsored by Electronic Arts. Command & Conquer and related diff --git a/SECURITY.md b/SECURITY.md index 62ac90d..09b592c 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -6,9 +6,9 @@ Security fixes target the latest released version of ZeroSyntax v2. ## Reporting a vulnerability -Please do not open a public issue for vulnerabilities. Report security issues by -emailing the maintainer listed on the GitHub repository profile, or by using -GitHub private vulnerability reporting if it is enabled for the repository. +Please do not open a public issue for vulnerabilities. Use +[GitHub private vulnerability reporting](https://github.com/ViTeXFTW/ZeroSyntaxV2/security/advisories/new) +or email the maintainer listed on the GitHub repository profile. Include: diff --git a/SUPPORT.md b/SUPPORT.md index dd2ff2b..165e183 100644 --- a/SUPPORT.md +++ b/SUPPORT.md @@ -1,6 +1,8 @@ # Support -Use GitHub issues for reproducible bugs and focused feature requests. Or write a message in the discord server [ZeroSyntax](https://discord.gg/FShKq5s2hH) +Use [GitHub Issues](https://github.com/ViTeXFTW/ZeroSyntaxV2/issues) for +reproducible bugs and focused feature requests. For questions, join the +[ZeroSyntax Discord server](https://discord.gg/FShKq5s2hH). Before opening an issue: diff --git a/docs/README.md b/docs/README.md new file mode 100644 index 0000000..774863b --- /dev/null +++ b/docs/README.md @@ -0,0 +1,11 @@ +# Documentation + +- [Diagnostics, suppression, and quick fixes](diagnostics.md) +- [Standalone language server setup](language-server.md) +- [VS Code extension development](vscode-development.md) +- [Release process](release.md) + +Community and repository policies remain at the repository root so GitHub can +discover them automatically: [contributing](../CONTRIBUTING.md), +[support](../SUPPORT.md), [security](../SECURITY.md), and the +[code of conduct](../CODE_OF_CONDUCT.md). diff --git a/docs/diagnostics.md b/docs/diagnostics.md new file mode 100644 index 0000000..9ebd112 --- /dev/null +++ b/docs/diagnostics.md @@ -0,0 +1,67 @@ +# Diagnostics and quick fixes + +ZeroSyntax reports stable diagnostic codes. Use the code shown by your editor +when searching for an issue or suppressing an intentional warning. + +## Suppress a diagnostic in one file + +Add a file-scope comment before the first INI block: + +```ini +; zerosyntax-disable: unresolved-reference, unreachable-set +``` + +Separate multiple codes with spaces or commas. Multiple file-scope pragma lines +accumulate. A misspelled code produces `unknown-suppression` instead of silently +hiding nothing. + +Suppressions are intended for warnings and hints that are valid for a specific +file. Fix error-level syntax and schema problems rather than suppressing them. + +## Diagnostic codes + +| Code | Meaning | +| --- | --- | +| `syntax` | The file cannot be parsed cleanly, such as when an `End` is missing. | +| `stray-field` | A field appears outside a valid block or module. | +| `unknown-block` | A top-level block is not in the Generals INI schema. | +| `overrides` | A map layer redefines an existing object-style definition. | +| `duplicate-definition` | The same definition is declared more than once. | +| `map-forward-reference` | A map or solo INI references a definition declared later in that file, after the point where the game needs it. | +| `map-projectile-object` | A weapon uses a map-defined projectile object that the game cannot resolve reliably. | +| `unreachable-set` | A `WeaponSet` or `ArmorSet` cannot activate, or an upgrade module has no matching set. | +| `unknown-field` | A field is not valid in the current block or module. | +| `missing-module-tag` | A module is missing its required `ModuleTag_*` name. | +| `unknown-module` | A module type is not known for the current module slot. | +| `missing-condition` | A conditional state block is missing its condition token. | +| `missing-value` | A field requires a value but none was provided. | +| `bad-bool` | A boolean is not `Yes` or `No`. | +| `non-positive` | A value that must be greater than zero is not. | +| `bad-percent` | A percentage is malformed or outside its allowed range. | +| `bad-color` | A color value is malformed. | +| `bad-coord` | A coordinate value is malformed. | +| `bad-number` | A numeric field does not contain a valid number. | +| `bad-enum` | A value is not a member of the expected enum. | +| `bad-flag` | A bitflag is not a member of the expected flag set. | +| `bad-prefixed` | A tagged value does not use its required `Prefix:value` form. | +| `unresolved-reference` | A referenced definition is not found in the workspace or configured base INI roots. | +| `unknown-model` | A model name is not found in the indexed W3D assets. | +| `unknown-model-member` | A bone or subobject is not found in the models active in that scope. | +| `unknown-suppression` | A `zerosyntax-disable` comment names an unknown code. | +| `module-wrong-slot` | A module type is used under the wrong slot. | +| `duplicate-module-tag` | Two modules in one object use the same module tag. | +| `editor-default-module` | A placeholder module value should be replaced before shipping. | + +## Quick fixes + +Open your editor's lightbulb or code-action menu on a diagnostic to see the +available fix. + +| Quick fix | When it appears | +| --- | --- | +| Insert missing `End` | A block or module is unterminated. | +| Replace with a known value | An enum or bitflag is close to a valid value. | +| Create a stub definition | A reference points to a missing definition that can be scaffolded safely. | +| Remove an unreachable `WeaponSet` or `ArmorSet` | An upgrade-conditioned set can never activate. | +| Insert a matching upgrade module or set | An object has only one side of an upgrade-conditioned weapon or armor setup. | +| Suppress a code in this file | A warning or hint is intentional for the current file. | diff --git a/docs/language-server.md b/docs/language-server.md new file mode 100644 index 0000000..8248f40 --- /dev/null +++ b/docs/language-server.md @@ -0,0 +1,68 @@ +# Standalone language server + +Use `zerosyntax-lsp` with any editor that supports the Language Server Protocol +over stdio. + +## Install + +1. Download the Windows x64 or Linux x64 server archive from the + [latest release](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases/latest). +2. Verify the archive against `SHA256SUMS.txt` from the same release. +3. Extract the archive and put `zerosyntax-lsp` (or `zerosyntax-lsp.exe`) on + your `PATH`, or configure its absolute path in your editor. +4. Register the server for the Generals/Zero Hour `.ini` files in your project. + +The server writes protocol messages to stdout, so clients must launch it using +stdio rather than a TCP port. + +## Client configuration + +Configure your LSP client with: + +| Option | Value | +| --- | --- | +| Command | `zerosyntax-lsp` | +| Transport | stdio | +| Files | Zero Hour `.ini` files | +| Workspace root | Your map or mod directory | + +The server indexes INI files under each workspace folder. Open the whole project +to enable cross-file completion, definitions, references, rename, and workspace +symbols. + +## Initialization options + +```json +{ + "format": { "enable": false }, + "baseIniRoots": [ + "C:/Games/Zero Hour", + "C:/Mods/MyMod/Data/INI", + "C:/Mods/MyMod.big" + ] +} +``` + +- `format.enable` controls whether the server advertises document formatting. + It defaults to `false`. +- `baseIniRoots` accepts directories and `.big` archives containing base game + or mod INI files and W3D assets. Those INI definitions are treated as loaded + before `map.ini` and `solo.ini`. + +Restart the language server after changing initialization options. + +## Supported LSP features + +ZeroSyntax supports incremental document sync, diagnostics, completion, hover, +go to definition, references, rename, semantic tokens, document and workspace +symbols, folding ranges, quick fixes, and optional document formatting. + +## Build from source + +Install Rust 1.75 or newer, clone the repository, and run: + +```sh +cargo build --locked --release -p zerosyntax-server +``` + +The binary is written to `target/release/zerosyntax-lsp` (`.exe` on Windows). diff --git a/docs/release.md b/docs/release.md index cbf9a36..2f3161f 100644 --- a/docs/release.md +++ b/docs/release.md @@ -36,10 +36,14 @@ cargo clippy --locked --all-targets --all-features -- -D warnings cd editors/vscode npm ci -npm run compile +npm test cd ../.. ``` +Review the root README, extension README, and files under `docs/` whenever a +release changes installation, settings, supported platforms, or user-visible +behavior. + The release workflow repeats CI and the real-corpus gate before building any release assets. @@ -68,6 +72,14 @@ configured. If `prod` contains changes that are not in `dev`, the workflow stops before building and asks for `prod` to be merged back into `dev` first. +## After release + +Verify that the GitHub Release contains both server archives, both +platform-specific `.vsix` files, and `SHA256SUMS.txt`. Install the matching +`.vsix` in a clean VS Code profile and open a Generals INI file. For a live +release, confirm the same version appears in the Marketplace when publishing is +enabled. + ## Repository settings - Keep `dev` as the default branch so the manual workflow is available. diff --git a/docs/vscode-development.md b/docs/vscode-development.md new file mode 100644 index 0000000..bdcba98 --- /dev/null +++ b/docs/vscode-development.md @@ -0,0 +1,44 @@ +# VS Code extension development + +These instructions are for contributors. Users should install a platform +package from [GitHub Releases](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases/latest). + +## Build and test + +From the repository root: + +```sh +cargo build --locked -p zerosyntax-server + +cd editors/vscode +npm ci +npm test +``` + +To debug the extension, open `editors/vscode` in VS Code and press F5. +The repository's launch configuration points the Extension Development Host at +the locally built debug server. + +## Choose a server binary + +The extension resolves the server in this order: + +1. `zerosyntax.server.path`. +2. The `ZEROSYNTAX_LSP_PATH` environment variable used by development tooling. +3. `editors/vscode/server/zerosyntax-lsp[.exe]`. +4. `zerosyntax-lsp` on `PATH`. + +## Package locally + +Build the release server, copy it into `editors/vscode/server`, then package the +extension: + +```sh +cargo build --locked --release -p zerosyntax-server +cd editors/vscode +npm ci +npm run package +``` + +The release workflow performs the platform-specific binary staging and VSIX +target selection automatically. See the [release process](release.md). diff --git a/editors/vscode/README.md b/editors/vscode/README.md index 7e5ab1d..9919f8f 100644 --- a/editors/vscode/README.md +++ b/editors/vscode/README.md @@ -1,52 +1,79 @@ -# ZeroSyntax v2 — VS Code extension +# ZeroSyntax v2 for VS Code -Reference editor client for the ZeroSyntax v2 language server (see the project -root README for the full architecture). -Provides diagnostics, completions, hover, go-to-definition, and schema-aware -semantic highlighting for C&C Generals: Zero Hour `.ini` files. +ZeroSyntax adds diagnostics, completion, navigation, refactoring, semantic +highlighting, and quick fixes for *Command & Conquer: Generals – Zero Hour* INI +files. The platform-specific extension package includes the language server, so +there is nothing else to install. -The server itself is IDE-agnostic; this extension is just a thin client that -launches it and speaks LSP. +## Install -## Build +1. Download the `.vsix` for Windows x64 or Linux x64 from the + [latest release](https://github.com/ViTeXFTW/ZeroSyntaxV2/releases/latest). +2. In VS Code, open **Extensions**, choose **Views and More Actions …**, then + select **Install from VSIX…**. +3. Open the downloaded file and reload VS Code if prompted. +4. Open your map or mod folder and start editing an `.ini` file. + +You can also install from a terminal: ```sh -cd editors/vscode -npm install -npm run compile +code --install-extension zerosyntax-vscode--.vsix ``` -## Provide the server binary +## Recommended setup -Build the server from the workspace root and make it discoverable in one of -these ways (checked in order): +Open the folder containing your project rather than a single file. ZeroSyntax +indexes the workspace so definitions, references, rename, and completion work +across its INI files. -1. Set `zerosyntax.server.path` to the absolute path of `zerosyntax-lsp`. -2. Copy the binary to `editors/vscode/server/zerosyntax-lsp[.exe]` (bundled into - the `.vsix`). -3. Put `zerosyntax-lsp` on your `PATH`. +When editing `map.ini` or `solo.ini`, configure **ZeroSyntax v2: Base Ini Roots** +with any game or mod folders and `.big` archives that load before the map. This +prevents false unresolved-reference warnings and enables W3D model and bone +checks. -```sh -cargo build --release -p zerosyntax-server -# option 2: -mkdir -p editors/vscode/server -cp target/release/zerosyntax-lsp* editors/vscode/server/ -``` +## Settings -## Run / debug +| Setting | Default | Purpose | +| --- | --- | --- | +| `zerosyntax.baseIniRoots` | `[]` | Base game/mod directories and `.big` archives used for map and model checks. | +| `zerosyntax.format.enable` | `false` | Enables indentation formatting. Changing it restarts the server. | +| `zerosyntax.server.path` | empty | Uses a custom `zerosyntax-lsp` binary instead of the bundled one. | +| `zerosyntax.trace.server` | `off` | Logs LSP traffic for troubleshooting. | -Open this folder in VS Code and press F5 to launch an Extension -Development Host, then open any `.ini` file recognized as **Generals INI**. +Formatting is intentionally off by default. Enable it only when you want +**Format Document** or format-on-save to normalize indentation. -## Package +## INI file association -```sh -npm run package # produces zerosyntax-vscode-.vsix (needs @vscode/vsce) +The extension associates `.ini` files with **Generals INI**. If your workspace +also contains unrelated INI files, keep those as plain text and override the +association only for the folders you want ZeroSyntax to handle: + +```json +{ + "files.associations": { + "**/*.ini": "plaintext", + "Data/INI/**/*.ini": "generals-ini", + "Maps/**/*.ini": "generals-ini" + } +} ``` -## Note on `.ini` association +Use the language selector in VS Code's status bar to change an individual file. + +## Troubleshooting + +- If the server cannot be found, reinstall the `.vsix` for your platform. A + source checkout does not contain a bundled server until it is built. +- If map references are reported as missing, configure + `zerosyntax.baseIniRoots` and check that the paths point to the required INI + folders or `.big` archives. +- For detailed logs, set `zerosyntax.trace.server` to `messages` or `verbose`, + reproduce the problem, then open **Output → ZeroSyntax v2 Language Server**. + +Report reproducible problems through +[GitHub Issues](https://github.com/ViTeXFTW/ZeroSyntaxV2/issues) with a minimal +INI sample, your OS, VS Code version, and ZeroSyntax version. -This extension claims the `.ini` extension under the `generals-ini` language id. -If you also edit unrelated `.ini` files, scope it per workspace with -`files.associations`, e.g. only treat files under your mod folder as -`generals-ini`. +Contributor build and packaging instructions are in the +[VS Code development guide](https://github.com/ViTeXFTW/ZeroSyntaxV2/blob/dev/docs/vscode-development.md). From c3846a7634feb94cf79a08d472d5c512ebe007a9 Mon Sep 17 00:00:00 2001 From: Mads Jans <90150876+ViTeXFTW@users.noreply.github.com> Date: Thu, 16 Jul 2026 10:48:03 +0200 Subject: [PATCH 3/4] chore: add project icon (#44) --- .gitignore | 1 + README.md | 4 ++++ editors/vscode/package.json | 3 ++- icon/ZeroSyntaxLogo256.png | Bin 0 -> 59798 bytes 4 files changed, 7 insertions(+), 1 deletion(-) create mode 100644 icon/ZeroSyntaxLogo256.png diff --git a/.gitignore b/.gitignore index b99d825..880081c 100644 --- a/.gitignore +++ b/.gitignore @@ -13,6 +13,7 @@ editors/vscode/out editors/vscode/out-test editors/vscode/*.vsix editors/vscode/server +editors/vscode/icon/ # Reference game source (large, external) /GeneralsCode diff --git a/README.md b/README.md index 111424c..8a8cfda 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,9 @@ # ZeroSyntax v2 +

+ ZeroSyntax logo +

+ [![CI](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/ci.yml/badge.svg)](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/ci.yml) [![Release](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/release.yml/badge.svg)](https://github.com/ViTeXFTW/ZeroSyntaxV2/actions/workflows/release.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE) diff --git a/editors/vscode/package.json b/editors/vscode/package.json index 5acd556..0931a33 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -9,6 +9,7 @@ "url": "https://github.com/ViTeXFTW/ZeroSyntaxV2" }, "publisher": "ViTeXFTW", + "icon": "icon/ZeroSyntaxLogo256.png", "engines": { "vscode": "^1.84.0" }, @@ -80,7 +81,7 @@ "compile": "tsc -p ./", "compile:test": "tsc -p ./tsconfig.test.json", "watch": "tsc -watch -p ./", - "vscode:prepublish": "npm run compile", + "vscode:prepublish": "node -e \"const fs=require('fs');fs.mkdirSync('icon',{recursive:true});fs.copyFileSync('../../icon/ZeroSyntaxLogo256.png','icon/ZeroSyntaxLogo256.png')\" && npm run compile", "package": "vsce package --allow-missing-repository", "test": "npm run compile && npm run compile:test && node ./out-test/src/test/runTest.js" }, diff --git a/icon/ZeroSyntaxLogo256.png b/icon/ZeroSyntaxLogo256.png new file mode 100644 index 0000000000000000000000000000000000000000..137e0d9fc928e1f612b013573106132dcb460152 GIT binary patch literal 59798 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 z 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

FA+^1NISe5lNfHf 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 Date: Thu, 16 Jul 2026 10:54:05 +0200 Subject: [PATCH 4/4] chore: bump minor version --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cd1151e..5f73db6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1528,7 +1528,7 @@ dependencies = [ [[package]] name = "zerosyntax-analysis" -version = "1.0.5" +version = "1.1.0" dependencies = [ "criterion", "rowan", @@ -1540,7 +1540,7 @@ dependencies = [ [[package]] name = "zerosyntax-schema" -version = "1.0.5" +version = "1.1.0" dependencies = [ "serde", "serde_json", @@ -1548,7 +1548,7 @@ dependencies = [ [[package]] name = "zerosyntax-server" -version = "1.0.5" +version = "1.1.0" dependencies = [ "anyhow", "dashmap 6.2.1", @@ -1567,7 +1567,7 @@ dependencies = [ [[package]] name = "zerosyntax-syntax" -version = "1.0.5" +version = "1.1.0" dependencies = [ "criterion", "logos", diff --git a/Cargo.toml b/Cargo.toml index 236dcf6..1884462 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,7 @@ resolver = "2" members = ["crates/schema", "crates/syntax", "crates/analysis", "crates/server"] [workspace.package] -version = "1.0.5" +version = "1.1.0" edition = "2021" license = "MIT" repository = "https://github.com/ViTeXFTW/ZeroSyntaxV2"