Merge branch 'main' into window_context_2
This commit is contained in:
commit
c76b9794e4
45 changed files with 1760 additions and 882 deletions
|
@ -3,7 +3,7 @@ authors = ["Nathan Sobo <nathansobo@gmail.com>"]
|
|||
description = "The fast, collaborative code editor."
|
||||
edition = "2021"
|
||||
name = "zed"
|
||||
version = "0.83.0"
|
||||
version = "0.84.0"
|
||||
publish = false
|
||||
|
||||
[lib]
|
||||
|
@ -96,7 +96,7 @@ serde_derive = { workspace = true }
|
|||
serde_json = { workspace = true }
|
||||
serde_path_to_error = "0.1.4"
|
||||
simplelog = "0.9"
|
||||
smallvec = { version = "1.6", features = ["union"] }
|
||||
smallvec = { workspace = true }
|
||||
smol = "1.2.5"
|
||||
tempdir = { version = "0.3.7" }
|
||||
thiserror = "1.0.29"
|
||||
|
|
|
@ -37,121 +37,107 @@ pub fn init(
|
|||
themes: Arc<ThemeRegistry>,
|
||||
node_runtime: Arc<NodeRuntime>,
|
||||
) {
|
||||
for (name, grammar, lsp_adapter) in [
|
||||
fn adapter_arc(adapter: impl LspAdapter) -> Arc<dyn LspAdapter> {
|
||||
Arc::new(adapter)
|
||||
}
|
||||
|
||||
let languages_list = [
|
||||
(
|
||||
"c",
|
||||
tree_sitter_c::language(),
|
||||
Some(Arc::new(c::CLspAdapter) as Arc<dyn LspAdapter>),
|
||||
vec![adapter_arc(c::CLspAdapter)],
|
||||
),
|
||||
(
|
||||
"cpp",
|
||||
tree_sitter_cpp::language(),
|
||||
Some(Arc::new(c::CLspAdapter)),
|
||||
),
|
||||
(
|
||||
"css",
|
||||
tree_sitter_css::language(),
|
||||
None, //
|
||||
vec![adapter_arc(c::CLspAdapter)],
|
||||
),
|
||||
("css", tree_sitter_css::language(), vec![]),
|
||||
(
|
||||
"elixir",
|
||||
tree_sitter_elixir::language(),
|
||||
Some(Arc::new(elixir::ElixirLspAdapter)),
|
||||
vec![adapter_arc(elixir::ElixirLspAdapter)],
|
||||
),
|
||||
(
|
||||
"go",
|
||||
tree_sitter_go::language(),
|
||||
Some(Arc::new(go::GoLspAdapter)),
|
||||
vec![adapter_arc(go::GoLspAdapter)],
|
||||
),
|
||||
(
|
||||
"json",
|
||||
tree_sitter_json::language(),
|
||||
Some(Arc::new(json::JsonLspAdapter::new(
|
||||
vec![adapter_arc(json::JsonLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
languages.clone(),
|
||||
themes.clone(),
|
||||
))),
|
||||
),
|
||||
(
|
||||
"markdown",
|
||||
tree_sitter_markdown::language(),
|
||||
None, //
|
||||
))],
|
||||
),
|
||||
("markdown", tree_sitter_markdown::language(), vec![]),
|
||||
(
|
||||
"python",
|
||||
tree_sitter_python::language(),
|
||||
Some(Arc::new(python::PythonLspAdapter::new(
|
||||
vec![adapter_arc(python::PythonLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
))),
|
||||
))],
|
||||
),
|
||||
(
|
||||
"rust",
|
||||
tree_sitter_rust::language(),
|
||||
Some(Arc::new(rust::RustLspAdapter)),
|
||||
),
|
||||
(
|
||||
"toml",
|
||||
tree_sitter_toml::language(),
|
||||
None, //
|
||||
vec![adapter_arc(rust::RustLspAdapter)],
|
||||
),
|
||||
("toml", tree_sitter_toml::language(), vec![]),
|
||||
(
|
||||
"tsx",
|
||||
tree_sitter_typescript::language_tsx(),
|
||||
Some(Arc::new(typescript::TypeScriptLspAdapter::new(
|
||||
vec![adapter_arc(typescript::TypeScriptLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
))),
|
||||
))],
|
||||
),
|
||||
(
|
||||
"typescript",
|
||||
tree_sitter_typescript::language_typescript(),
|
||||
Some(Arc::new(typescript::TypeScriptLspAdapter::new(
|
||||
vec![adapter_arc(typescript::TypeScriptLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
))),
|
||||
))],
|
||||
),
|
||||
(
|
||||
"javascript",
|
||||
tree_sitter_typescript::language_tsx(),
|
||||
Some(Arc::new(typescript::TypeScriptLspAdapter::new(
|
||||
vec![adapter_arc(typescript::TypeScriptLspAdapter::new(
|
||||
node_runtime.clone(),
|
||||
))),
|
||||
))],
|
||||
),
|
||||
(
|
||||
"html",
|
||||
tree_sitter_html::language(),
|
||||
Some(Arc::new(html::HtmlLspAdapter::new(node_runtime.clone()))),
|
||||
vec![adapter_arc(html::HtmlLspAdapter::new(node_runtime.clone()))],
|
||||
),
|
||||
(
|
||||
"ruby",
|
||||
tree_sitter_ruby::language(),
|
||||
Some(Arc::new(ruby::RubyLanguageServer)),
|
||||
vec![adapter_arc(ruby::RubyLanguageServer)],
|
||||
),
|
||||
(
|
||||
"erb",
|
||||
tree_sitter_embedded_template::language(),
|
||||
Some(Arc::new(ruby::RubyLanguageServer)),
|
||||
),
|
||||
(
|
||||
"scheme",
|
||||
tree_sitter_scheme::language(),
|
||||
None, //
|
||||
),
|
||||
(
|
||||
"racket",
|
||||
tree_sitter_racket::language(),
|
||||
None, //
|
||||
vec![adapter_arc(ruby::RubyLanguageServer)],
|
||||
),
|
||||
("scheme", tree_sitter_scheme::language(), vec![]),
|
||||
("racket", tree_sitter_racket::language(), vec![]),
|
||||
(
|
||||
"lua",
|
||||
tree_sitter_lua::language(),
|
||||
Some(Arc::new(lua::LuaLspAdapter)),
|
||||
vec![adapter_arc(lua::LuaLspAdapter)],
|
||||
),
|
||||
(
|
||||
"yaml",
|
||||
tree_sitter_yaml::language(),
|
||||
Some(Arc::new(yaml::YamlLspAdapter::new(node_runtime.clone()))),
|
||||
vec![adapter_arc(yaml::YamlLspAdapter::new(node_runtime.clone()))],
|
||||
),
|
||||
] {
|
||||
languages.register(name, load_config(name), grammar, lsp_adapter, load_queries);
|
||||
];
|
||||
|
||||
for (name, grammar, lsp_adapters) in languages_list {
|
||||
languages.register(name, load_config(name), grammar, lsp_adapters, load_queries);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -163,7 +149,7 @@ pub async fn language(
|
|||
) -> Arc<Language> {
|
||||
Arc::new(
|
||||
Language::new(load_config(name), Some(grammar))
|
||||
.with_lsp_adapter(lsp_adapter)
|
||||
.with_lsp_adapters(lsp_adapter.into_iter().collect())
|
||||
.await
|
||||
.with_queries(load_queries(name))
|
||||
.unwrap(),
|
||||
|
|
|
@ -1,21 +1,23 @@
|
|||
use anyhow::{anyhow, Result};
|
||||
use async_trait::async_trait;
|
||||
use futures::StreamExt;
|
||||
use futures::{future::BoxFuture, FutureExt};
|
||||
use gpui::AppContext;
|
||||
use language::{LanguageServerBinary, LanguageServerName, LspAdapter};
|
||||
use lsp::CodeActionKind;
|
||||
use node_runtime::NodeRuntime;
|
||||
use serde_json::json;
|
||||
use serde_json::{json, Value};
|
||||
use smol::fs;
|
||||
use std::{
|
||||
any::Any,
|
||||
ffi::OsString,
|
||||
future,
|
||||
path::{Path, PathBuf},
|
||||
sync::Arc,
|
||||
};
|
||||
use util::http::HttpClient;
|
||||
use util::ResultExt;
|
||||
|
||||
fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||
fn typescript_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||
vec![
|
||||
server_path.into(),
|
||||
"--stdio".into(),
|
||||
|
@ -24,6 +26,10 @@ fn server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
|||
]
|
||||
}
|
||||
|
||||
fn eslint_server_binary_arguments(server_path: &Path) -> Vec<OsString> {
|
||||
vec![server_path.into(), "--stdio".into()]
|
||||
}
|
||||
|
||||
pub struct TypeScriptLspAdapter {
|
||||
node: Arc<NodeRuntime>,
|
||||
}
|
||||
|
@ -37,7 +43,7 @@ impl TypeScriptLspAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
struct Versions {
|
||||
struct TypeScriptVersions {
|
||||
typescript_version: String,
|
||||
server_version: String,
|
||||
}
|
||||
|
@ -52,7 +58,7 @@ impl LspAdapter for TypeScriptLspAdapter {
|
|||
&self,
|
||||
_: Arc<dyn HttpClient>,
|
||||
) -> Result<Box<dyn 'static + Send + Any>> {
|
||||
Ok(Box::new(Versions {
|
||||
Ok(Box::new(TypeScriptVersions {
|
||||
typescript_version: self.node.npm_package_latest_version("typescript").await?,
|
||||
server_version: self
|
||||
.node
|
||||
|
@ -67,7 +73,7 @@ impl LspAdapter for TypeScriptLspAdapter {
|
|||
_: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let versions = versions.downcast::<Versions>().unwrap();
|
||||
let versions = versions.downcast::<TypeScriptVersions>().unwrap();
|
||||
let server_path = container_dir.join(Self::NEW_SERVER_PATH);
|
||||
|
||||
if fs::metadata(&server_path).await.is_err() {
|
||||
|
@ -87,37 +93,28 @@ impl LspAdapter for TypeScriptLspAdapter {
|
|||
|
||||
Ok(LanguageServerBinary {
|
||||
path: self.node.binary_path().await?,
|
||||
arguments: server_binary_arguments(&server_path),
|
||||
arguments: typescript_server_binary_arguments(&server_path),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let mut last_version_dir = None;
|
||||
let mut entries = fs::read_dir(&container_dir).await?;
|
||||
while let Some(entry) = entries.next().await {
|
||||
let entry = entry?;
|
||||
if entry.file_type().await?.is_dir() {
|
||||
last_version_dir = Some(entry.path());
|
||||
}
|
||||
}
|
||||
let last_version_dir = last_version_dir.ok_or_else(|| anyhow!("no cached binary"))?;
|
||||
let old_server_path = last_version_dir.join(Self::OLD_SERVER_PATH);
|
||||
let new_server_path = last_version_dir.join(Self::NEW_SERVER_PATH);
|
||||
let old_server_path = container_dir.join(Self::OLD_SERVER_PATH);
|
||||
let new_server_path = container_dir.join(Self::NEW_SERVER_PATH);
|
||||
if new_server_path.exists() {
|
||||
Ok(LanguageServerBinary {
|
||||
path: self.node.binary_path().await?,
|
||||
arguments: server_binary_arguments(&new_server_path),
|
||||
arguments: typescript_server_binary_arguments(&new_server_path),
|
||||
})
|
||||
} else if old_server_path.exists() {
|
||||
Ok(LanguageServerBinary {
|
||||
path: self.node.binary_path().await?,
|
||||
arguments: server_binary_arguments(&old_server_path),
|
||||
arguments: typescript_server_binary_arguments(&old_server_path),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
last_version_dir
|
||||
container_dir
|
||||
))
|
||||
}
|
||||
})()
|
||||
|
@ -170,6 +167,136 @@ impl LspAdapter for TypeScriptLspAdapter {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct EsLintLspAdapter {
|
||||
node: Arc<NodeRuntime>,
|
||||
}
|
||||
|
||||
impl EsLintLspAdapter {
|
||||
const SERVER_PATH: &'static str =
|
||||
"node_modules/vscode-langservers-extracted/lib/eslint-language-server/eslintServer.js";
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn new(node: Arc<NodeRuntime>) -> Self {
|
||||
EsLintLspAdapter { node }
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl LspAdapter for EsLintLspAdapter {
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> Option<BoxFuture<'static, Value>> {
|
||||
Some(
|
||||
future::ready(json!({
|
||||
"": {
|
||||
"validate": "on",
|
||||
"packageManager": "npm",
|
||||
"useESLintClass": false,
|
||||
"experimental": {
|
||||
"useFlatConfig": false
|
||||
},
|
||||
"codeActionOnSave": {
|
||||
"mode": "all"
|
||||
},
|
||||
"format": false,
|
||||
"quiet": false,
|
||||
"onIgnoredFiles": "off",
|
||||
"options": {},
|
||||
"rulesCustomizations": [],
|
||||
"run": "onType",
|
||||
"problems": {
|
||||
"shortenToSingleLine": false
|
||||
},
|
||||
"nodePath": null,
|
||||
"workspaceFolder": {
|
||||
"name": "testing_ts",
|
||||
"uri": "file:///Users/julia/Stuff/testing_ts"
|
||||
},
|
||||
"codeAction": {
|
||||
"disableRuleComment": {
|
||||
"enable": true,
|
||||
"location": "separateLine",
|
||||
"commentStyle": "line"
|
||||
},
|
||||
"showDocumentation": {
|
||||
"enable": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}))
|
||||
.boxed(),
|
||||
)
|
||||
}
|
||||
|
||||
async fn name(&self) -> LanguageServerName {
|
||||
LanguageServerName("eslint".into())
|
||||
}
|
||||
|
||||
async fn fetch_latest_server_version(
|
||||
&self,
|
||||
_: Arc<dyn HttpClient>,
|
||||
) -> Result<Box<dyn 'static + Send + Any>> {
|
||||
Ok(Box::new(
|
||||
self.node
|
||||
.npm_package_latest_version("vscode-langservers-extracted")
|
||||
.await?,
|
||||
))
|
||||
}
|
||||
|
||||
async fn fetch_server_binary(
|
||||
&self,
|
||||
versions: Box<dyn 'static + Send + Any>,
|
||||
_: Arc<dyn HttpClient>,
|
||||
container_dir: PathBuf,
|
||||
) -> Result<LanguageServerBinary> {
|
||||
let version = versions.downcast::<String>().unwrap();
|
||||
let server_path = container_dir.join(Self::SERVER_PATH);
|
||||
|
||||
if fs::metadata(&server_path).await.is_err() {
|
||||
self.node
|
||||
.npm_install_packages(
|
||||
[("vscode-langservers-extracted", version.as_str())],
|
||||
&container_dir,
|
||||
)
|
||||
.await?;
|
||||
}
|
||||
|
||||
Ok(LanguageServerBinary {
|
||||
path: self.node.binary_path().await?,
|
||||
arguments: eslint_server_binary_arguments(&server_path),
|
||||
})
|
||||
}
|
||||
|
||||
async fn cached_server_binary(&self, container_dir: PathBuf) -> Option<LanguageServerBinary> {
|
||||
(|| async move {
|
||||
let server_path = container_dir.join(Self::SERVER_PATH);
|
||||
if server_path.exists() {
|
||||
Ok(LanguageServerBinary {
|
||||
path: self.node.binary_path().await?,
|
||||
arguments: eslint_server_binary_arguments(&server_path),
|
||||
})
|
||||
} else {
|
||||
Err(anyhow!(
|
||||
"missing executable in directory {:?}",
|
||||
container_dir
|
||||
))
|
||||
}
|
||||
})()
|
||||
.await
|
||||
.log_err()
|
||||
}
|
||||
|
||||
async fn label_for_completion(
|
||||
&self,
|
||||
_item: &lsp::CompletionItem,
|
||||
_language: &Arc<language::Language>,
|
||||
) -> Option<language::CodeLabel> {
|
||||
None
|
||||
}
|
||||
|
||||
async fn initialization_options(&self) -> Option<serde_json::Value> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use gpui::TestAppContext;
|
||||
|
|
|
@ -21,7 +21,7 @@ use log::LevelFilter;
|
|||
use node_runtime::NodeRuntime;
|
||||
use parking_lot::Mutex;
|
||||
use project::Fs;
|
||||
use serde_json::json;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use settings::{
|
||||
self, settings_file::SettingsFile, KeymapFileContent, Settings, SettingsFileContent,
|
||||
WorkingDirectory,
|
||||
|
@ -317,6 +317,30 @@ fn init_logger() {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct LocationData {
|
||||
file: String,
|
||||
line: u32,
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize)]
|
||||
struct Panic {
|
||||
thread: String,
|
||||
payload: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
location_data: Option<LocationData>,
|
||||
backtrace: Vec<String>,
|
||||
// TODO
|
||||
// stripped_backtrace: String,
|
||||
}
|
||||
|
||||
#[derive(Serialize)]
|
||||
struct PanicRequest {
|
||||
panic: Panic,
|
||||
version: String,
|
||||
token: String,
|
||||
}
|
||||
|
||||
fn init_panic_hook(app_version: String) {
|
||||
let is_pty = stdout_is_a_pty();
|
||||
panic::set_hook(Box::new(move |info| {
|
||||
|
@ -333,39 +357,38 @@ fn init_panic_hook(app_version: String) {
|
|||
},
|
||||
};
|
||||
|
||||
let message = match info.location() {
|
||||
Some(location) => {
|
||||
format!(
|
||||
"thread '{}' panicked at '{}'\n{}:{}\n{:?}",
|
||||
thread,
|
||||
payload,
|
||||
location.file(),
|
||||
location.line(),
|
||||
backtrace
|
||||
)
|
||||
}
|
||||
None => format!(
|
||||
"thread '{}' panicked at '{}'\n{:?}",
|
||||
thread, payload, backtrace
|
||||
),
|
||||
let panic_data = Panic {
|
||||
thread: thread.into(),
|
||||
payload: payload.into(),
|
||||
location_data: info.location().map(|location| LocationData {
|
||||
file: location.file().into(),
|
||||
line: location.line(),
|
||||
}),
|
||||
backtrace: format!("{:?}", backtrace)
|
||||
.split("\n")
|
||||
.map(|line| line.to_string())
|
||||
.collect(),
|
||||
// modified_backtrace: None,
|
||||
};
|
||||
|
||||
if is_pty {
|
||||
eprintln!("{}", message);
|
||||
return;
|
||||
}
|
||||
if let Some(panic_data_json) = serde_json::to_string_pretty(&panic_data).log_err() {
|
||||
if is_pty {
|
||||
eprintln!("{}", panic_data_json);
|
||||
return;
|
||||
}
|
||||
|
||||
let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
|
||||
let panic_file_path =
|
||||
paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, timestamp));
|
||||
let panic_file = std::fs::OpenOptions::new()
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(&panic_file_path)
|
||||
.log_err();
|
||||
if let Some(mut panic_file) = panic_file {
|
||||
write!(&mut panic_file, "{}", message).log_err();
|
||||
panic_file.flush().log_err();
|
||||
let timestamp = chrono::Utc::now().format("%Y_%m_%d %H_%M_%S").to_string();
|
||||
let panic_file_path =
|
||||
paths::LOGS_DIR.join(format!("zed-{}-{}.panic", app_version, timestamp));
|
||||
let panic_file = std::fs::OpenOptions::new()
|
||||
.append(true)
|
||||
.create(true)
|
||||
.open(&panic_file_path)
|
||||
.log_err();
|
||||
if let Some(mut panic_file) = panic_file {
|
||||
write!(&mut panic_file, "{}", panic_data_json).log_err();
|
||||
panic_file.flush().log_err();
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
@ -402,15 +425,17 @@ fn upload_previous_panics(http: Arc<dyn HttpClient>, cx: &mut AppContext) {
|
|||
};
|
||||
|
||||
if diagnostics_telemetry {
|
||||
let text = smol::fs::read_to_string(&child_path)
|
||||
let panic_data_text = smol::fs::read_to_string(&child_path)
|
||||
.await
|
||||
.context("error reading panic file")?;
|
||||
let body = serde_json::to_string(&json!({
|
||||
"text": text,
|
||||
"version": version,
|
||||
"token": ZED_SECRET_CLIENT_TOKEN,
|
||||
}))
|
||||
|
||||
let body = serde_json::to_string(&PanicRequest {
|
||||
panic: serde_json::from_str(&panic_data_text)?,
|
||||
version: version.to_string(),
|
||||
token: ZED_SECRET_CLIENT_TOKEN.into(),
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
let request = Request::post(&panic_report_url)
|
||||
.redirect_policy(isahc::config::RedirectPolicy::Follow)
|
||||
.header("Content-Type", "application/json")
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue