Conversation
…cle events On desktop the TypeScript language server (vtsls) always lints JS, yet JSHint still also linted plain-JS projects (it only deferred to ESLint), so the Problems panel showed duplicate diagnostics. JSHint now defers to the language server the same way it defers to ESLint: it runs only when it is the sole JS diagnostics source, when a .jshintrc opts it in, or as a fallback when no server is running. ESLint and the language server keep coexisting (rules vs. compiler), like VS Code. Browser is unchanged - no server there, so JSHint stays the JS linter. - LSPClient: add isLintingProviderActive(languageId); make the module an EventDispatcher exposing EVENT_LANGUAGE_SERVER_STARTED / _STOPPED for extensions. A new _announceServerStarted() fires STARTED and re-runs inspection on every path that brings a server up (initial start, restart, crash auto-restart) - so linters that defer re-evaluate even on a clean file, whose empty publishDiagnostics wouldn't otherwise trigger a re-run. - JSHint: resolve a desktop-only LSPClient handle and defer in canInspect, deriving the language id from LanguageManager. - Tests: new "defers JSHint to the language server in a plain JS project" spec; update the two ESLint-failure-fallback specs to expect the LSP (not JSHint) to cover the file on desktop.
…t switch The server was spawned eagerly on app boot and repointed on every project switch, regardless of language - so a Python-only project still ran vtsls and re-indexed it on switch. Mirror VS Code's onLanguage model instead: start the server only when a served-language (JS/TS/JSX/TSX) file is the active editor, and repoint (workspace/didChangeWorkspaceFolders) only when a served file is active right after a project switch - never on ordinary file switches. Once started the server stays alive idle (no proactive shutdown). - main.js: _ensureServerForActiveEditor() driven by activeEditorChange + an initial evaluation; a pendingRepoint flag (set on EVENT_PROJECT_OPEN) gates the repoint so file switches don't touch the workspace-folder/restart machinery. Report a start failure via window.logger.reportError, deduped (start is retried lazily). Drop the eager appReady start and the now-meaningless readiness flag. - LSPClient.changeWorkspaceRoot: check same-root first so a redundant call is a no-op and never restarts a server that lacks live workspace-folder support. - tests: the lazy "never started" state isn't observable in the reused integration window (keep-alive, no stop path), so don't assert it; drop the readiness-flag wait (window load already guarantees the extension's appReady ran).
…e clipped detail The highlighted auto-import row rendered token.detail inline - a long "Add import from <module> …" string that clipped to a useless "Add import from "fs" names…", while non-highlighted rows showed the short module. Skip the inline signature for auto-imports (their detail is that import line; the doc popup still shows it in full) and keep the short source-module tag visible on the highlighted row. In-scope items are unchanged - they still show their type signature inline.
…ctable Restyle the LSP documentation popup and the parameter-hint popup so all three code-hint surfaces (completion list, doc popup, parameter hints) share one visual identity: same menu background, border radius and shadow, in both light and dark themes. Redesign the fenced code blocks inside the doc popup as elevated panels and add a per-block copy button (with copied feedback). Make the doc popup text selectable: add user-select and an I-beam cursor, and stop the popup's own mousedown/click from bubbling to Bootstrap's outside-click handler (which was tearing the popup down before a drag-select could start). Native selection is preserved because the handler does not preventDefault.
Replace the separate-coloured signature/code panel with a faint wash derived from the popup surface (low-opacity black/white), a hairline border and soft corners. Distinct enough to register as a code region, quiet enough not to look like a pasted-in card, and consistent across light and dark themes.
…tive The legacy Tern engine and vtsls both ran for JS files on desktop: the priority system meant the LSP's hints always won, but Tern still spun up its worker and indexed the whole project in parallel - pure waste. Gate it: JavaScriptCodeHints now skips creating a Tern session (so ScopeManager never indexes) whenever the language server serves the file's language, mirroring JSHint's lazy desktop-only LSPClient handle so the browser build is untouched. The server starts lazily and can come up after Tern already indexed the first file, so we also reset Tern on EVENT_LANGUAGE_SERVER_STARTED and let it resume on _STOPPED.
Previously every keystroke (debounced) shipped the entire file to the language server, ignoring the server's advertised incremental capability - costly on large files under sustained typing (vtsls re-reads the whole buffer each time). Now DocumentSync reads the server's textDocumentSync kind and, when it is Incremental, accumulates the CodeMirror change records during the debounce window and sends them as ordered LSP range edits; it falls back to full text when the server wants full sync, when a change record can't be mapped, or on a refresh-from-disk. notifyDidChange takes the contentChanges array so the caller decides the shape. Adds two integration tests that drive many real edits (sequential inserts, mid-document replacement, deletion, and a same-line multi-cursor batch) and use the server's own diagnostics as the sync oracle.
A feature-request flush() can race the document-change listener: it ships a full update that already includes a keystroke which is also still queued in pendingChanges, so the debounced incremental send replays that edit and the server applies it twice - leaving a phantom stray token (e.g. a "}" reported as "Declaration or statement expected") that no restart cleared. Fix: before trusting the accumulated incremental edits, replay them on the last-sent text and require they reproduce the current document exactly; otherwise send a full resync. This makes divergence impossible regardless of flush/keystroke ordering. The decision and replay are factored into pure helpers (_contentChangesFor / _applyIncremental) and covered by a new unit:DocumentSync suite (14 specs), including the double-apply case.
|
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.



On desktop the TypeScript language server (vtsls) always lints JS, yet JSHint still also linted plain-JS projects (it only deferred to ESLint), so the Problems panel showed duplicate diagnostics. JSHint now defers to the language server the same way it defers to ESLint: it runs only when it is the sole JS diagnostics source, when a .jshintrc opts it in, or as a fallback when no server is running. ESLint and the language server keep coexisting (rules vs. compiler), like VS Code. Browser is unchanged - no server there, so JSHint stays the JS linter.