Skip to content

Commit

Permalink
Enable clangd's dot-to-arrow feature (#21142)
Browse files Browse the repository at this point in the history
Closes #20815


![dot2arrow1127](https://github.com/user-attachments/assets/d825f9bf-52ae-47ee-b3a3-5f952b6e8979)

Release Notes:
- Enabled clangd's dot-to-arrow feature
  • Loading branch information
feeiyu authored Nov 28, 2024
1 parent a4584c9 commit c2c968f
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 17 deletions.
10 changes: 9 additions & 1 deletion crates/language/src/language.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,10 @@ use gpui::{AppContext, AsyncAppContext, Model, SharedString, Task};
pub use highlight_map::HighlightMap;
use http_client::HttpClient;
pub use language_registry::{LanguageName, LoadedLanguage};
use lsp::{CodeActionKind, LanguageServerBinary, LanguageServerBinaryOptions, LanguageServerName};
use lsp::{
CodeActionKind, InitializeParams, LanguageServerBinary, LanguageServerBinaryOptions,
LanguageServerName,
};
use parking_lot::Mutex;
use regex::Regex;
use schemars::{
Expand Down Expand Up @@ -484,6 +487,11 @@ pub trait LspAdapter: 'static + Send + Sync {
fn language_ids(&self) -> HashMap<String, String> {
Default::default()
}

/// Support custom initialize params.
fn prepare_initialize_params(&self, original: InitializeParams) -> Result<InitializeParams> {
Ok(original)
}
}

async fn try_fetch_server_binary<L: LspAdapter + 'static + Send + Sync + ?Sized>(
Expand Down
25 changes: 23 additions & 2 deletions crates/languages/src/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ use futures::StreamExt;
use gpui::AsyncAppContext;
use http_client::github::{latest_github_release, GitHubLspBinaryVersion};
pub use language::*;
use lsp::{LanguageServerBinary, LanguageServerName};
use lsp::{InitializeParams, LanguageServerBinary, LanguageServerName};
use serde_json::json;
use smol::fs::{self, File};
use std::{any::Any, env::consts, path::PathBuf, sync::Arc};
use util::{fs::remove_matching, maybe, ResultExt};
use util::{fs::remove_matching, maybe, merge_json_value_into, ResultExt};

pub struct CLspAdapter;

Expand Down Expand Up @@ -257,6 +258,26 @@ impl super::LspAdapter for CLspAdapter {
filter_range,
})
}

fn prepare_initialize_params(
&self,
mut original: InitializeParams,
) -> Result<InitializeParams> {
// enable clangd's dot-to-arrow feature.
let experimental = json!({
"textDocument": {
"completion" : {
"editsNearCursor": true
}
}
});
if let Some(ref mut original_experimental) = original.capabilities.experimental {
merge_json_value_into(experimental, original_experimental);
} else {
original.capabilities.experimental = Some(experimental);
}
Ok(original)
}
}

async fn get_cached_server_binary(container_dir: PathBuf) -> Option<LanguageServerBinary> {
Expand Down
30 changes: 19 additions & 11 deletions crates/lsp/src/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -599,22 +599,14 @@ impl LanguageServer {
Ok(())
}

/// Initializes a language server by sending the `Initialize` request.
/// Note that `options` is used directly to construct [`InitializeParams`], which is why it is owned.
///
/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize)
pub fn initialize(
mut self,
options: Option<Value>,
cx: &AppContext,
) -> Task<Result<Arc<Self>>> {
pub fn default_initialize_params(&self, cx: &AppContext) -> InitializeParams {
let root_uri = Url::from_file_path(&self.working_dir).unwrap();
#[allow(deprecated)]
let params = InitializeParams {
InitializeParams {
process_id: None,
root_path: None,
root_uri: Some(root_uri.clone()),
initialization_options: options,
initialization_options: None,
capabilities: ClientCapabilities {
workspace: Some(WorkspaceClientCapabilities {
configuration: Some(true),
Expand Down Expand Up @@ -779,6 +771,22 @@ impl LanguageServer {
}),
locale: None,
..Default::default()
}
}

/// Initializes a language server by sending the `Initialize` request.
/// Note that `options` is used directly to construct [`InitializeParams`], which is why it is owned.
///
/// [LSP Specification](https://microsoft.github.io/language-server-protocol/specifications/lsp/3.17/specification/#initialize)
pub fn initialize(
mut self,
initialize_params: Option<InitializeParams>,
cx: &AppContext,
) -> Task<Result<Arc<Self>>> {
let params = if let Some(params) = initialize_params {
params
} else {
self.default_initialize_params(cx)
};

cx.spawn(|_| async move {
Expand Down
14 changes: 11 additions & 3 deletions crates/project/src/lsp_store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5673,8 +5673,6 @@ impl LspStore {
.initialization_options(&(delegate))
.await?;

Self::setup_lsp_messages(this.clone(), &language_server, delegate, adapter);

match (&mut initialization_options, override_options) {
(Some(initialization_options), Some(override_options)) => {
merge_json_value_into(override_options, initialization_options);
Expand All @@ -5683,8 +5681,18 @@ impl LspStore {
_ => {}
}

let initialization_params = cx.update(|cx| {
let mut params = language_server.default_initialize_params(cx);
params.initialization_options = initialization_options;
adapter.adapter.prepare_initialize_params(params)
})??;

Self::setup_lsp_messages(this.clone(), &language_server, delegate, adapter);

let language_server = cx
.update(|cx| language_server.initialize(initialization_options, cx))?
.update(|cx| {
language_server.initialize(Some(initialization_params), cx)
})?
.await
.inspect_err(|_| {
if let Some(this) = this.upgrade() {
Expand Down

0 comments on commit c2c968f

Please sign in to comment.