- Languages & Frameworks › Java › Language Server › JDK (languages.java.jdtlsJdk) runs jdtls on its own JDK, like IDEA's JDK for importer; the project keeps compiling and running with the Project JDK.
- Toolchain pages get the Global / This project switch (default This project); Global shows and edits the global layer.
- File › New Projects Setup › Settings for New Projects… edits only the global layer, which new projects inherit.
- Configuration errors (launch_error) show as "Not started" instead of "Crashed".
Fixes#18Fixes#19
Claude-Session: https://claude.ai/code/session_01SaPPsVPuk6ZTNsoUCNCbMv
- The IDE is a GUI-subsystem binary, so Windows allocated a fresh console
window for every console-subsystem child it started: one black window per
language server, per settings-driven restart, per debug adapter and per
toolchain probe, titled with the child's own path. Closing it killed the
child, which is how editing the language-server settings broke highlighting.
- Peer::spawn, the spawn point for every language server, wired stdio but never
passed CREATE_NO_WINDOW. The rustup-proxy probe, the DAP adapter, debugpy
probe, runInTerminal and cargo spawns, the SDK probes, the run-configuration
probes, the coverage exporter and tool diagnostics/downloads (curl, tar) had
the same gap, while git, cargo builds, gh, docker and run configurations
passed the flag inline — five copies of the magic constant, six subsystems
without it.
- Add ide_core::process::{CREATE_NO_WINDOW, hide_console_window} as the single
definition, route every spawn through it (tokio commands via as_std_mut()) and
fold the inline copies into it.
- Verified locally on Windows with a console-detached harness: a plain spawn
reports a visible console window (GetConsoleWindow + IsWindowVisible), the
patched Peer::spawn reports a console without a window. cargo check, cargo
clippy --all-targets and the affected test suites (249 tests) are green.
Co-authored-by: l0ng-ai <[email protected]>
Release builds use the GUI subsystem, so a console child spawned without
CREATE_NO_WINDOW gets its own console window. git, gh, docker, builds and
run configurations already set the flag; language servers, SDK and tool
probes, debug adapters, tool downloads, coverage export and perf did not.
Add ide_core::process::no_window and use it at every remaining spawn.
Fixes#16
- ⌘T (Ctrl+Shift+T on Windows) opens a terminal tab while the terminal
has focus; elsewhere the key keeps its IDE action.
- The tab bar's ▾ menu lists installed shells under "New Predefined
Session" (login shell, shell integration) and links to Settings.
- Settings › Tools › Terminal: pick the shell path from the installed
shells or browse for one, "Move focus to the Editor with Escape",
fallback font, column width and a link to the Terminal keymap.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
$SHELL is inherited from whatever launched the app, so starting it from a
terminal running bash opened bash even when the login shell is zsh. Read
the passwd entry first and fall back to $SHELL.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Release downloads: buf, clojure-lsp, texlab, neocmakelsp, LemMinX, Perl
Navigator, kotlin-language-server, kotlin-debug-adapter and netcoredbg;
Open VSX: bash-debug and php-debug (run through node). Two new methods:
`gem` (ruby-lsp, solargraph), installed into the tool's folder and
launched with GEM_HOME, and `dotnet tool` (csharp-ls, fsautocomplete),
launched with DOTNET_ROOT so a Homebrew / user-local .NET is found.
Tools declare the runtime they need (Java, Node.js, Perl).
Each was installed from its real source and started on macOS arm64.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Every grammar-only language now gets colours: Zig, Nix and Make from the
queries their crates ship, GraphQL and HCL (Terraform) from our own, as
those crates ship none.
Grammar queries follow two conventions, so the precedence is set per
grammar: nvim-style (the later pattern wins) or tree-sitter CLI style
(the first one wins, Nix). nvim's `#lua-match?` is evaluated; patterns
with predicates we cannot evaluate no longer match unconditionally,
which coloured every Zig identifier as a constant.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
ElixirLS ships one platform-independent zip of launcher scripts that
build the server with the project's Elixir / OTP on first start. Both
the language server and the debug adapter are installed from it, each
linked to its own launcher (language_server / debug_adapter).
Tools can now declare runtimes they need on PATH; Install stays
disabled with the reason ("Elixir is required") until they are found.
The Elixir debug adapter is renamed elixir-ls-debugger so it no longer
shares the server's tool name.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Servers and debug adapters could only be found on PATH or in the IDE's
tools folder; the only way to pick another executable (a version that
matches the project's Elixir/OTP, a local build) was an undocumented
languages/*.toml override. `tools.<command>.path` now names the
executable to launch: language servers (configure_server, restarted on
change), debug sessions and the tool list honour it, the latter
reporting a Custom status with its version or why the path is unusable.
The Language Servers page is laid out like Plugins: a compact list
grouped by availability on the left, the selected tool's command, path,
location, version, install actions and hints on the right.
A debugger named like its language server (ElixirLS's elixir-ls /
elixir-ls-debugger) was folded into the server's row and never listed;
it now gets a row of its own.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Elixir files opened as plain text: highlighting only came from
@codemirror/language-data, which has no Elixir mode. Grammars now carry
their own highlights.scm; `doc_highlights` folds its captures into a small
kind vocabulary (inner nodes and later patterns win, interpolation clears
the string colour), memoised per document version on the incremental
tree. The editor maps kinds onto Lezer tags, so colours follow the active
scheme, and requests them only when no CodeMirror mode exists.
Enabled for Elixir; other grammar-only languages need their query wired.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Review fixes for several repositories in one project:
- A path equal to a nested repository's root (a submodule's entry, an untracked
clone) belongs to the enclosing repository, in the backend and the Commit view.
It was routed to the nested repository as ".", so Rollback ran `git restore` and
`git clean` over the whole submodule and Commit staged everything in it.
- Repository-scoped commands take the repository root exactly and fail when it is
gone instead of running in an enclosing repository; path-based ones resolve the
file's repository (Project::with_repo_of).
- The rescan on a repository appearing or going watches `.git/HEAD`: the watcher
never reports a `.git` path itself, so the old check never fired.
- Status skips a repository that cannot be read; refresh falls back to the primary
repository when the selected one is gone instead of failing every time.
- Commit and Compare-with-Local diffs resolve repository-relative paths against the
selected repository's root, not the project root.
- Update Project and Fetch go on after a failing repository and report the failures
together; Update skips repositories with a detached HEAD or no upstream.
- The Push dialog leaves out a repository that cannot be read.
- Shelve and patches fail clearly for changes of a nested repository instead of
leaving them out silently (they still support the main repository only).
- Fix the repository discovery test on Windows (path separators); Chinese text for
the new strings.
Review fixes for the Project JDK / Maven settings:
- jdtls gets the user settings.xml as java.configuration.maven.userSettings, so the
editor resolves dependencies through the same mirrors and servers as sync and builds.
- The configured local repository (else <localRepository> of the chosen settings.xml)
is where the static POM model looks for parent POMs / BOMs and where the Lombok
agent is looked for.
- Maven discovery finds mvn.cmd on PATH on Windows and the homes Maven Wrapper 3.3+
downloads (dists/<name>/<hash> without a nested folder).
- A Project JDK pointing at the JDK's bin directory is accepted.
- Detected run configurations reload when language settings change, so Maven and
Gradle runs use the new JDK, Maven home and options.
- Chinese text for the new settings.
Only the repository containing the project root was known, so nested clones and
submodules (or a folder of side-by-side service repositories) showed no changes and
could not be committed or pushed. The project now has IDEA's VCS roots: the enclosing
repository plus those found below the project (scanned in the background, rescanned when
a .git appears or goes). Status covers all of them; path-based commands go to the file's
repository and repository-scoped ones take the selected repository.
The Commit view groups changes by repository and commits each one with included changes;
the branch widget names the selected repository and switches between them; Update Project
and Fetch run in every repository; Push lists every repository with outgoing commits; a
repository that stops in a merge or rebase is selected so Continue / Abort act on it.
Closes#12
The JDK was always picked automatically (JAVA_HOME, PATH, the usual install dirs, by the
module's Java version) and Maven was the project's mvnw or mvn on PATH, with no way to
override either. languages.java.jdk (Languages & Frameworks › Java › Project JDK) now sets
the default jdtls runtime, the JDK of Run/Debug and JAVA_HOME for Maven and Gradle;
languages.java.maven (Build Tools › Maven) sets the Maven home, -s and
-Dmaven.repo.local for sync, builds, tool-window goals and detected run configurations.
JDKs and Maven installations are detected for the pickers.
Closes#13
* fix(java): Run jdtls with a Lombok agent and show build errors at launch
jdtls compiles with ECJ, which only generates Lombok members when the
server JVM runs -javaagent:lombok.jar. Nothing put it there, so @Data /
@Setter classes lost their accessors and Run launched stale classes
with "Unresolved compilation problem" stubs and no explanation.
- Projects whose build files mention Lombok get the newest jar: the
IDE-managed one (new "Lombok (jdtls agent)" tool, latest release from
Maven Central), else ~/.m2 (incl. settings.xml localRepository) or the
Gradle cache. Each agent gets its own jdtls workspace so everything is
rebuilt with it.
- Settings › Languages & Frameworks › Java › JVM options
(java.jdt.ls.vmargs); a Lombok agent there wins.
- Run (and Debug, as a notification) list the first compile errors when
the build has errors, plus a hint when Lombok is missing or older than
1.18.34.
Fixes#3
* fix(java): Base the Lombok hint on the agent jdtls actually runs
A Lombok agent in Settings › Java › JVM options wins over the managed
and cached jars, but the launch hint still looked only at those: with
no cached jar it said Lombok was missing, and with an old cached one it
blamed that version although jdtls ran the user's. The hint and the
startup warning now use the user's agent (version from its file name).
a66f01e adds files.ignoredNames to exclude_globs(), so the expected
length is file_excludes() + 1, not files.exclude + 1. The test failed on
every platform since.
Name patterns the IDE treats as nonexistent (.DS_Store, __pycache__, *.pyc, VCS dirs, ...) were hard-coded in five places, and Git changes ignored none of them, so .DS_Store showed up as unversioned. files.ignoredNames (IDEA's default list) now drives the project view, navigation bar, index, watcher, Find in Files, inspections and the Git status.
* fix: Stop the status refresh loop and the double project open at startup
Every status rewrote .git/index, even with nothing to persist: gix's
`write_changes` writes an empty change set too. The watcher reports
.git/index writes as VCS changes, so each status triggered the next one,
together with an ahead/behind walk. On a repository with a long history
(freqtrade, 33k commits behind upstream) that kept a core busy for as long
as the project was open. Write back only when `has_changes()`.
A project passed on the command line was opened twice: the launch and the
"reopen last project" restore ran concurrently, and the restore checked
for an open project before the launch had finished. The second open found
the index cache locked and indexed in memory only; with a different last
project, the window ended up on whichever finished last. The restore now
waits for the startup launch.
* fix(lsp): Run jdtls on the Java version its bundles need
jdtls's launcher checks for Java 21, and so did JDTLS_MIN_JAVA, but the
Eclipse platform a release ships moves on: 1.63 bundles
org.eclipse.core.filesystem with JavaSE-25, so on a JDK 21 the server died
resolving its bundles ("jdtls is not ready (Crashed)") and the error told
users to install the 21 they already had.
Read the requirement from the installed jdtls instead: the highest osgi.ee
capability / Bundle-RequiredExecutionEnvironment among its plugins'
manifests (cached per install), never below 21. The runtime choice, the
rescan while no JDK fits and the "needs JDK N" message use it.
Fixes#4
* fix(lsp): Run jdtls on a JDK 21+ and offer Install in the server popup
jdtls refuses to start on Java < 21, and its launcher took whatever
JAVA_HOME / PATH pointed at, so it crash-looped with a Python traceback
when that was an older JDK (#1). Pick the first detected JDK 21+ and pass
it via JAVA_HOME; projects still compile against their own runtimes.
When none is found, report a clear message instead of launching, and
rescan on restart so a newly installed JDK is picked up. JDK detection
now also covers the java on PATH and Windows vendor directories.
The Language Servers status popup showed the manual install hint for
missing servers; it now has an Install button that runs tools.install,
which opens the Language Servers settings page for tools the IDE cannot
install itself.
Fixes#1
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
* fix(lsp): Address review of the jdtls runtime check
- Cache the JDK scan and rescan at most every 10s while no JDK 21+ is
found, refreshing the shared list instead of discarding it; skip
duplicate Windows Program Files roots.
- Check `launch_error` in the manager (inside the blocking launch task)
rather than in ProcessLauncher, and skip such servers in batch
inspection.
- Keep the install hint visible next to the Install button; when the tool
list failed to load, try the install so the error is reported.
- Don't let a server snapshot requested before a status event overwrite
that newer status (left jdtls showing "Starting…" while missing).
Use the Windows wrapper name for Maven, compare walked paths with `/`,
relax the own-process footprint floor, skip tests that assert Unix paths
or shells on Windows, and stop Git converting fixture line endings in CI.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
The Gradle and Maven tests expected the Unix wrapper and command names, and
the canonical-root test uses Unix absolute paths. CI now reports every
failing test instead of stopping at the first few.
Claude-Session: https://claude.ai/code/session_01B65qLEKnkeYTGdbwhLpjCu
Opening another project in the same window left the previous project's state in
module-level stores: Amend and the commit message carried over, debug sessions kept
running, and Git Log, usages, hierarchy, inspection, HTTP client, recent locations,
navigation history and notifications still showed the old project.
Reset each of them on a project root change, stop the old debug sessions, ask about
unsaved changes before leaving a project, close the settings window (it would apply
to the new project) and end the indexing task when a scan is cancelled.