* fix(notebook): send the notebook path to the UI with forward slashes
On Windows a notebook's snapshot and output events carried its canonical
path as `to_string_lossy()` (`C:\a\b.ipynb`), and the UI uses that path as
the notebook tab's identity, while the project tree and editor name the same
file `C:/a/b.ipynb`. NotebookSnapshot.path and NotebookOutputEvent.path are
now IpcPath, like the other path fields on the IPC boundary (#1456 did the
same for Spring route sources and Add to .gitignore).
* chore: regenerate bindings for the notebook IpcPath fields
---------
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
Linked Gradle builds are saved with forward slashes, so on Windows the launcher of a
build outside the project came out as `C:/…/external\gradlew.bat`. load_build now
rebuilds the build folder from its components, giving the launcher and module folders
native separators; the saved identity is unchanged.
* perf(vcs): filter the Git log with git log instead of a background search index
The log built a persistent inverted index of every commit's message, authors and
changed paths in the background, with a progress bar above the commit list, and
walked trees itself to filter by path. Building it took minutes on large
repositories, and filters were slow until it finished.
- Text: plain text uses `git log --fixed-strings --grep` (with
`--regexp-ignore-case` unless Match Case is on); text of 4+ hex digits also
matches hash prefixes. Regex filters still match in-process.
- Paths: `git log -- :(literal)<paths>` replaces the in-process path walk and
its per-commit tree cache. It uses git's history simplification and, when the
repository has a changed-path commit-graph, its Bloom filters. Glob characters
in a path are literal.
- Authors match against the commit metadata cache.
- Removed the search tables, `index_log`, the `vcs_log_index` command and the
indexing progress bar. The commit metadata cache stays.
* docs(contributing): ask for screenshots only when a change alters what users see
Removing a feature together with its UI, copy-only and non-visual changes now
describe what was checked instead of attaching before/after screenshots.
* fix(vcs): match case-insensitive non-ASCII Git log text in process
git folds case only for ASCII under the C locale it runs with, so a
case-insensitive filter like "ärger" missed "Ärger". Such text is now
matched against commit messages directly. Path and text selection also
ignore log.showSignature and log.follow from the user's config.
* fix(plugins): hand plugins paths in one form on Windows
Plugins got the project root, editor path, provider documents, code action edits, vcs-status roots and find-files results as D:\… while event paths from the UI use /, so Checkstyle could not find the project of a saved file. The host now converts every path it hands to plugins with ipc_path::to_ipc.
* fix(checkstyle): match native Windows report paths
* test(plugins): use workbench IPC paths in host fixtures
Updating a Tomcat deployment took web resources only from src/main/webapp, so JSPs under WebContent (maven-war-plugin webResources) never reached it. It now reads warSourceDirectory and webResources from the pom, or webAppDirName / webAppDirectory from the Gradle build.
The JetBrains importer skipped SpringBootApplicationConfigurationType and Application as unsupported types. Both now map to the spring-boot / application forms' command line with their module, working directory and environment; options without a field are listed as left out.
Two opens of one window could each find no current project and build a full project (index, language servers, watchers); the second replaced the first without closing it, leaving two jdtls on one workspace. open_project and open_light now hold a per-window lock from the check to the insert.
The main toolbar gear's Theme submenu and Settings › Appearance › Theme preview the theme under the pointer after the same delay as Quick Switch Scheme, and closing without a choice brings the selected theme back. Choosing a theme while it was previewed left the preview flag on, so the start-up theme cache kept the previous theme; `setTheme` now ends the preview.
Import Theme from JetBrains IDE… lists one row per theme plugin and installs it without switching the theme, like any theme plugin install. It reads only the newest settings folder of each product, so folders left behind by upgrades don't list their plugins again.
Co-authored-by: ldg030201 <100822592+ldg030201@users.noreply.github.com>
* perf(vfs): list directories off the main thread and reuse the repository lookup
Opening a folder on a network share (\\wsl.localhost\<distro>\...) is slow
because every listing ran on the main thread and walked up to the repository
root and ran a repository discovery again.
- fs_read_dir runs on the blocking pool.
- GitignoreStack::cached keeps the repository root and the repo-level rules
for a few seconds. An edit of .git/info/exclude is still seen at once (its
mtime and size are checked) and every .gitignore / .ignore is read fresh.
Refs #916
* feat(remote): open WSL projects through a WSL transport
A folder of a WSL distro (\\wsl.localhost\<distro>\... or \\wsl$\...) now opens
as a remote project whose openidea-server runs inside the distro, so the
terminal, SDK discovery, run, language servers and git are native Linux.
- RemoteTarget (ssh | wsl) replaces the SSH configuration id in the remote
launch, connection, session and recents; old recents are read as SSH and a
WSL target never inherits the legacy trust migration.
- remote_wsl: probe the distro, stream the server into ~/.openidea/server and
start it with `wsl.exe -d <distro> --exec <bin> --stdio`. Distro names are
validated and every command goes through --exec with positional arguments.
- wsl_distros / wsl_resolve commands; File > Open, the CLI and recents route
WSL folders to the distro and focus the window that already has them.
- Remote Development dialog: SSH/WSL choice with the detected distros; the
status bar shows `WSL: <distro>` / `SSH: <host>`.
- ide-jsonrpc: skip the NUL left at the start of a line by UTF-16 output of
wsl.exe, which made the first message of the server disappear.
Not run on Windows yet: only a stand-in for wsl.exe is tested.
Refs #925, #327, #721
* fix(remote): satisfy clippy in WSL output decoding
* style(run): format run types
* fix: regenerate bindings and drop untranslated WSL catalog entry
* test(i18n): list WSL as an untranslated product name
* fix(run): pick build wrappers and shell quoting by the execution host
A remote window runs commands on its Linux or macOS server, so a Windows
desktop no longer selects gradlew.bat, mvnw.cmd or Windows quoting for it.
* fix(welcome): open legacy WSL UNC recents and sessions through the distro
Recents and the restored session called the local openProject for a
\\wsl.localhost folder saved before WSL projects, which fails with OS
error 123. They now resolve it like the other entry points.
* fix(windows): keep WSL files out of remote project launches
path_launch tested the WSL share before is_dir, so a first-instance CLI
launch with a WSL file opened a remote project instead of LightEdit.
* fix(remote): run-command OS comes from the remote host, not an assumption
The server's OS was dropped after connect, so a restored session had none and
isWindows() assumed every remote host is Unix. Keep it on the connection and
the session, and resolve it through hostOs().
---------
Co-authored-by: NguyenBang <nguyenbang@NTBANG.local>
Co-authored-by: NguyenBang <nguyenbang@Mac.lan>
Co-authored-by: l0ng-ai <24760907+l0ng-ai@users.noreply.github.com>
A terminal that starts but never shows a prompt left nothing in the log: the
spawn was logged at debug level only. The spawn (shell, pid, size), the first
output (after how long, and whether it is ConPTY's cursor position query) and
the first input (and whether it is the cursor position report) are now logged
at info level, once per session, so a user's log tells whether the shell never
wrote, or its query was never answered.
Refs #1224
With API 1.1 the host provides ui.copy-to-clipboard, so that case only failed
on its signature. Use a name that never exists so it keeps covering a missing
function.
Linked builds are saved normalised (canonical, forward slashes), but unlinking
compared the paths it was given verbatim, so a build outside the project could
not be unlinked on Windows (C:\… vs C:/…), nor through a symlinked path. Unlink
now normalises each path the way linking saves it. The Gradle linkage tests also
create the platform's wrapper (gradlew.bat on Windows) and compare canonical
paths without the \\?\ prefix.
$/progress also covers background work such as indexing and workspace
builds, during which an empty answer is final, so treating it as loading
made "no definition" wait for servers like clangd or jdtls. Navigation and
hover now wait only while a server says it is loading (rust-analyzer's
quiescent flag); other servers answer as before.
An answer requested while loading that comes back after loading ended is
asked once more instead of returned as final.
A bottom tool window lists the connected Android devices (adb devices -l) and
streams the selected one's log (adb logcat -v threadtime, the last 200 lines first),
parsed into time, pid, level, tag and message in a virtualised list that follows the
end until scrolled up. The filter box takes Android Studio's logcat expressions
(tag:, message:, pid:, level:, -term, |, parentheses, regex) and remembers recent
ones. The new ide-android crate runs adb, which it finds through ANDROID_HOME /
ANDROID_SDK_ROOT, the usual SDK locations or PATH; the stream goes over a Channel
in batches (300 lines, or once the oldest waiting line is 60 ms old) and stops with
its request. The window is listed under the stripe's overflow until first opened.
Co-authored-by: payailk <80739895+payailk@users.noreply.github.com>
Dart projects that depend on the Flutter SDK were debugged through
`dart debug_adapter`, which cannot start a program importing dart:ui and has no
hot reload. A session now uses `flutter debug_adapter` when the program's or the
working directory's pubspec.yaml depends on the Flutter SDK, or when an attach
configuration asks for it (add-to-app: vm-service-uri and device map to the
adapter's attach arguments). Hot Reload and Hot Restart are sent over DAP and
appear in the toolbar of Dart sessions. Dart files also get a debug configuration.
Co-authored-by: payailk <80739895+payailk@users.noreply.github.com>
check_component only compared import names and the API version, so a component
built from unreleased WIT (a function added under @1.0.0) or missing the plugin
world's exports passed `openidea-plugin check` and installing, then failed when
the IDE started it. It now links the component against the host's linker and
reports the missing or mismatched function with what to do.
Closes#1468
Configurations created for a main class, and the Spring Boot applications
detected in a module, set their working directory to the module directory.
A relative path in the VM options (such as --module-path=app/server/target/dependency)
then resolved against the module and the JVM failed to start. They now leave the
working directory empty, so the process starts in the project root, which is what
an empty working directory means elsewhere. The module is still stored separately
and keeps supplying the classpath and the debugger's sources.
Fixes#1197
Plugins get three host calls in API 1.1: vcs.remotes (under vcs.read) lists the
repository's remotes, ui.copy-to-clipboard and ui.open-url act on the window that
invoked the plugin's command.
Remote URLs are returned without the user:password part they may carry, and the
two UI calls fail when there is no invoking window instead of reaching every window.
Co-authored-by: dengliu <5108773+dengliu@users.noreply.github.com>
The Profiles node listed only the POMs' profiles; it now also lists those of the user settings.xml (the configured file, else ~/.m2/settings.xml), checked by default when <activeProfiles> names them or they are activeByDefault, and deactivated with -P!id when unchecked.
Fixes#1442
Welcome › Projects can put recent projects into named groups: Move to Group (other groups, New Group…, Remove from group) on a project, Rename / New / Remove Group on a group (removing keeps its projects). Groups are listed first, fold with click, Enter or ←/→, and searching lists matches without groups. Groups live in recent-groups.json beside recent.json; grouped projects are exempt from the 30-project cap and leave their group when removed from recent projects.
Fixes#1420
Adds a search bar to query result grids (match case / words / regex, previous/next occurrence, Filter rows) and a pager for console results (first/previous/next/last, page size). Later pages re-run the read-only query with a skip, which every driver reads past without decoding, so only one page crosses IPC; Last counts rows with the statement wrapped so a trailing line comment can't swallow the closing parenthesis.
Closes#1431
Co-authored-by: kidp2h <40386174+kidp2h@users.noreply.github.com>
An interpreter that detection doesn't look for (a virtualenv in a subfolder such as backend/.venv, or one set by path) was missing from sdk_detect, so the status bar and interpreter menu showed its raw path. sdk_detect for Python now adds the project's interpreter when detection didn't find it, named by the same rules, and a project-local .venv in a subfolder is named after that folder.
Fixes#1428
Closing Settings while an ACP Registry agent was installing cancelled the install, and Install was offered again while a previous attempt could still hold the agent's folder. Installs now outlive the page as a background task of the project windows (stoppable from the status bar); the backend refuses a second install of the same agent and marks it installing in the list, which a reopened page follows until it ends.
Fixes#1430
Spring route sources came back from the host with native separators, so on Windows every source failed the prefix check against the forward-slash project root and Search Everywhere showed no endpoints. RouteSource.path is now an IpcPath and the index compares by path segment; the add-to-ignore result also returns IPC paths.
Fixes#1422
feat(maven): add POMs outside the root reactor as Maven projects
Add Maven Projects only re-linked POMs Maven had already discovered: picking a pom.xml inside the
project that the root POM doesn't list as a module (an independent build kept out of the reactor)
closed the dialog and changed nothing. Such POMs are now kept in the project's Maven settings
(linkedProjects) and loaded as independent top-level projects, after the root reactor, by the
static model, the sync, the Java language server import and the content roots; each runs its goals
in its own directory. A picked POM that the root reactor lists stays its module. The dialog takes
several POMs at once, and unlinking a linked project drops the link instead of hiding it.
Right after a project opens, rust-analyzer answers navigation with nothing
until it has read the project, misses macro-generated items until build
scripts and proc macros are built, and withdraws answers (ContentModified)
while loading changes its data. Go to Definition reported "Cannot find
declaration" or did nothing in that window.
The client now enables rust-analyzer's experimental/serverStatus and tracks
whether a server is still loading (its quiescent flag, else any $/progress
task). Definition, declaration, type definition, implementation and hover
retry an empty or withdrawn answer each time a loading phase ends, for up to
30 s; background work such as cargo check does not trigger the wait. The
server shows as busy while it loads.
Opening a folder of independent Gradle builds selected only the first build. Link Gradle Projects… (pick a build's settings or build file) and Unlink on a build's root let an ordinary project window manage several independent builds without changing their scripts. The build model holds a list of Gradle builds; each keeps its own wrapper, working directory, environment, task routing and sync cache, keyed by the owning build directory. The links persist in the project's Gradle settings (linkedProjects); unlinking leaves files and saved run configurations alone. Existing includeBuild support is unchanged, and an explicitly linked build takes precedence over a composite that also includes it. Workspace windows keep Link/Unlink disabled.
Co-authored-by: gudcks0305 <84506708+gudcks0305@users.noreply.github.com>
fix(vfs): report files deleted on macOS again
Since the watcher queues raw notify events (#1412), deleting a file on macOS was never reported, so
its symbols stayed in the index and the tree kept it (the project smoke tests failed for every
language). FSEvents delivers a deleted file's coalesced history flags as create, remove, then
modify events. Create + remove merged into a transient path, the following modify turned it back
into a creation, and a creation of a path that no longer exists is dropped. A modify no longer
revives a transient path; only a create does, and the disk decides as before.
* fix(tools): find Python on Windows without python3.exe
Installing debugpy on Windows failed with "cannot run python3.exe … (os error 3)": the tool
manager looked for `python3` first, and on Windows that only finds the App Execution Alias in
WindowsApps, which can't start without the Store's Python. Windows installs `python.exe` and the
`py` launcher instead. On Windows the interpreter is now looked up as `python`, `py`, then
`python3`, and a WindowsApps alias only counts when it runs. The debugpy adapter's default
interpreter is `python` on Windows too. macOS and Linux keep `python3` first.
* fix(tools): keep searching past broken Python aliases
Window destruction and the close_project command detach the project at once and let its language servers, kernels and debug sessions shut down in the background; opening a project waits for pending shutdowns and exit waits for them with a bound.
Closes#1414
On a fresh install, Settings › Plugins › Available showed no marketplace plugins until the user refreshed by hand: opening the page asked for the listing without a refresh, which only returned the cached index, and a first run has none. The listing now reads the index when none has been read yet; later opens keep using the index already read, and an explicit refresh reads it again.
Tool downloads from GitHub releases called api.github.com anonymously unless GITHUB_TOKEN or GH_TOKEN was set, so they hit the 60-requests-an-hour limit and failed with 403. When neither variable is set, the request now uses the active github.com account from `gh auth token` (the same login the GitHub features use), asked per request with a 5 s, cancellable lookup. The token goes to curl over stdin (`--header @-`), only for https://api.github.com, with `-q` so a user curlrc can't log or forward it, HTTPS-only redirects, and redacted from error messages. Without gh or a login, downloads stay anonymous.
Co-authored-by: qjlqyf <109515705+qjlqyf@users.noreply.github.com>
SSH passwords and key passphrases, git HTTPS credentials, the HTTP proxy
password and data source passwords were kept in plaintext JSON files in
the app data directory. They now live in the OS credential store via
keyring 4 (macOS Keychain, Windows Credential Manager, Secret Service on
Linux); each file keeps only an index of keys under a per-directory id.
Files from older versions are moved key by key on first use, with a
.migrating sidecar so a failed or interrupted move retries without
duplicating credentials. Without a credential store (headless Linux)
the old file is still read but nothing new is written to disk; the
secret lasts for the session. New data sources no longer save their
password or SSH tunnel secret unless asked.
Also keeps the index path in SecretStore for global data sources and
runs their test against the in-memory store.
Fixes#740 (credentials part)
Co-authored-by: LittleGuava <52166187+LittleGuava@users.noreply.github.com>
Data sources can be made global (Global option in their properties): stored in data-sources.toml of the app data directory, listed in every project, with their saved passwords under an app-wide key that moves along when the scope changes. Fixes#1252
package_hash fed each package-relative path to the digest with
to_string_lossy, so a walked path hashed as `web\index.html` on Windows
and `web/index.html` elsewhere. The same package had two digests: a
market index built on Linux failed verification on Windows, and a
package signed on one OS did not verify on another.
Join path components with `/` before hashing. Digests on macOS and
Linux are unchanged byte for byte; installed plugins keep their recorded
.package-hash, and a recomputed digest is accepted as a silent update by
the grant ledger, so existing Windows installs are not re-prompted.
Closes#1258
Document::diff only trimmed the common prefix and suffix, so two distant
edits on disk became one change spanning everything between them. The
caret and scroll position inside that span were mapped to its start,
which made the editor jump to the first edit after an agent, formatter
or git operation rewrote the file.
Diff the changed middle line by line (Myers via similar, 50 ms deadline
with a coarser fallback) and emit one change per edited region, trimmed
to its differing characters. The frontend DocSync path produces the same
per-region changes, so external reloads, local history restores and
formatting keep the caret and view in place.
Closes#1326
Co-authored-by: ntbang0901 <121003585+ntbang0901@users.noreply.github.com>
Settings › Editor › Inspections › Java gets the inspection, off by default. When on, jdtls's compiler reports the missing field and offers the add default/generated ID quick fixes. Built-in inspections can now be off by default, the backend resolves the profile in effect, the compiler-defaults file is named after the variant so jdtls restarts with it, and saving inspection settings reconfigures language servers. Fixes#1199
Opens each fixtures/ project through the ops the app's commands call and checks the source and test roots from its build file, the index, Search Everywhere / Go to Class / Go to Symbol answered from it and kept current as files come and go, and the Maven / Gradle model. Ignored tests run a Maven and a Gradle sync and check virtualenv and JDK detection; the Language smoke java, kotlin and python jobs run them.
debugpy ran the project manager (`uv`, `poetry`, …) as a module. Configurations run through uv, poetry, pdm, pipenv, hatch or rye now pass the manager as the debuggee's interpreter, keep the script / -m module / tool as the target, and run the adapter and launcher on a plain interpreter (debugLauncherPython, now preferred by the backend for the adapter command).
Plugin tool windows that list code locations (routes, failed tests,
queries) had no way to take the user to file:line. A host import
`views.open-location(path, line, column)` opens a file inside the project
in an editor of the window the call came from, caret at the given line and
column (0-based, UTF-16). It needs `project.read` and refuses paths outside
the project; the event goes only to the calling window, as `open-terminal`
does. The Rust SDK exposes it as `host::open_location` (with the mock), the
API table lists it, and the shipped components are rebuilt for the new WIT.
Closes#1334
Co-authored-by: yzPeedro <54516747+yzPeedro@users.noreply.github.com>
A view's `icon` could only be a built-in icon name, so a plugin's tool
window button couldn't show the plugin's own mark. Like `fileIcons`, an
`icon` ending in `.svg` is now a path in the package: the host reads and
checks it at install time (a missing file or an SVG with `<script>` refuses
the install), serves it as the `viewIcon/<id>` asset, and the tool window
registers it as an external icon, falling back to the plugin icon if it
can't be loaded. Icon names work as before.
Closes#1335
Co-authored-by: yzPeedro <54516747+yzPeedro@users.noreply.github.com>
With a PHP file focused, the status bar shows the PHP level Intelephense
checks against (`PHP 7.4`); the tooltip says where it comes from (the
settings, config.platform.php or require.php). Clicking it opens Auto (with
the composer.json version) and 5.6 to 8.5; picking one writes the same
project setting as Settings › Languages & Frameworks › PHP, so diagnostics
follow without reopening the project. The widget is hidden for other files.
For a file of a linked workspace project, the level comes from that
project's settings and the choices are disabled. The menu is also the
action "PHP Language Level".
Closes#1091
Co-authored-by: DanielADK <18214958+DanielADK@users.noreply.github.com>
The test-events and delegated-run init scripts were written to a path built from the desktop's temporary directory, which doesn't exist on a remote host. A new `run_gradle_init_script` command writes a script under the host's own temporary directory, named by its content, and returns the path Gradle reads it from.
CodeLLDB runs debug-console input as LLDB commands unless its console mode says otherwise, so Evaluate Expression, the Debug Console and breakpoint log messages failed with "'x' is not a valid command". Launch and attach requests now set `_adapterSettings.consoleMode` to `evaluate` unless the configuration picks a mode; LLDB commands still run with a leading backtick.
crates/ide-host/tests/vcs_flow.rs takes rust-app through a day with Git
via the ops the app's commands call: an unsaved edit marked in the
gutter against HEAD, Local Changes and the file's diff once saved, a
commit at the head of the log, a branch with its own change, checkout
back with the open file following, a stash pushed and popped, and a
merge that conflicts. Then the open file shows the conflict, the three
versions are offered, and Accept Theirs is committed as a merge.
Intelephense loads only its 68 default stub sets, so code using redis,
imagick, memcached, wordpress and the like showed "Undefined type", and
there was no way to point it at a platform's classes outside the project.
- Each ext-* in require or require-dev of the root composer.json adds its
stub set, and Settings › PHP › Additional stubs adds others (wordpress).
`stubs` replaces Intelephense's defaults, so the defaults are sent with
the additions; nothing is sent when nothing is added.
- Settings › PHP › Include paths: folders (absolute, ~/ or relative to the
project) sent as environment.includePaths.
Both apply on composer.json and settings changes without reopening the
project; Settings › Language Servers options still win.
Fixes#1232Fixes#1233