effective caps
This commit is contained in:
parent
0617098175
commit
3410652c71
2 changed files with 77 additions and 59 deletions
|
@ -308,6 +308,15 @@ pub struct DynamicCapabilities {
|
|||
pub text_document_sync_did_save: Option<HashMap<String, SaveOptions>>,
|
||||
}
|
||||
|
||||
/// Effective text document synchronization behavior, merging static and dynamic capabilities.
|
||||
#[derive(Debug, Default, Clone)]
|
||||
pub struct EffectiveTextDocumentSync {
|
||||
/// Effective change sync kind (FULL or INCREMENTAL), if any.
|
||||
pub change: Option<TextDocumentSyncKind>,
|
||||
/// Whether to include text on didSave, or None if didSave is not supported.
|
||||
pub save_include_text: Option<bool>,
|
||||
}
|
||||
|
||||
impl LanguageServer {
|
||||
/// Starts a language server process.
|
||||
pub fn new(
|
||||
|
@ -1149,6 +1158,68 @@ impl LanguageServer {
|
|||
update(self.dynamic_capabilities.write().deref_mut());
|
||||
}
|
||||
|
||||
pub fn effective_text_document_sync(&self) -> EffectiveTextDocumentSync {
|
||||
let static_caps = self.capabilities();
|
||||
let dyn_caps = self.dynamic_capabilities();
|
||||
|
||||
let change = dyn_caps
|
||||
.text_document_sync_did_change
|
||||
.as_ref()
|
||||
.and_then(|m| {
|
||||
if m.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut best: Option<TextDocumentSyncKind> = None;
|
||||
for kind in m.values() {
|
||||
best = Some(match (best, kind) {
|
||||
(None, k) => *k,
|
||||
(
|
||||
Some(TextDocumentSyncKind::FULL),
|
||||
&TextDocumentSyncKind::INCREMENTAL,
|
||||
) => TextDocumentSyncKind::INCREMENTAL,
|
||||
(Some(curr), _) => curr,
|
||||
});
|
||||
}
|
||||
best
|
||||
}
|
||||
})
|
||||
.or_else(|| {
|
||||
static_caps
|
||||
.text_document_sync
|
||||
.as_ref()
|
||||
.and_then(|sync| match sync {
|
||||
TextDocumentSyncCapability::Kind(kind) => Some(*kind),
|
||||
TextDocumentSyncCapability::Options(options) => options.change,
|
||||
})
|
||||
});
|
||||
|
||||
let save_include_text = dyn_caps
|
||||
.text_document_sync_did_save
|
||||
.as_ref()
|
||||
.and_then(|m| {
|
||||
if m.is_empty() {
|
||||
None
|
||||
} else {
|
||||
Some(m.values().any(|opts| opts.include_text.unwrap_or(false)))
|
||||
}
|
||||
})
|
||||
.or_else(|| match static_caps.text_document_sync.as_ref()? {
|
||||
TextDocumentSyncCapability::Options(opts) => match opts.save.as_ref()? {
|
||||
TextDocumentSyncSaveOptions::Supported(true) => Some(false),
|
||||
TextDocumentSyncSaveOptions::Supported(false) => None,
|
||||
TextDocumentSyncSaveOptions::SaveOptions(save_opts) => {
|
||||
Some(save_opts.include_text.unwrap_or(false))
|
||||
}
|
||||
},
|
||||
TextDocumentSyncCapability::Kind(_) => None,
|
||||
});
|
||||
|
||||
EffectiveTextDocumentSync {
|
||||
change,
|
||||
save_include_text,
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the reported capabilities of the running language server and
|
||||
/// what we know on the client/adapter-side of its capabilities.
|
||||
pub fn adapter_server_capabilities(&self) -> AdapterServerCapabilities {
|
||||
|
|
|
@ -75,7 +75,7 @@ use lsp::{
|
|||
LSP_REQUEST_TIMEOUT, LanguageServer, LanguageServerBinary, LanguageServerBinaryOptions,
|
||||
LanguageServerId, LanguageServerName, LanguageServerSelector, LspRequestFuture,
|
||||
MessageActionItem, MessageType, OneOf, RenameFilesParams, SymbolKind,
|
||||
TextDocumentSyncSaveOptions, TextEdit, WillRenameFiles, WorkDoneProgressCancelParams,
|
||||
TextEdit, WillRenameFiles, WorkDoneProgressCancelParams,
|
||||
WorkspaceFolder, notification::DidRenameFiles,
|
||||
};
|
||||
use node_runtime::read_package_installed_version;
|
||||
|
@ -7208,40 +7208,9 @@ impl LspStore {
|
|||
.collect()
|
||||
};
|
||||
|
||||
let document_sync_kind = {
|
||||
let dyn_caps = language_server.dynamic_capabilities();
|
||||
let dynamic = dyn_caps
|
||||
.text_document_sync_did_change
|
||||
.as_ref()
|
||||
.and_then(|m| {
|
||||
if m.is_empty() {
|
||||
None
|
||||
} else {
|
||||
let mut best: Option<lsp::TextDocumentSyncKind> = None;
|
||||
for kind in m.values() {
|
||||
best = Some(match (best, kind) {
|
||||
(None, k) => *k,
|
||||
(
|
||||
Some(lsp::TextDocumentSyncKind::FULL),
|
||||
lsp::TextDocumentSyncKind::INCREMENTAL,
|
||||
) => lsp::TextDocumentSyncKind::INCREMENTAL,
|
||||
(Some(curr), _) => curr,
|
||||
});
|
||||
}
|
||||
best
|
||||
}
|
||||
});
|
||||
dynamic.or_else(|| {
|
||||
language_server
|
||||
.capabilities()
|
||||
.text_document_sync
|
||||
.as_ref()
|
||||
.and_then(|sync| match sync {
|
||||
lsp::TextDocumentSyncCapability::Kind(kind) => Some(*kind),
|
||||
lsp::TextDocumentSyncCapability::Options(options) => options.change,
|
||||
})
|
||||
})
|
||||
};
|
||||
let document_sync_kind = language_server
|
||||
.effective_text_document_sync()
|
||||
.change;
|
||||
|
||||
let content_changes: Vec<_> = match document_sync_kind {
|
||||
Some(lsp::TextDocumentSyncKind::FULL) => {
|
||||
|
@ -7302,7 +7271,7 @@ impl LspStore {
|
|||
let local = self.as_local()?;
|
||||
|
||||
for server in local.language_servers_for_worktree(worktree_id) {
|
||||
if let Some(include_text) = include_text(server.as_ref()) {
|
||||
if let Some(include_text) = server.effective_text_document_sync().save_include_text {
|
||||
let text = if include_text {
|
||||
Some(buffer.read(cx).text())
|
||||
} else {
|
||||
|
@ -13284,29 +13253,7 @@ async fn populate_labels_for_symbols(
|
|||
}
|
||||
}
|
||||
|
||||
fn include_text(server: &lsp::LanguageServer) -> Option<bool> {
|
||||
let dyn_caps = server.dynamic_capabilities();
|
||||
if let Some(map) = dyn_caps.text_document_sync_did_save.as_ref() {
|
||||
if !map.is_empty() {
|
||||
let any_true = map.values().any(|opts| opts.include_text.unwrap_or(false));
|
||||
return Some(any_true);
|
||||
}
|
||||
}
|
||||
match server.capabilities().text_document_sync.as_ref()? {
|
||||
lsp::TextDocumentSyncCapability::Options(opts) => match opts.save.as_ref()? {
|
||||
// Server wants didSave but didn't specify includeText.
|
||||
lsp::TextDocumentSyncSaveOptions::Supported(true) => Some(false),
|
||||
// Server doesn't want didSave at all.
|
||||
lsp::TextDocumentSyncSaveOptions::Supported(false) => None,
|
||||
// Server provided SaveOptions.
|
||||
lsp::TextDocumentSyncSaveOptions::SaveOptions(save_options) => {
|
||||
Some(save_options.include_text.unwrap_or(false))
|
||||
}
|
||||
},
|
||||
// We do not have any save info. Kind affects didChange only.
|
||||
lsp::TextDocumentSyncCapability::Kind(_) => None,
|
||||
}
|
||||
}
|
||||
// include_text logic moved into lsp::LanguageServer::effective_text_document_sync()
|
||||
|
||||
/// Completion items are displayed in a `UniformList`.
|
||||
/// Usually, those items are single-line strings, but in LSP responses,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue