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/.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/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/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" diff --git a/README.md b/README.md index f44042e..8a8cfda 100644 --- a/README.md +++ b/README.md @@ -1,204 +1,88 @@ # ZeroSyntax v2 +
+
+
` 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
-```
+## Documentation
-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.
+- [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/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
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).
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 0000000..137e0d9
Binary files /dev/null and b/icon/ZeroSyntaxLogo256.png differ