Skip to content

Instantly share code, notes, and snippets.

@anirudhb
Created May 11, 2020 00:45
Show Gist options
  • Save anirudhb/28647e85edf8828a19b07cd84460b23c to your computer and use it in GitHub Desktop.
Save anirudhb/28647e85edf8828a19b07cd84460b23c to your computer and use it in GitHub Desktop.
Patch to improve Dart LSP support for LanguageClient-Neovim
diff --git a/src/language_server_protocol.rs b/src/language_server_protocol.rs
index 1b3d7cb..d38aaf3 100644
--- a/src/language_server_protocol.rs
+++ b/src/language_server_protocol.rs
@@ -1197,6 +1197,14 @@ impl LanguageClient {
related_information: Some(true),
..PublishDiagnosticsCapability::default()
}),
+ code_action: Some(CodeActionCapability {
+ code_action_literal_support: Some(CodeActionLiteralSupport {
+ code_action_kind: CodeActionKindLiteralSupport {
+ value_set: vec!["quickfix".to_owned(), "assist".to_owned(), "refactor".to_owned()],
+ },
+ }),
+ ..CodeActionCapability::default()
+ }),
code_lens: Some(GenericCapability {
dynamic_registration: Some(true),
}),
@@ -3172,6 +3180,10 @@ impl LanguageClient {
virtual_texts.extend(self.virtual_texts_from_code_lenses(filename)?.into_iter());
}
+ if UseVirtualText::All == use_virtual_text {
+ virtual_texts.extend(self.virtual_texts_from_close_labels(filename)?.into_iter());
+ }
+
if self.get(|state| state.is_nvim)? {
let namespace_id = self.get_or_create_namespace(&LCNamespace::VirtualText)?;
self.vim()?.set_virtual_texts(
@@ -3233,7 +3245,7 @@ impl LanguageClient {
.push_str(format!(" | {}", text).as_str()),
None => virtual_texts.push(VirtualText {
line,
- text,
+ text: format!("// {}", text),
hl_group: "Comment".into(),
}),
}
@@ -3243,6 +3255,32 @@ impl LanguageClient {
Ok(virtual_texts)
}
+ fn virtual_texts_from_close_labels(&self, filename: &str) -> Fallible<Vec<VirtualText>> {
+ let mut virtual_texts = vec![];
+ let close_labels = self.get(|state| state.close_labels.get(filename).cloned().unwrap_or_default())?;
+
+ for cl in close_labels {
+ let line = cl.lnum;
+ let text = cl.label;
+
+ match virtual_texts
+ .iter()
+ .position(|v: &VirtualText| v.line == line)
+ {
+ Some(idx) => virtual_texts[idx]
+ .text
+ .push_str(format!(" | {}", text).as_str()),
+ None => virtual_texts.push(VirtualText {
+ line,
+ text,
+ hl_group: "Comment".into(),
+ }),
+ }
+ }
+
+ Ok(virtual_texts)
+ }
+
pub fn languageClient_handleCompleteDone(&self, params: &Value) -> Fallible<()> {
let filename = self.vim()?.get_filename(params)?;
let position = self.vim()?.get_position(params)?;
@@ -3657,6 +3695,37 @@ impl LanguageClient {
Ok(())
}
+ pub fn dart_handleCloseLabels(&self, params: &Value) -> Fallible<()> {
+ info!("Begin {}", NOTIFICATION__DartCloseLabels);
+ let params: CloseLabelParams = serde_json::from_value(params.clone())?;
+ let mut filename = params.uri.filepath()?.to_string_lossy().into_owned();
+ // Workaround bug: remove first '/' in case of '/C:/blabla'.
+ if filename.starts_with('/') && filename.chars().nth(2) == Some(':') {
+ filename.remove(0);
+ }
+ // Unify name to avoid mismatch due to case insensitivity.
+ let filename = filename.canonicalize();
+ let close_labels = params
+ .labels
+ .into_iter()
+ .map(|lab| {
+ CloseLabel {
+ label: lab.label,
+ lnum: lab.range.end.line,
+ }
+ })
+ .collect::<Vec<_>>();
+
+ self.update(|state| {
+ state
+ .close_labels
+ .insert(filename.clone(), close_labels.clone());
+ Ok(())
+ })?;
+ info!("End {}", NOTIFICATION__DartCloseLabels);
+ Ok(())
+ }
+
pub fn window_progress(&self, params: &Value) -> Fallible<()> {
info!("Begin {}", NOTIFICATION__WindowProgress);
let params: WindowProgressParams = params.clone().to_lsp()?;
diff --git a/src/logger.rs b/src/logger.rs
index e7c22e4..ad2d25e 100644
--- a/src/logger.rs
+++ b/src/logger.rs
@@ -74,7 +74,7 @@ fn create_config(path: &Option<PathBuf>, level: LevelFilter) -> Fallible<Config>
.write(true)
.truncate(true)
.open(&path)
- .with_context(|err| format!("Failed to open file ({}): {}", path, err))?;
+ .with_context(|err| format!("Failed to open file ({:?}): {}", path, err))?;
#[allow(clippy::write_literal)]
writeln!(
f,
diff --git a/src/rpchandler.rs b/src/rpchandler.rs
index 7811be7..5a337d3 100644
--- a/src/rpchandler.rs
+++ b/src/rpchandler.rs
@@ -183,6 +183,7 @@ impl LanguageClient {
NOTIFICATION__RustBeginBuild => self.rust_handleBeginBuild(&params)?,
NOTIFICATION__RustDiagnosticsBegin => self.rust_handleDiagnosticsBegin(&params)?,
NOTIFICATION__RustDiagnosticsEnd => self.rust_handleDiagnosticsEnd(&params)?,
+ NOTIFICATION__DartCloseLabels => self.dart_handleCloseLabels(&params)?,
NOTIFICATION__WindowProgress => self.window_progress(&params)?,
NOTIFICATION__ServerExited => self.languageClient_serverExited(&params)?,
diff --git a/src/types.rs b/src/types.rs
index f0a4b26..813e6d0 100644
--- a/src/types.rs
+++ b/src/types.rs
@@ -54,6 +54,7 @@ pub const NOTIFICATION__ClearDocumentHighlight: &str = "languageClient/clearDocu
pub const NOTIFICATION__RustBeginBuild: &str = "rustDocument/beginBuild";
pub const NOTIFICATION__RustDiagnosticsBegin: &str = "rustDocument/diagnosticsBegin";
pub const NOTIFICATION__RustDiagnosticsEnd: &str = "rustDocument/diagnosticsEnd";
+pub const NOTIFICATION__DartCloseLabels: &str = "dart/textDocument/publishClosingLabels";
// This is an RLS extension but the name is general enough to assume it might be implemented by
// other language servers or planned for inclusion in the base protocol.
pub const NOTIFICATION__WindowProgress: &str = "window/progress";
@@ -110,6 +111,24 @@ pub enum UseVirtualText {
No,
}
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct CloseLabel {
+ pub label: String,
+ pub lnum: u64,
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct CloseLabelParams {
+ pub uri: Url,
+ pub labels: Vec<CloseLabelParamsLabel>,
+}
+
+#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
+pub struct CloseLabelParamsLabel {
+ pub label: String,
+ pub range: Range,
+}
+
#[derive(Serialize)]
pub struct State {
// Program state.
@@ -135,6 +154,8 @@ pub struct State {
pub diagnostics: HashMap<String, Vec<Diagnostic>>,
// filename => codeLens.
pub code_lens: HashMap<String, Vec<CodeLens>>,
+ // filename => closeLabels.
+ pub close_labels: HashMap<String, Vec<CloseLabel>>,
#[serde(skip_serializing)]
pub line_diagnostics: HashMap<(String, u64), String>,
pub sign_next_id: u64,
@@ -221,6 +242,7 @@ impl State {
semantic_scope_to_hl_group_table: HashMap::new(),
semantic_highlights: HashMap::new(),
code_lens: HashMap::new(),
+ close_labels: HashMap::new(),
diagnostics: HashMap::new(),
line_diagnostics: HashMap::new(),
sign_next_id: 75_000,
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment