Repository navigation
chore: combine the linter and language server in one workspace - #8
Merged
Merged
Conversation
Closed files are reduced to a compact symbol summary and only open documents keep a syntax tree, which keeps the resident set around 10 MB for a handful of resources. Types come from LuaCATS annotations, table shapes, natives and manifest-aware globals; the lint rules are shared with qbx-lint so the editor and CI agree.
…lazy library members Probing against ox_lib and qbx_core showed that their main tables were invisible: they are created through setmetatable, published with _ENV.name, extended from lazily loaded files and, for the ox_lib cache, filled through cache:set. A second index pass also settles types that depend on files indexed later.
The release profile aborted on panic, so a single bug would have killed the editor's server. Requests and notifications now run behind catch_unwind and answer with an internal error instead. scripts/stress.mjs fires every feature at random positions of every file in a workspace to find such bugs.
…x_lib cache keys Closed files are linted one at a time when the server is idle so the Problems panel covers the workspace, and a save or close only re-lints the resource it belongs to. Event name completion now only offers handlers the call can reach, lib.onCache and an onCache snippet list the cache keys found in the indexed ox_lib source, and qbx/fileInfo tells editors which side a file runs on.
…w completions The server now formats documents with qbx_lua_fmt, feeds the cross-file lint rules from its index (event and export arity, wrong side, security, dependencies, locale keys including unused keys reported on the JSON file), finds and renames fields and methods across related files by resolving each candidate's owner type, and completes locale keys, convars from code and .cfg files, and state bag keys.
… current resource Hovering a table now lists its fields with types and the short literal values remembered by the index. Global lookups no longer fall back to symbols of unrelated resources, and a table the resource fills itself is no longer merged with same-named tables of imported libraries, so Config means this resource's Config.
Calling an export of an escrowed resource was reported as unknown because only the readable Lua was considered. Resources are now opaque when they ship a .fxap marker, contain an encrypted file, run non-Lua scripts or register exports under computed names, and the cross-file rules stay silent about them. The escrow state is kept on the resource entry, which also makes a resource with an encrypted file but no marker count, as the linter already did. The encrypted fixture moves to its own resource so the shop fixture keeps exercising the cross-file rules.
Inside `if IsDuplicityVersion() then` of a client or shared file the server natives were hidden, because only the manifest side was used. Diagnostics pick the same narrowing up through the linter. The probe script now only records diagnostics of the probed document, prints the resolved side, and can print messages with PROBE_VERBOSE.
A snippet shared its label with the plain function and sorted after it, so accepting the first `CreateThread` only inserted the word. Snippets now sort ahead, are marked as such in the list and preview their body. CreateThread expands to the loop with Wait(0), which is what people want nearly every time; `CreateThread once` keeps the bare form and SetTimeout joins the list. onCache no longer needs ox_lib in the workspace (it falls back to the usual cache keys) and is also offered after `lib.`.
Signature help and inlay hints for TriggerServerEvent and friends only
knew the native's `...: any`, although the index already holds the
handler registered under the event name. They now show the native's
leading parameters followed by the handler's, and say where the handler
lives. lib.callback calls get the same, minus the `source` parameter
of server callbacks.
The callback of lib.onCache('key', ...) takes its parameter types from
cache.key. Native handle types (Vehicle, Ped, Hash, ...) resolve to
integer instead of whatever class a resource declared under that name.
Snippets use the event and keyword icons, preview their body without
placeholder syntax, and are listed by the new qbx/snippets request.
Mapping Vehicle, Ped, Hash and the other handle types to integer fixed the clash with classes of the same name in ox_lib and qbx_core, but it also turned every native signature into `vehicle: integer`. A handle is now its own type: it prints under its name, has no members and never looks a class up. `require 'glm'` returns the built-in library instead of a module of the resource, which is how ox_lib obtains it.
The shared release workflow now builds release notes from the commits since the previous tag, so the hand-kept file is redundant.
Requests flush dirty documents before handling, then workspace publication flushed the same documents again. Remove each document from the dirty set immediately after its index update.
A dirty document triggered diagnostics for every open document. Publish changed documents and open documents in their affected resources, where shared diagnostics context can change.
Keep the dirty-document indexing optimization while retaining diagnostics publication for every open document. Cross-file diagnostics can depend on documents outside the changed resource.
Request-time indexing must not consume dirty document state before idle diagnostics publication. Keep dirty markers until publish_dirty completes so diagnostics are sent after requests.
- Requests flushed the dirty set without draining it, so every request in a burst and the idle publish reindexed the same documents again. - flush_index now drains the set and marks diagnostics as pending; publish_dirty reads that flag instead of the set. - Replace the test that passed without the fix with one that fails on both the old flush and a drain that drops publication.
…hanges qbx-lint can take its settings from a LuaLS or EmmyLua config when there is no qbxlint.toml, so watch those files as well and reload the config when they change, the same way qbxlint.toml is handled. Formatting used an empty config root to tell that no qbxlint.toml was found and the editor's indentation should apply. A config read from .luarc.json has a root, which would have switched formatting to qbx-lint's defaults, so check format_configured instead.
Loop variables, indexed fields and generic calls now get the types their tables and annotations describe instead of `unknown`. - pairs/ipairs/next: keep literal types for inline tables, read the array part of top-level local tables, and handle tuples, class fields, unions and `for k, v in next, t`. ipairs yields only the array part. - Indexing: a key typed as string literals looks up each named field, and `list[i]` works on top-level local arrays. Table constructors keep their array part and every `[key]` next to named fields. - Generics: record `@generic` names on function types and bind them from `table<K, V>`, `V[]` and `T?` parameters and callback returns. Callback parameters use the bound types, and unbound generics are `unknown` rather than their names. - Hover: string literal unions and aliases no longer list the string library, aliases of non-table types show their definition, and a top-level local array shows as `string[]`.
- Index the array part and `[key]` entries of every indexed table,
so `Config.Items = { 'a', 'b' }` loops and indexes as `string[]`.
- Keep `@overload` signatures on function types. A call uses the
declared signature unless its argument count or value kinds rule
it out, then the first overload that fits, for both the result
and callback parameter types.
- Index each part of a union: `(string[]|integer[])[1]` is
`string|integer`.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Changes
Shared analysis changes currently require coordinating two repositories and matching release tags. Import
qbx-lua-lsintocrates/qbx_lua_lsand make it a member of the existing Cargo workspace, so one PR and one CI run can change and test the linter and server together.The full-history subtree import preserves all 47 linter commits and 56 server commits from the current main branches, including their original hashes and authors. The imported server's
src/,tests/anddocs/trees match the original repository exactly. Integration changes share workspace metadata/dependencies and one lockfile, remove duplicate repository configuration, update developer documentation/scripts, and package both binaries under their existing archive names.Release builds remain separate so server-only documentation stays out of the CLI. The server keeps panic unwinding for LSP request recovery; the CLI retains abort-on-panic through the
lint-releaseprofile. The existing root GitHub Action remains available.Merge this PR using Create a merge commit. Do not squash or rebase it: that would discard the imported commit graph from main.
docs/repository-migration.mddocuments namespacing the five historical server tags underlua-ls/, publishing the first shared release, updating the editor, and archiving the original server repository after cutover. No existing tags or releases are changed by this PR.Companion editor migration: Qbox-project/qbx-editor#3. Merge that after this PR and the first shared release.
Checks
cargo fmt --all --check,cargo clippy --workspace --all-targets --locked -- -D warnings, andcargo test --workspace --lockedpassed on Windows.1.0.4.lua-ls/; their publication is a documented cutover step.Linux/macOS builds remain covered by the existing release matrix; no release was published during validation.