дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 11:15:40 +02:00
* feat(editor): Drag tabs and files between split panes
HTML5 drag and drop never reaches the webview while native file drop is
enabled, so tab, project-file and changelist drags did nothing. They now
run on pointer events:
- Drag an editor tab onto another pane, or onto a pane's edge to split it.
- Drag files from the Project view into an editor pane (center opens them
there, an edge opens them in a new split).
- Drag files between changelists in the Commit view.
- "Drag-and-drop with Alt pressed only" applies to tabs and stripe buttons.
* fix(lsp): Deliver server settings and start servers on a supported JDK
- workspace/configuration answers a server's own section (basedpyright)
from its settings block; basedpyright runs in "standard" mode and keeps
auto search paths on, so `src/` layouts resolve from `tests/`.
- jdtls: formatting follows the editor indent, calls complete without
guessed arguments, and JDK internals stay out of completion.
- `max-java` in a language server config picks an installed JDK no newer
than that (kotlin-language-server fails on JDK 25).
- Server initialization may take up to 5 minutes (first Gradle import).
- `lsp_resend_diagnostics` re-emits stored diagnostics after a reload.
- Spelling only checks declared names (not called methods like
`substring`) and accepts plurals of known software terms.
* feat(editor): Quick fixes, completion and navigation while typing
Quick fixes
- Errors get a red quick-fix bulb; Apply Quick Fix (⌥⇧↵) fixes the most
severe problem at the caret, and the error hover offers the fix directly.
- Code generated by a code action is re-indented to the file's style.
- Python: Implement abstract methods (⌃I or the bulb) from the bases.
- Duplicate code actions are listed once.
Completion
- Overloads sharing a name, and a name importable from several modules,
are no longer merged into one entry.
- Auto-import entries show the module they import from.
- Call snippets without a stop (`new ArrayList<>()`) leave the caret inside
the parentheses with parameter info, or past them when nothing takes
arguments; parameter info also opens after server call snippets.
- The selected item is resolved ahead of acceptance, so its auto-import
is applied (rust-analyzer).
Navigation and diagnostics
- Language server requests wait for pending edits, so Go to Declaration
right after typing answers for the current text; an empty answer right
after an edit is retried while the server catches up.
- Diagnostics come back after a window reload; error underlines stay
visible under typo / unused highlighting.
- Implementation gutter markers no longer refresh in a loop while the
server reports progress.
- A missing alternative server no longer shows as a server error.
* chore(lint): Skip agent worktrees under .claude
* fix(editor): Skip cancelled LSP requests and limit generated-code reformat
- Requests cancelled while waiting for pending edits are not sent.
- Code generated by an action is reformatted per changed hunk, so an added
import doesn't reformat the code between it and the generated lines.
- A long busy spell caused by a settle refresh re-runs it only once.
- Files dropped on a file row of another changelist move to that changelist.
- Python Implement methods: a nested class without bases ends the lookup,
class bodies continue through unindented string lines, and
`@abstractproperty` stubs become `@property`.
- Resend diagnostics goes through the host ops, and custom servers get
`max_java`.
* fix(editor): Rank the exact type first in Java constructor completion
jdtls appends the call or body to filterText (`String(${0})`); matching
on the label instead lets typing `String` rank `String` above
`StringBuilder` and the other types sharing its sort text.
* fix(editor): List identical completion items once
kotlin-language-server repeats a class once per classpath entry declaring
it, so `String()` and `String` were listed three times each.
* fix(editor): Keep the internal cancellation message out of the UI text catalog
344 рядки
9.9 KiB
Rust
344 рядки
9.9 KiB
Rust
//! IPC commands of `ide_host::ops::lsp` (the shared implementation).
|
|
|
|
use crate::state::AppState;
|
|
use ide_core::{DocId, IdeResult, Location, Pos, Range, RequestId, ServerId, TextEdit, WorkspaceEdit};
|
|
#[allow(unused_imports)]
|
|
pub use ide_host::ops::lsp::*;
|
|
use ide_lsp::types::*;
|
|
use tauri::{State, Window};
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_completion(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
trigger: Option<String>,
|
|
) -> IdeResult<CompletionList> {
|
|
ide_host::ops::lsp::lsp_completion(&state.host, window.label(), request, doc, pos, trigger).await
|
|
}
|
|
|
|
/// Inline (ghost text) suggestions at `pos`; `automatic` when triggered by typing.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_inline_completion(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
automatic: bool,
|
|
) -> IdeResult<Vec<InlineCompletionItem>> {
|
|
ide_host::ops::lsp::lsp_inline_completion(&state.host, window.label(), request, doc, pos, automatic).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_resolve_completion(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
item: CompletionItem,
|
|
) -> IdeResult<CompletionItem> {
|
|
ide_host::ops::lsp::lsp_resolve_completion(&state.host, window.label(), doc, item).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_hover(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
) -> IdeResult<Option<Hover>> {
|
|
ide_host::ops::lsp::lsp_hover(&state.host, window.label(), request, doc, pos).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_signature_help(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
) -> IdeResult<Option<SignatureHelp>> {
|
|
ide_host::ops::lsp::lsp_signature_help(&state.host, window.label(), doc, pos).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_goto(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
kind: GotoKind,
|
|
) -> IdeResult<Vec<Location>> {
|
|
ide_host::ops::lsp::lsp_goto(&state.host, window.label(), doc, pos, kind).await
|
|
}
|
|
|
|
/// Implementations of the symbols at `positions`, one list per position (the
|
|
/// editor's "is implemented / overridden" gutter markers). Cancel with
|
|
/// `cancel_request(request)`.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_implementations(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
positions: Vec<Pos>,
|
|
) -> IdeResult<Vec<Vec<Location>>> {
|
|
ide_host::ops::lsp::lsp_implementations(&state.host, window.label(), request, doc, positions).await
|
|
}
|
|
|
|
/// Contents of a virtual document (library class, decompiled code) that a
|
|
/// language server returned a non-`file:` URI for. Cached per project.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_virtual_document(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
uri: String,
|
|
) -> IdeResult<VirtualDocument> {
|
|
ide_host::ops::lsp::lsp_virtual_document(&state.host, window.label(), uri).await
|
|
}
|
|
|
|
/// References of the symbol at `pos`. `project_wide` also searches project files
|
|
/// outside the language server's analysis scope; bulk scans over many symbols
|
|
/// leave it off. Cancel with `cancel_request(request)`.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_references(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
include_declaration: bool,
|
|
project_wide: bool,
|
|
) -> IdeResult<References> {
|
|
ide_host::ops::lsp::lsp_references(
|
|
&state.host,
|
|
window.label(),
|
|
request,
|
|
doc,
|
|
pos,
|
|
include_declaration,
|
|
project_wide,
|
|
)
|
|
.await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_document_highlights(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
) -> IdeResult<Vec<Highlight>> {
|
|
ide_host::ops::lsp::lsp_document_highlights(&state.host, window.label(), doc, pos).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_workspace_symbols(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
query: String,
|
|
) -> IdeResult<Vec<WorkspaceSymbol>> {
|
|
ide_host::ops::lsp::lsp_workspace_symbols(&state.host, window.label(), request, query).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_code_actions(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
range: Range,
|
|
only: Vec<String>,
|
|
) -> IdeResult<Vec<CodeAction>> {
|
|
ide_host::ops::lsp::lsp_code_actions(&state.host, window.label(), doc, range, only).await
|
|
}
|
|
|
|
/// Cancellable code actions with the kinds the servers advertise (Refactor This, refactoring availability).
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_code_action_query(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
request: RequestId,
|
|
doc: DocId,
|
|
range: Range,
|
|
only: Vec<String>,
|
|
) -> IdeResult<CodeActionQuery> {
|
|
ide_host::ops::lsp::lsp_code_action_query(&state.host, window.label(), request, doc, range, only).await
|
|
}
|
|
|
|
/// Resolves a code action's edit without applying it (intention preview).
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_resolve_code_action(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
action: CodeAction,
|
|
) -> IdeResult<CodeAction> {
|
|
ide_host::ops::lsp::lsp_resolve_code_action(&state.host, window.label(), doc, action).await
|
|
}
|
|
|
|
/// Resolves (if needed), applies the edit, then runs the command of a code action.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_apply_code_action(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
action: CodeAction,
|
|
) -> IdeResult<()> {
|
|
ide_host::ops::lsp::lsp_apply_code_action(&state.host, window.label(), doc, action).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_prepare_rename(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
) -> IdeResult<Option<Range>> {
|
|
ide_host::ops::lsp::lsp_prepare_rename(&state.host, window.label(), doc, pos).await
|
|
}
|
|
|
|
/// Computes the rename edit without applying it, so the UI can preview conflicts.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_rename(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
new_name: String,
|
|
) -> IdeResult<WorkspaceEdit> {
|
|
ide_host::ops::lsp::lsp_rename(&state.host, window.label(), doc, pos, new_name).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_format(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
range: Option<Range>,
|
|
options: FormatOptions,
|
|
) -> IdeResult<Vec<TextEdit>> {
|
|
ide_host::ops::lsp::lsp_format(&state.host, window.label(), doc, range, options).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_inlay_hints(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
range: Range,
|
|
) -> IdeResult<Vec<InlayHint>> {
|
|
ide_host::ops::lsp::lsp_inlay_hints(&state.host, window.label(), doc, range).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_semantic_tokens(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
) -> IdeResult<Option<SemanticTokens>> {
|
|
ide_host::ops::lsp::lsp_semantic_tokens(&state.host, window.label(), doc).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_code_lens(window: Window, state: State<'_, AppState>, doc: DocId) -> IdeResult<Vec<CodeLens>> {
|
|
ide_host::ops::lsp::lsp_code_lens(&state.host, window.label(), doc).await
|
|
}
|
|
|
|
/// Links in a document (`href`s, Markdown links, `#include`s…) from its language servers.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_document_links(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
) -> IdeResult<Vec<DocumentLink>> {
|
|
ide_host::ops::lsp::lsp_document_links(&state.host, window.label(), doc).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_call_hierarchy(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
direction: HierarchyDirection,
|
|
) -> IdeResult<Vec<HierarchyItem>> {
|
|
ide_host::ops::lsp::lsp_call_hierarchy(&state.host, window.label(), doc, pos, direction).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_type_hierarchy(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
pos: Pos,
|
|
direction: HierarchyDirection,
|
|
) -> IdeResult<Vec<HierarchyItem>> {
|
|
ide_host::ops::lsp::lsp_type_hierarchy(&state.host, window.label(), doc, pos, direction).await
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn lsp_servers(window: Window, state: State<'_, AppState>) -> IdeResult<Vec<ServerInfo>> {
|
|
ide_host::ops::lsp::lsp_servers(&state.host, window.label())
|
|
}
|
|
|
|
/// Re-emits the language servers' current diagnostics (the UI loaded after they arrived).
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn lsp_resend_diagnostics(window: Window, state: State<'_, AppState>) -> IdeResult<()> {
|
|
ide_host::ops::lsp::lsp_resend_diagnostics(&state.host, window.label())
|
|
}
|
|
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_restart(window: Window, state: State<'_, AppState>, server: ServerId) -> IdeResult<()> {
|
|
ide_host::ops::lsp::lsp_restart(&state.host, window.label(), server).await
|
|
}
|
|
|
|
/// Applies a (previewed) workspace edit, e.g. after rename confirmation.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub fn apply_workspace_edit(window: Window, state: State<'_, AppState>, edit: WorkspaceEdit) -> IdeResult<()> {
|
|
ide_host::ops::lsp::apply_workspace_edit(&state.host, window.label(), edit)
|
|
}
|
|
|
|
/// Runs a server command (`workspace/executeCommand`), e.g. a completion item's
|
|
/// follow-up command. Edits the server requests arrive via `workspace/applyEdit`.
|
|
#[tauri::command]
|
|
#[specta::specta]
|
|
pub async fn lsp_execute_command(
|
|
window: Window,
|
|
state: State<'_, AppState>,
|
|
doc: DocId,
|
|
command: Command,
|
|
) -> IdeResult<()> {
|
|
ide_host::ops::lsp::lsp_execute_command(&state.host, window.label(), doc, command).await
|
|
}
|