Fix TypeScript diagnostics (#3457)
Deals with https://github.com/zed-industries/community/issues/2124 * sends more ClientCapabilities LSP data, diagnostics capabilities in particular: those are now required by typescript-language-server LSP to start publishing diagnostics * sends more parameters during eslint workspace initialization, so it is able to correctly look up project's typescript config Presumably, it's not enough and some convoluted project set ups may break still, but let's wait for examples and feedback. Release Notes: - Fixed typescript-language-server diagnostics not appearing for newer server versions; fixed eslint diagnostics using wrong directory for typescript config lookup
This commit is contained in:
commit
7b76db4b50
16 changed files with 140 additions and 44 deletions
|
@ -197,8 +197,12 @@ impl CachedLspAdapter {
|
|||
self.adapter.code_action_kinds()
|
||||
}
|
||||
|
||||
pub fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
self.adapter.workspace_configuration(cx)
|
||||
pub fn workspace_configuration(
|
||||
&self,
|
||||
workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
self.adapter.workspace_configuration(workspace_root, cx)
|
||||
}
|
||||
|
||||
pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) {
|
||||
|
@ -312,7 +316,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
None
|
||||
}
|
||||
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
futures::future::ready(serde_json::json!({})).boxed()
|
||||
}
|
||||
|
||||
|
|
|
@ -200,8 +200,12 @@ impl CachedLspAdapter {
|
|||
self.adapter.code_action_kinds()
|
||||
}
|
||||
|
||||
pub fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
self.adapter.workspace_configuration(cx)
|
||||
pub fn workspace_configuration(
|
||||
&self,
|
||||
workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
self.adapter.workspace_configuration(workspace_root, cx)
|
||||
}
|
||||
|
||||
pub fn process_diagnostics(&self, params: &mut lsp::PublishDiagnosticsParams) {
|
||||
|
@ -315,7 +319,7 @@ pub trait LspAdapter: 'static + Send + Sync {
|
|||
None
|
||||
}
|
||||
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(&self, _: &Path, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
futures::future::ready(serde_json::json!({})).boxed()
|
||||
}
|
||||
|
||||
|
|
|
@ -429,8 +429,8 @@ impl LanguageServer {
|
|||
let root_uri = Url::from_file_path(&self.root_path).unwrap();
|
||||
#[allow(deprecated)]
|
||||
let params = InitializeParams {
|
||||
process_id: Default::default(),
|
||||
root_path: Default::default(),
|
||||
process_id: None,
|
||||
root_path: None,
|
||||
root_uri: Some(root_uri.clone()),
|
||||
initialization_options: options,
|
||||
capabilities: ClientCapabilities {
|
||||
|
@ -451,12 +451,15 @@ impl LanguageServer {
|
|||
inlay_hint: Some(InlayHintWorkspaceClientCapabilities {
|
||||
refresh_support: Some(true),
|
||||
}),
|
||||
diagnostic: Some(DiagnosticWorkspaceClientCapabilities {
|
||||
refresh_support: None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
text_document: Some(TextDocumentClientCapabilities {
|
||||
definition: Some(GotoCapability {
|
||||
link_support: Some(true),
|
||||
..Default::default()
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
code_action: Some(CodeActionClientCapabilities {
|
||||
code_action_literal_support: Some(CodeActionLiteralSupport {
|
||||
|
@ -501,7 +504,7 @@ impl LanguageServer {
|
|||
}),
|
||||
hover: Some(HoverClientCapabilities {
|
||||
content_format: Some(vec![MarkupKind::Markdown]),
|
||||
..Default::default()
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
inlay_hint: Some(InlayHintClientCapabilities {
|
||||
resolve_support: Some(InlayHintResolveClientCapabilities {
|
||||
|
@ -515,6 +518,20 @@ impl LanguageServer {
|
|||
}),
|
||||
dynamic_registration: Some(false),
|
||||
}),
|
||||
publish_diagnostics: Some(PublishDiagnosticsClientCapabilities {
|
||||
related_information: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
on_type_formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
diagnostic: Some(DiagnosticClientCapabilities {
|
||||
related_document_support: Some(true),
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
experimental: Some(json!({
|
||||
|
@ -524,15 +541,15 @@ impl LanguageServer {
|
|||
work_done_progress: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
general: None,
|
||||
},
|
||||
trace: Default::default(),
|
||||
trace: None,
|
||||
workspace_folders: Some(vec![WorkspaceFolder {
|
||||
uri: root_uri,
|
||||
name: Default::default(),
|
||||
}]),
|
||||
client_info: Default::default(),
|
||||
locale: Default::default(),
|
||||
client_info: None,
|
||||
locale: None,
|
||||
};
|
||||
|
||||
let response = self.request::<request::Initialize>(params).await?;
|
||||
|
|
|
@ -434,8 +434,8 @@ impl LanguageServer {
|
|||
let root_uri = Url::from_file_path(&self.root_path).unwrap();
|
||||
#[allow(deprecated)]
|
||||
let params = InitializeParams {
|
||||
process_id: Default::default(),
|
||||
root_path: Default::default(),
|
||||
process_id: None,
|
||||
root_path: None,
|
||||
root_uri: Some(root_uri.clone()),
|
||||
initialization_options: options,
|
||||
capabilities: ClientCapabilities {
|
||||
|
@ -456,12 +456,15 @@ impl LanguageServer {
|
|||
inlay_hint: Some(InlayHintWorkspaceClientCapabilities {
|
||||
refresh_support: Some(true),
|
||||
}),
|
||||
diagnostic: Some(DiagnosticWorkspaceClientCapabilities {
|
||||
refresh_support: None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
text_document: Some(TextDocumentClientCapabilities {
|
||||
definition: Some(GotoCapability {
|
||||
link_support: Some(true),
|
||||
..Default::default()
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
code_action: Some(CodeActionClientCapabilities {
|
||||
code_action_literal_support: Some(CodeActionLiteralSupport {
|
||||
|
@ -503,7 +506,7 @@ impl LanguageServer {
|
|||
}),
|
||||
hover: Some(HoverClientCapabilities {
|
||||
content_format: Some(vec![MarkupKind::Markdown]),
|
||||
..Default::default()
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
inlay_hint: Some(InlayHintClientCapabilities {
|
||||
resolve_support: Some(InlayHintResolveClientCapabilities {
|
||||
|
@ -517,6 +520,20 @@ impl LanguageServer {
|
|||
}),
|
||||
dynamic_registration: Some(false),
|
||||
}),
|
||||
publish_diagnostics: Some(PublishDiagnosticsClientCapabilities {
|
||||
related_information: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
on_type_formatting: Some(DynamicRegistrationClientCapabilities {
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
diagnostic: Some(DiagnosticClientCapabilities {
|
||||
related_document_support: Some(true),
|
||||
dynamic_registration: None,
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
experimental: Some(json!({
|
||||
|
@ -526,15 +543,15 @@ impl LanguageServer {
|
|||
work_done_progress: Some(true),
|
||||
..Default::default()
|
||||
}),
|
||||
..Default::default()
|
||||
general: None,
|
||||
},
|
||||
trace: Default::default(),
|
||||
trace: None,
|
||||
workspace_folders: Some(vec![WorkspaceFolder {
|
||||
uri: root_uri,
|
||||
name: Default::default(),
|
||||
}]),
|
||||
client_info: Default::default(),
|
||||
locale: Default::default(),
|
||||
client_info: None,
|
||||
locale: None,
|
||||
};
|
||||
|
||||
let response = self.request::<request::Initialize>(params).await?;
|
||||
|
|
|
@ -2641,8 +2641,9 @@ impl Project {
|
|||
});
|
||||
|
||||
for (adapter, server) in servers {
|
||||
let workspace_config =
|
||||
cx.update(|cx| adapter.workspace_configuration(cx)).await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(server.root_path(), cx))
|
||||
.await;
|
||||
server
|
||||
.notify::<lsp::notification::DidChangeConfiguration>(
|
||||
lsp::DidChangeConfigurationParams {
|
||||
|
@ -2753,7 +2754,7 @@ impl Project {
|
|||
stderr_capture.clone(),
|
||||
language.clone(),
|
||||
adapter.clone(),
|
||||
worktree_path,
|
||||
Arc::clone(&worktree_path),
|
||||
ProjectLspAdapterDelegate::new(self, cx),
|
||||
cx,
|
||||
) {
|
||||
|
@ -2776,6 +2777,7 @@ impl Project {
|
|||
cx.spawn_weak(|this, mut cx| async move {
|
||||
let result = Self::setup_and_insert_language_server(
|
||||
this,
|
||||
&worktree_path,
|
||||
override_options,
|
||||
pending_server,
|
||||
adapter.clone(),
|
||||
|
@ -2891,6 +2893,7 @@ impl Project {
|
|||
|
||||
async fn setup_and_insert_language_server(
|
||||
this: WeakModelHandle<Self>,
|
||||
worktree_path: &Path,
|
||||
override_initialization_options: Option<serde_json::Value>,
|
||||
pending_server: PendingLanguageServer,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
|
@ -2903,6 +2906,7 @@ impl Project {
|
|||
this,
|
||||
override_initialization_options,
|
||||
pending_server,
|
||||
worktree_path,
|
||||
adapter.clone(),
|
||||
server_id,
|
||||
cx,
|
||||
|
@ -2932,11 +2936,14 @@ impl Project {
|
|||
this: WeakModelHandle<Self>,
|
||||
override_options: Option<serde_json::Value>,
|
||||
pending_server: PendingLanguageServer,
|
||||
worktree_path: &Path,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
server_id: LanguageServerId,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<Arc<LanguageServer>> {
|
||||
let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx)).await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(worktree_path, cx))
|
||||
.await;
|
||||
let language_server = pending_server.task.await?;
|
||||
|
||||
language_server
|
||||
|
@ -2964,11 +2971,14 @@ impl Project {
|
|||
language_server
|
||||
.on_request::<lsp::request::WorkspaceConfiguration, _, _>({
|
||||
let adapter = adapter.clone();
|
||||
let worktree_path = worktree_path.to_path_buf();
|
||||
move |params, mut cx| {
|
||||
let adapter = adapter.clone();
|
||||
let worktree_path = worktree_path.clone();
|
||||
async move {
|
||||
let workspace_config =
|
||||
cx.update(|cx| adapter.workspace_configuration(cx)).await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(&worktree_path, cx))
|
||||
.await;
|
||||
Ok(params
|
||||
.items
|
||||
.into_iter()
|
||||
|
|
|
@ -2677,8 +2677,9 @@ impl Project {
|
|||
})?;
|
||||
|
||||
for (adapter, server) in servers {
|
||||
let workspace_config =
|
||||
cx.update(|cx| adapter.workspace_configuration(cx))?.await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(server.root_path(), cx))?
|
||||
.await;
|
||||
server
|
||||
.notify::<lsp::notification::DidChangeConfiguration>(
|
||||
lsp::DidChangeConfigurationParams {
|
||||
|
@ -2790,7 +2791,7 @@ impl Project {
|
|||
stderr_capture.clone(),
|
||||
language.clone(),
|
||||
adapter.clone(),
|
||||
worktree_path,
|
||||
Arc::clone(&worktree_path),
|
||||
ProjectLspAdapterDelegate::new(self, cx),
|
||||
cx,
|
||||
) {
|
||||
|
@ -2822,6 +2823,7 @@ impl Project {
|
|||
cx.spawn(move |this, mut cx| async move {
|
||||
let result = Self::setup_and_insert_language_server(
|
||||
this.clone(),
|
||||
&worktree_path,
|
||||
initialization_options,
|
||||
pending_server,
|
||||
adapter.clone(),
|
||||
|
@ -2942,6 +2944,7 @@ impl Project {
|
|||
|
||||
async fn setup_and_insert_language_server(
|
||||
this: WeakModel<Self>,
|
||||
worktree_path: &Path,
|
||||
initialization_options: Option<serde_json::Value>,
|
||||
pending_server: PendingLanguageServer,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
|
@ -2954,6 +2957,7 @@ impl Project {
|
|||
this.clone(),
|
||||
initialization_options,
|
||||
pending_server,
|
||||
worktree_path,
|
||||
adapter.clone(),
|
||||
server_id,
|
||||
cx,
|
||||
|
@ -2983,11 +2987,14 @@ impl Project {
|
|||
this: WeakModel<Self>,
|
||||
initialization_options: Option<serde_json::Value>,
|
||||
pending_server: PendingLanguageServer,
|
||||
worktree_path: &Path,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
server_id: LanguageServerId,
|
||||
cx: &mut AsyncAppContext,
|
||||
) -> Result<Arc<LanguageServer>> {
|
||||
let workspace_config = cx.update(|cx| adapter.workspace_configuration(cx))?.await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(worktree_path, cx))?
|
||||
.await;
|
||||
let language_server = pending_server.task.await?;
|
||||
|
||||
language_server
|
||||
|
@ -3016,11 +3023,14 @@ impl Project {
|
|||
language_server
|
||||
.on_request::<lsp::request::WorkspaceConfiguration, _, _>({
|
||||
let adapter = adapter.clone();
|
||||
let worktree_path = worktree_path.to_path_buf();
|
||||
move |params, cx| {
|
||||
let adapter = adapter.clone();
|
||||
let worktree_path = worktree_path.clone();
|
||||
async move {
|
||||
let workspace_config =
|
||||
cx.update(|cx| adapter.workspace_configuration(cx))?.await;
|
||||
let workspace_config = cx
|
||||
.update(|cx| adapter.workspace_configuration(&worktree_path, cx))?
|
||||
.await;
|
||||
Ok(params
|
||||
.items
|
||||
.into_iter()
|
||||
|
|
|
@ -105,6 +105,7 @@ impl LspAdapter for JsonLspAdapter {
|
|||
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, serde_json::Value> {
|
||||
let action_names = cx.all_action_names().collect::<Vec<_>>();
|
||||
|
|
|
@ -29,7 +29,6 @@ pub struct IntelephenseLspAdapter {
|
|||
impl IntelephenseLspAdapter {
|
||||
const SERVER_PATH: &'static str = "node_modules/intelephense/lib/intelephense.js";
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
|
||||
Self { node }
|
||||
}
|
||||
|
|
|
@ -107,7 +107,11 @@ impl LspAdapter for TailwindLspAdapter {
|
|||
}))
|
||||
}
|
||||
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
_: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
future::ready(json!({
|
||||
"tailwindCSS": {
|
||||
"emmetCompletions": true,
|
||||
|
|
|
@ -205,7 +205,6 @@ pub struct EsLintLspAdapter {
|
|||
impl EsLintLspAdapter {
|
||||
const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js";
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
|
||||
EsLintLspAdapter { node }
|
||||
}
|
||||
|
@ -213,13 +212,23 @@ impl EsLintLspAdapter {
|
|||
|
||||
#[async_trait]
|
||||
impl LspAdapter for EsLintLspAdapter {
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
workspace_root: &Path,
|
||||
_: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
future::ready(json!({
|
||||
"": {
|
||||
"validate": "on",
|
||||
"rulesCustomizations": [],
|
||||
"run": "onType",
|
||||
"nodePath": null,
|
||||
"workingDirectory": {"mode": "auto"},
|
||||
"workspaceFolder": {
|
||||
"uri": workspace_root,
|
||||
"name": workspace_root.file_name()
|
||||
.unwrap_or_else(|| workspace_root.as_os_str()),
|
||||
},
|
||||
}
|
||||
}))
|
||||
.boxed()
|
||||
|
|
|
@ -93,7 +93,11 @@ impl LspAdapter for YamlLspAdapter {
|
|||
) -> Option<LanguageServerBinary> {
|
||||
get_cached_server_binary(container_dir, &*self.node).await
|
||||
}
|
||||
fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
let tab_size = all_language_settings(None, cx)
|
||||
.language(Some("YAML"))
|
||||
.tab_size;
|
||||
|
|
|
@ -105,6 +105,7 @@ impl LspAdapter for JsonLspAdapter {
|
|||
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, serde_json::Value> {
|
||||
let action_names = cx.all_action_names();
|
||||
|
|
|
@ -29,7 +29,6 @@ pub struct IntelephenseLspAdapter {
|
|||
impl IntelephenseLspAdapter {
|
||||
const SERVER_PATH: &'static str = "node_modules/intelephense/lib/intelephense.js";
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
|
||||
Self { node }
|
||||
}
|
||||
|
|
|
@ -107,7 +107,11 @@ impl LspAdapter for TailwindLspAdapter {
|
|||
}))
|
||||
}
|
||||
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
_: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
future::ready(json!({
|
||||
"tailwindCSS": {
|
||||
"emmetCompletions": true,
|
||||
|
|
|
@ -205,7 +205,6 @@ pub struct EsLintLspAdapter {
|
|||
impl EsLintLspAdapter {
|
||||
const SERVER_PATH: &'static str = "vscode-eslint/server/out/eslintServer.js";
|
||||
|
||||
#[allow(unused)]
|
||||
pub fn new(node: Arc<dyn NodeRuntime>) -> Self {
|
||||
EsLintLspAdapter { node }
|
||||
}
|
||||
|
@ -213,13 +212,23 @@ impl EsLintLspAdapter {
|
|||
|
||||
#[async_trait]
|
||||
impl LspAdapter for EsLintLspAdapter {
|
||||
fn workspace_configuration(&self, _: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
workspace_root: &Path,
|
||||
_: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
future::ready(json!({
|
||||
"": {
|
||||
"validate": "on",
|
||||
"rulesCustomizations": [],
|
||||
"run": "onType",
|
||||
"nodePath": null,
|
||||
"workingDirectory": {"mode": "auto"},
|
||||
"workspaceFolder": {
|
||||
"uri": workspace_root,
|
||||
"name": workspace_root.file_name()
|
||||
.unwrap_or_else(|| workspace_root.as_os_str()),
|
||||
},
|
||||
}
|
||||
}))
|
||||
.boxed()
|
||||
|
|
|
@ -93,7 +93,11 @@ impl LspAdapter for YamlLspAdapter {
|
|||
) -> Option<LanguageServerBinary> {
|
||||
get_cached_server_binary(container_dir, &*self.node).await
|
||||
}
|
||||
fn workspace_configuration(&self, cx: &mut AppContext) -> BoxFuture<'static, Value> {
|
||||
fn workspace_configuration(
|
||||
&self,
|
||||
_workspace_root: &Path,
|
||||
cx: &mut AppContext,
|
||||
) -> BoxFuture<'static, Value> {
|
||||
let tab_size = all_language_settings(None, cx)
|
||||
.language(Some("YAML"))
|
||||
.tab_size;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue