дзеркало
https://github.com/l0ng-ai/openidea.git
синхронізовано 2026-11-09 19:25:54 +02:00
feat(nav): Complete file paths and flag unresolved web file references
Path completion in href/src/url()/@import, Markdown links and path-like strings, folders first. HTML and CSS paths that name no file get a 'Cannot resolve file' warning. File references resolve in the backend like IDEA's: relative to the file, /-rooted against the project and resource roots.
Цей коміт міститься в:
1 джерело
87b463990c
коміт
68dcea409c
16 files changed
+652
-74
No files matched your search
@@ -104,6 +104,9 @@ pub fn builder() -> tauri_specta::Builder<tauri::Wry> {
|
||||
nav::mark_recent,
|
||||
nav::recent_files,
|
||||
nav::web_goto,
|
||||
nav::fs_resolve_reference,
|
||||
nav::path_completions,
|
||||
nav::web_unresolved_references,
|
||||
search::search_start,
|
||||
search::replace_in_files,
|
||||
search::replace_preview,
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
use super::doc::blocking;
|
||||
use crate::state::AppState;
|
||||
use ide_core::{DocId, IdeResult, Location, Pos};
|
||||
use crate::state::{AppState, Project};
|
||||
use ide_core::{DocId, IdeResult, IpcPath, Location, Pos};
|
||||
use ide_index::{FileMatch, IndexStatus, SymbolFilter, SymbolMatch};
|
||||
use ide_language::WebReference;
|
||||
use ide_language::{FileReference, WebReference};
|
||||
use ide_workspace::file_refs::{self, PathCompletion};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specta::Type;
|
||||
use std::path::PathBuf;
|
||||
@@ -96,3 +97,74 @@ pub async fn web_goto(window: Window, state: State<'_, AppState>, doc: DocId, po
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// The project root and its resource roots (served at `/`), for file references.
|
||||
fn reference_roots(project: &Project) -> (PathBuf, Vec<PathBuf>) {
|
||||
let resources = project.roots().resource_dirs().iter().map(|d| project.root.join(d)).collect();
|
||||
(project.root.clone(), resources)
|
||||
}
|
||||
|
||||
/// The existing file or directory a path written in `from` names (`href`, `url()`, a string literal).
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn fs_resolve_reference(
|
||||
window: Window,
|
||||
state: State<'_, AppState>,
|
||||
from: IpcPath,
|
||||
value: String,
|
||||
) -> IdeResult<Option<IpcPath>> {
|
||||
let project = state.project(window.label()).ok();
|
||||
blocking(move || {
|
||||
let (root, resources) = project.as_deref().map(reference_roots).unzip();
|
||||
let resources = resources.unwrap_or_default();
|
||||
Ok(file_refs::resolve(&value, &from, root.as_deref(), &resources).map(Into::into))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Files and folders that continue `prefix`, a path being typed in `from`.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn path_completions(
|
||||
window: Window,
|
||||
state: State<'_, AppState>,
|
||||
from: IpcPath,
|
||||
prefix: String,
|
||||
) -> IdeResult<Vec<PathCompletion>> {
|
||||
let project = state.project(window.label()).ok();
|
||||
blocking(move || {
|
||||
let (root, resources) = project.as_deref().map(reference_roots).unzip();
|
||||
let resources = resources.unwrap_or_default();
|
||||
Ok(file_refs::complete(&prefix, &from, root.as_deref(), &resources))
|
||||
})
|
||||
.await
|
||||
}
|
||||
|
||||
/// Paths in an HTML document or stylesheet that name no existing file.
|
||||
#[tauri::command]
|
||||
#[specta::specta]
|
||||
pub async fn web_unresolved_references(
|
||||
window: Window,
|
||||
state: State<'_, AppState>,
|
||||
doc: DocId,
|
||||
) -> IdeResult<Vec<FileReference>> {
|
||||
let project = state.project(window.label())?;
|
||||
let syntax = state.syntax();
|
||||
blocking(move || {
|
||||
let snap = project.documents.snapshot(doc)?;
|
||||
if snap.large {
|
||||
return Ok(Vec::new());
|
||||
}
|
||||
let (root, resources) = reference_roots(&project);
|
||||
Ok(syntax
|
||||
.web_file_references(&snap.language, &snap.text)
|
||||
.into_iter()
|
||||
.filter(|r| {
|
||||
file_refs::is_file_reference(&r.value)
|
||||
&& !file_refs::path_part(&r.value).is_empty()
|
||||
&& file_refs::resolve(&r.value, &snap.path, Some(&root), &resources).is_none()
|
||||
})
|
||||
.collect())
|
||||
})
|
||||
.await
|
||||
}
|
||||
Reference in new issue
Заблокувати користувача