Find in Files skipped dotfiles (.eslintrc, .github/workflows/*.yml) and git-ignored files (.env, *.log) because the ide-search walkers dropped every hidden or ignored entry, files as well as folders. A shared walker now lets the ignore rules pick only the folders to enter and lists each walked folder for its files, so ignored folders (target/, logs/) are still skipped while ignored files elsewhere and hidden files are searched, as Go to File does since #1313. Find in Files, Inspect Code / Locate Duplicates (scope_files) and LSP reference candidates (files_with_word) all use it; .git, symlinks, archives, files.exclude and excluded roots still apply.
Fixes#1317
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
Menu rows now follow the pointer without taking focus: focusing the row on every pointer enter dropped the hover paint in the Windows webview, so menus looked frozen. Keyboard navigation continues from the hovered row, and an item's onActive fires once per enter. Focus no longer scrolls the page when a menu row takes it.
On Solarized Dark the selection and hover colours were the popup and panel colour, so menu, tree, list and tab selection was invisible there; on Solarized Light selection matched the panels. Both themes get distinct selection and hover colours, and the editor keeps Solarized's own selection colour.
Co-authored-by: tomgor <12905387+tomgor@users.noreply.github.com>
Git › Show History for Selection, as in IDEA: from Git › Current File and the editor's Git menu it opens a tab with only the commits that changed the selected lines (or the caret line), newest first, and the block before and after each commit in the diff viewer. Only Show History for the whole file existed before. git log -L tracks the lines across renames; the selection is first mapped through unsaved and uncommitted edits to HEAD's lines, and those edits come first as Local Changes. The query is its own ide-vcs module and cancellable command (vcs_block_history), read-only and allowed in Restricted Mode (--no-ext-diff --no-textconv).
Co-authored-by: ldg030201 <100822592+ldg030201@users.noreply.github.com>
Intelephense checked PHP code against its default 8.5, whatever version the project targets. Settings › Languages & Frameworks › PHP gets a PHP language level, Auto (default: composer.json config.platform.php, else the lowest version require.php allows) or 5.6–8.5, sent as environment.phpVersion; nothing is sent without a requirement. Intelephense applies the version only to documents it parses after reading its configuration, so servers that opt in (resync-on-configuration, Intelephense only) get their open documents again right after workspace/configuration is answered (new jsonrpc Handler::after_response), and Intelephense keeps one index per level because it fixes the built-in functions when it indexes. A change to a root or workspace member composer.json reconfigures the servers.
Co-authored-by: DanielADK <18214958+DanielADK@users.noreply.github.com>
The index walker used the ignore crate, which drops ignored files before we see them, and the watcher dropped their events too, so git-ignored files such as .env were missing from the index and Go to File, the Files tab and @ mentions could not reach them in any scope. As in IDEA, ignored folders stay out of the project but ignored files stay in it: each walked folder is also listed and the files the walker skipped are indexed by name only (no read, hash or symbols), the ignored flag is stored (index schema 3) so a file whose rules flip is re-parsed or dropped on the next scan, and the watcher reports ignored files in a separate list that only the index and open editors use (Local History, deployment, LSP and fsChanged see the same events as before). Watcher updates classify files by listing their folder with the scan's walker, so nested, global and info/exclude rules apply the same way.
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
The rpc integration test wrote *.tmp fixtures; a machine whose global excludes file lists *.tmp already ignores them, so the backend never writes the .gitignore / info/exclude entry and the test failed reading it. The fixtures now use a suffix no excludes file lists.
Co-authored-by: qtvbwfn <5848026+qtvbwfn@users.noreply.github.com>
For a folder that isn't a repository, the current-branch query answers with a repository found below it, so the New Agent Task page read "<folder> on <branch>" although the agent runs in the folder itself and the branch couldn't be changed. The branch is now shown only when the project is a repository.
* test(lsp): smoke-test everyday code intelligence per language with real servers
A new ide-host integration test drives completion, go to definition, Find
Usages, hover, diagnostics with a quick fix, an intention, formatting and
rename on each language's fixtures/ project, through the ops the app's
commands call and the language server the app starts by default:
TypeScript (vtsls), Python (basedpyright + Ruff), Rust (rust-analyzer),
Go (gopls), Java (jdtls) and Kotlin (kotlin-lsp). A failure names the
language and the operation.
The tests are ignored by default; a Language smoke workflow installs pinned
server versions and runs one language per job on changes to crates/,
languages/ and fixtures/. Adds fixtures/java-app (Maven, JDK 21) for Java.
* test(lsp): rename TypeScript from a usage and check Rust errors while typing
Covers the fixes the smoke test turned up: a TypeScript rename started at a
call site in another file renames the declaration (#1301), and rust-analyzer's
own diagnostics and fixes arrive without saving (#1306).
Current Kotlin LSP releases launch with bin/intellij-server; the
kotlin-lsp.sh / kotlin-lsp.cmd wrappers the installer picked now print a
deprecation warning and are announced to go away, which would leave a
fresh install without a server. The installer prefers the launcher and
still finds the wrappers in older releases.
rust-analyzer reports its own analysis (a missing field, a wrong type) only
to clients that pull diagnostics; it pushes just `cargo check`'s, so in the
editor a Rust type error showed up only after saving. The client now
advertises `textDocument/diagnostic` and pulls an open file's diagnostics
from servers with a `diagnosticProvider`: when it opens or its server
starts, after edits (once typing pauses), on save (and other open files
for servers with inter-file dependencies) and on
`workspace/diagnostic/refresh`. Pulled and pushed diagnostics are kept
apart and shown, and given to code actions, together; a newer pull
supersedes an older reply, a server-cancelled pull is retried, and closing
a file drops what was pulled.
Renaming an imported function at a call site renamed only the local binding,
leaving `import { formatMoney as formatPrice }` and the declaration as it
was: both TypeScript servers default to aliases on rename. vtsls gets
`typescript.preferences.useAliasesForRenames = false` (and the JavaScript
one), typescript-language-server `providePrefixAndSuffixTextForRename = false`,
in every language that starts them.
Unversioned files in the commit view could be added or ignored but not deleted. Their context menu now offers Delete…, as IDEA's Changes view does: it asks first and moves the files to the Trash, only when every selected file is unversioned.
gopls sends a document version for every file of a rename, including files
the editor never opened. Applying a workspace edit rejected any versioned
file without an open document as changed, so a Go rename touching a closed
file always failed with "changed; request the refactoring again". For a file
that isn't open, the preconditions captured with the edit now decide; an
edit without them is still rejected.
Show History picked its repository with repoOf, which routes a nested repository's own root to the enclosing repository (right for the commit view's submodule pointer), so a submodule folder listed its gitlink history in the parent repository. A repository's own root now opens that repository's history, as in IDEA; other paths still use the innermost repository.
The inline cell editor is a single-line input that drops a value's line breaks on the first change, and it committed on every Enter; the Record view's fields had the same problem. Multi-line values now open in the multi-line editor, Shift+Enter opens it for any cell (from the grid or the inline editor) and Cmd/Ctrl+Enter applies it; CRLF values keep CRLF; the grid marks line breaks with a muted ↵; the Record view uses a text area for multi-line values.
Merged project windows are separate native windows that take turns being visible. Hidden members kept their own earlier frame and monitor, so the first switch after merging, and any switch after moving or resizing the window, moved or resized the window on screen; a maximized member could appear on another display. The group now copies the selected window's frame and display to the hidden members after a selection and after the visible window is moved or resized (debounced), skips copies when the frame already matches, and leaves macOS simple fullscreen to its own path, so switching projects only changes which window is visible.
Co-authored-by: xtr-hub <242808782+xtr-hub@users.noreply.github.com>
#1309 made the Find in Files, file scope, index and walk_files walkers require git inside a repository, so an outer repository's .gitignore stops at a nested repository. External TypeScript project discovery (ide-lsp) and Lombok detection (ide-sdk) still walked with require_git(false) and could miss a nested repository's sources the same way; they now use the same check. Adds tests for walk_files (nested repository with its own .gitignore and info/exclude, a plain folder inside the outer repository, the outer repository, a folder outside any repository) and for scope_files.
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
The walkers used require_git(false), and with it the ignore crate never treats a .git directory as a boundary, so an outer repository's .gitignore hid a project that is its own repository inside an ignored folder (Find in Files found nothing). Walkers now require git when the walked folder is inside a repository, so rules stop at a nested repository's root as in git; folders outside any repository still honour their .gitignore. Covers the Find in Files engine, the file scope, the index walk and ide-vfs walk_files.
New Branch dropped its suggestion when validateBranchName rejected it, and the current branch always exists, so a plain New Branch from HEAD always opened empty; the test never seeded the local branches. The suggestion is kept, the dialog shows that the branch exists from the start and Create stays disabled until the name changes; other prefilled prompts (Rename Branch) keep showing errors only after editing.
The find bar belonged to the pane and every bar shared one query, and its effect re-ran the search and moved the caret whenever the active tab changed, so switching files dragged the previous file's search into the next one and lost its caret. Each tab now has its own find bar with its own query and options, as with IDEA's per-editor search session. The last search only pre-fills a newly opened bar (or the selection does) and drives Find Next without a bar; showing a bar again only highlights, and the caret moves only when the query or an option changes in that bar. Bars of closed tabs are dropped.
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
The JVM run-target scanner only reads the file's own text, so a class like `class App extends AtomStarter {}`, whose superclass (in the project or a library JAR) declares `static main`, got no gutter Run, no Ctrl+Shift+R and no file-level Run, although the JVM launches it. Classes with an `extends` clause and no main of their own are now candidates: the superclass chain is walked through the language server's type hierarchy, each class supertype's source (file, decompiled or source-jar document) is checked for a static main, and the answer is cached per class and `extends` clause, so the gutter, Run from context, launch and debug agree. Interfaces are skipped (a static interface main is not inherited); negative answers are asked again when the server settles. `main(java.lang.String[] a)` is accepted as well.
Co-authored-by: ntbang0901 <121003585+ntbang0901@users.noreply.github.com>
On WebKit, CodeMirror positions tooltips absolutely inside the editor, but the tooltip space still reported the whole window as the right bound. CodeMirror never shifted a tooltip near the editor's right edge to the left, the box was squeezed into the space left of that edge, and the next measurement read the squeezed width, so it could end as a one-character column. The tooltip space is now the editor's own horizontal extent (clamped to the window) and tooltips size to their content, which fixes hover, inline blame, debugger values, signature help and hints together.
Co-authored-by: ntbang0901 <121003585+ntbang0901@users.noreply.github.com>
"Show pinned tabs in a separate row" was ignored while "Multiple rows" was on, because the pinned row explicitly excluded horizontal layouts with multiple rows. The two options are independent, so the pinned row now shows whenever some but not all tabs are pinned, and each row wraps on its own. With the rows split, dropping a tab on the pinned row pins it and keeps it in the pinned group, and dropping it on the other row unpins it.
Co-authored-by: ntbang0901 <121003585+ntbang0901@users.noreply.github.com>
Scroll containers set cursor: text, and the webview applies an element's cursor to its scrollbar, so scrollbars showed the I-beam. The containers now keep the arrow and the text inside them gets the I-beam: the editor (.cm-content instead of .cm-scroller, which also covers the diff and merge editors), the source preview, the Run, Build and Debugger consoles, the Git console, the Database output and the Services log.
Co-authored-by: ppxb <17081240+ppxb@users.noreply.github.com>
The workbench sets user-select: none on body and nothing restored it for editable elements, so a contenteditable such as CodeMirror's .cm-content inherited it. In WebKit a contenteditable with user-select: none cannot hold a selection, so typing, paste and drag-and-drop into the editor could be dropped. input, textarea and [contenteditable="true"] now get user-select: text next to the cursor: text rule they share; the selection lock still overrides it.
Co-authored-by: nguyenmuoi157 <33494100+nguyenmuoi157@users.noreply.github.com>
Activating a tool window focuses its `[data-autofocus]` element or first
content field one frame later, else its body. A lazily loaded view such as
the Terminal renders its field after that, so the first ⌥F12 left focus on
the body. When no target exists yet, the tool window now watches its body
and focuses the target when it appears, unless focus has moved on.
Adds a `stubDesktop` fixture that switches the browser-mode workbench to
desktop mode over a stubbed IPC layer: tests answer the commands they need,
push Channel messages and IdeEvents, and assert on the commands invoked.
Unstubbed commands fail as unavailable; documents keep the in-memory backend.
New flows covered:
- editing: modified marker and ⌘S save, ⌘R Replace All with one undo step
- code intelligence: completion, ⌘B to another file, Find Usages, in-place
rename, diagnostics with an ⌥⏎ quick fix
- VCS: ⌘K commit with message validation and default inclusion
- run: ⌃R output streaming and exit, ⌘F2 stop
- debug: breakpoint, stop with frames and variables, step over, resume
- search: Find in Files results opening at the match line; the Search
Everywhere file case no longer needs fixme
- terminal: typed command reaches the shell and its output renders
- project: Close Project to Welcome, trust prompt, open a recent project
java-usages, kotlin-bridge and the patched Lombok agent are JDT LS bundles and a Java agent embedded into the app, not OpenIDEA plugins. Move them to java/ so plugins/ holds only plugins, and update the paths that embed or mention them.
Also fix the stale build path in the hello fixture and the contributor guide's layout (there is no templates/ directory; starter templates live in the openidea-plugin CLI).
Opening a popup (intentions, completion) moved focus out of the editor and
autosaved it. The save cleanup could change the text, such as trailing
spaces on another line, so the quick fix the popup listed no longer matched
and the first attempt to apply it failed.
While focus is in a popup the editor is not saved; it is saved when focus
moves on from the popup to anything but the editor.
An edit's preconditions hashed disk contents plus unsaved buffers. Saving a
buffer moved its text from one to the other and changed the hash, so a
quick fix, rename or refactoring listed just before a save (autosave of a
freshly typed scratch, for one) failed with "changed; request the
refactoring again", and only the next attempt worked.
Unsaved buffers now stand in for their files' bytes in the hash, so saving
doesn't change it; edits, external writes and file operations still do.
The Available tab always showed a "There is no online plugin repository"
notice under the search field when no index was set. Release builds use
the official index by default, so the notice only appeared in development
builds, where the empty URL field above it already said the same thing.
The URL field itself sat at the top of the list although most people never
change it.
- The notice is gone, and the search placeholder reads "Search plugins"
because the list holds marketplace plugins as well as local ones.
- With a repository configured, the empty details panel says "No plugin
selected" instead of claiming there is no online repository.
- The marketplace index URL is edited from the gear menu's "Plugin
Repository…" dialog; leaving it empty restores the default.
A new Java scratch was an empty file that couldn't run until a class and
main method were typed in. Languages can now define `scratch-template` in
`languages/<id>.toml`; a new scratch gets that content with the caret at
`$END$`.
- Java, Kotlin, Go, Rust, C and C++ get a runnable `main`.
- Other languages still start empty.
jdtls still completes and navigates JDK classes in a non-project file such
as a scratch; it only skips semantic checks and project classes. The banner
said navigation and completion don't work, and in a Maven or Gradle project
it offered a build reload that can't bring a file outside the project in.
- The banner now says only syntax errors are reported and only JDK classes
resolve.
- The Maven / Gradle reload is offered only for files inside the open
project (or one of its workspace projects).
`taskkill /T /F` only starts terminating the tree, and the caller then
waits for its direct child. A grandchild could still be exiting, with its
files open, when `kill_tree` returned or `Peer::exited` resolved. The
descendants are now opened before the kill and waited for (up to 5 s)
after it. A process counts as a descendant only if it started after its
parent, so a reused parent id doesn't pull in unrelated processes.
Closes#1270
A provider call that starts a plugin instance (or reads files) can run past
the edit-path soft deadline on a slow runner and returns nothing; the tests
now ask again, as the editor does. The AI completion test cancels the slow
request only once the server has it, and measures from the cancel. The
SourcePreview test waits for the effect that marks the selection scope.
Closes#1269
- `openidea-plugin new` makes a Rust plugin depend on the SDK at the tool's
release tag (git) unless the plugin is inside the source tree the tool was
built from or `--sdk` is given; the path written before only resolved on
the machine that built the tool.
- The command template compiles again: `run_command` returns
`openidea_plugin::Error`. A test now runs `cargo test` on the generated
plugin against the SDK.
- plugins/README.md: installing the tool with `cargo install --git`, the SDK
dependency, where plugins can be installed (welcome screen and trusted
projects), and where to look when a plugin misbehaves.
* fix(lsp): resolve newly installed Python packages without a restart
Packages installed into an excluded .venv (uv add, uv pip install) never
reached the Python language servers: the watcher reports changes in excluded
folders only as excluded_dirs, and didChangeWatchedFiles forwarded nothing but
the server's own source files. basedpyright kept its failed import resolution
until restarted.
Language servers get a watched-files list of globs. Files matching it, and
excluded folders matching it, are forwarded too; the Python servers watch
their configuration and site-packages.
* fix(lsp): let servers register the files they watch
Clients now support dynamic registration of workspace/didChangeWatchedFiles,
with relative patterns. Changes on disk go to each server as its registered
watchers match them, including folders in excluded trees (a package installed
into .venv, go.mod rewritten by go get). Folders outside the project that
relative patterns name (a virtualenv elsewhere, a path dependency) get their
own watchers. Servers that register nothing keep hearing of their languages'
files.
Registrations sent right after initialized are no longer dropped while the
server is still being marked ready.
Replaces the per-server watched-files list.
The webview focuses a clicked button and the focus stays there: across
project window-tab switches, and popups hand it back to their trigger. The
next keystroke switches the engine to keyboard modality, so that button got a
focus ring (window tabs, the title-bar project switcher). A pressed control is
now marked and keeps no ring until Tab or an arrow key moves focus onto it.
Focus itself is unchanged, since actions resolve their context from it.
Closes#1211
Folders now appear in the composer's `@` completion next to files, from a new
`find_dirs` index query over the folders that hold indexed files (kept
incrementally in the index, ~0.5 ms on 100k files). Enter or a click
references the folder as `@dir/` and sends it as a resource link; Tab keeps
completing inside it.
Closes#1202