mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 08:52:12 +00:00
- Git › Show History is offered for folders, multi-selection and the project root, not just single files. - The Push dialog lets you pick any configured remote; pushing to another remote keeps the upstream's branch name and shows outgoing commits against that remote's branch. - The Changes toolbar gains New Changelist (changelists already supported new/edit/delete/set active/move). - Compare with Current gains Show Diff, opening the whole-project diff between the branch and HEAD. - Merge view: F7 / Shift+F7 navigate conflicts, the three panes scroll together, and each side pane can be annotated with Git Blame of its own content. - Windows-only test fixes in ide-lsp and ide-sdk. Fixes #343 Fixes #310 Fixes #358 Fixes #348 Fixes #320 Refs #317 Co-authored-by: a-rookie-of-C-language <[email protected]>
95 lines
4.1 KiB
Rust
95 lines
4.1 KiB
Rust
//! Vue Language Server (Volar 3): the TypeScript it loads as a library, and the
|
||
//! `@vue/typescript-plugin` that vtsls' tsserver hosts for it (hybrid mode).
|
||
|
||
use crate::npm::{find_command, package_dir};
|
||
use std::ffi::OsStr;
|
||
use std::path::{Path, PathBuf};
|
||
|
||
pub(crate) const SERVER: &str = "vue-language-server";
|
||
const PACKAGE: &str = "@vue/language-server";
|
||
const PLUGIN: &str = "@vue/typescript-plugin";
|
||
|
||
/// The TypeScript `lib` directory has the language-service API (`typescript.js`).
|
||
/// TypeScript 7, the native port, ships only `tsc`.
|
||
pub(crate) fn has_ts_api(lib: &Path) -> bool {
|
||
lib.join("typescript.js").is_file()
|
||
}
|
||
|
||
/// `@vue/language-server`'s directory for the `vue-language-server` command.
|
||
pub(crate) fn server_package(command: &str, path: &OsStr) -> Option<PathBuf> {
|
||
package_dir(&find_command(command, path)?, PACKAGE)
|
||
}
|
||
|
||
/// The TypeScript `require('typescript')` resolves to from `package`, when usable.
|
||
pub(crate) fn own_typescript(package: &Path) -> Option<PathBuf> {
|
||
package.ancestors().map(|a| a.join("node_modules").join("typescript").join("lib")).find(|l| has_ts_api(l))
|
||
}
|
||
|
||
/// vtsls `globalPlugins` entry loading the Vue plugin shipped with `package`.
|
||
pub(crate) fn tsserver_plugin(package: &Path) -> serde_json::Value {
|
||
serde_json::json!({
|
||
"name": PLUGIN,
|
||
"location": package.to_string_lossy(),
|
||
"languages": ["vue"],
|
||
"configNamespace": "typescript",
|
||
"enableForWorkspaceTypeScriptVersions": true,
|
||
})
|
||
}
|
||
|
||
pub(crate) fn missing_typescript_message() -> String {
|
||
"Vue Language Server needs TypeScript 5 or 6 (TypeScript 7 has no language service API). \
|
||
Reinstall it in Settings › Languages & Frameworks › Language Servers, add typescript@6 \
|
||
to the project, or pick a TypeScript version in Settings › Languages & Frameworks › TypeScript."
|
||
.to_owned()
|
||
}
|
||
|
||
#[cfg(test)]
|
||
mod tests {
|
||
use super::*;
|
||
|
||
fn touch(p: &Path) {
|
||
std::fs::create_dir_all(p.parent().unwrap()).unwrap();
|
||
std::fs::write(p, "{}").unwrap();
|
||
}
|
||
|
||
#[test]
|
||
fn finds_the_package_of_every_npm_install_layout() {
|
||
let tmp = tempfile::tempdir().unwrap();
|
||
let t = tmp.path();
|
||
// (executable, package.json) per layout.
|
||
let layouts = [
|
||
// The IDE's tools dir / a project: node_modules/.bin shim.
|
||
("tools/node_modules/.bin/vue-language-server", "tools/node_modules/@vue/language-server/package.json"),
|
||
// Windows global: %APPDATA%\npm\vue-language-server(.cmd) + %APPDATA%\npm\node_modules.
|
||
("npm/vue-language-server", "npm/node_modules/@vue/language-server/package.json"),
|
||
// Unix global prefix: <prefix>/bin + <prefix>/lib/node_modules.
|
||
("prefix/bin/vue-language-server", "prefix/lib/node_modules/@vue/language-server/package.json"),
|
||
];
|
||
for (bin, pkg) in layouts {
|
||
touch(&t.join(bin));
|
||
touch(&t.join(pkg));
|
||
let found = server_package(&t.join(bin).to_string_lossy(), OsStr::new(""));
|
||
assert_eq!(found, Some(t.join(pkg).parent().unwrap().to_path_buf()), "{bin}");
|
||
}
|
||
let path = std::env::join_paths([t.join("tools/node_modules/.bin")]).unwrap();
|
||
// npm's `.bin` shims on Windows get a `.cmd` (or `.exe`) name; the bare
|
||
// name is not executable there.
|
||
let shim = if cfg!(windows) { "vue-language-server.cmd" } else { SERVER };
|
||
touch(&t.join("tools/node_modules/.bin").join(shim));
|
||
assert_eq!(server_package(SERVER, &path), Some(t.join("tools/node_modules/@vue/language-server")));
|
||
assert_eq!(server_package("not-installed", &path), None);
|
||
}
|
||
|
||
#[test]
|
||
fn own_typescript_skips_typescript_7() {
|
||
let tmp = tempfile::tempdir().unwrap();
|
||
let pkg = tmp.path().join("node_modules/@vue/language-server");
|
||
touch(&pkg.join("package.json"));
|
||
// TypeScript 7 ships only `tsc`.
|
||
touch(&tmp.path().join("node_modules/typescript/lib/tsc.js"));
|
||
assert_eq!(own_typescript(&pkg), None);
|
||
touch(&tmp.path().join("node_modules/typescript/lib/typescript.js"));
|
||
assert_eq!(own_typescript(&pkg), Some(tmp.path().join("node_modules/typescript/lib")));
|
||
}
|
||
}
|