Skip to content
Permalink
Browse files

implement lsp-workspace-symbol; close #104

  • Loading branch information...
ul committed Oct 11, 2018
1 parent 7a31de2 commit dd339ef9a4c8e52c96348081af53dba8e0ec870b
Showing with 119 additions and 31 deletions.
  1. +1 −0 README.asciidoc
  2. +19 −1 rc/lsp.kak
  3. +15 −1 src/controller.rs
  4. +7 −0 src/general.rs
  5. +2 −28 src/language_features/document_symbol.rs
  6. +32 −0 src/util.rs
  7. +43 −1 src/workspace.rs
@@ -99,6 +99,7 @@ It adds:
* `lsp-references` command to find references for a symbol under the main cursor, mapped to `gr` by default
* `lsp-highlight-references` command to highlight references in current buffer for a symbol under the main cursor with `Reference` face (which is equal to `MatchingChar` face by default)
* `lsp-document-symbol` command to list current buffer's symbols
* `lsp-workspace-symbol` command to list project-wide symbols matching the query
* `lsp-diagnostics` command to list project-wide diagnostics (current buffer determines project and language to collect diagnostics)
* inline diagnostics highlighting using `DiagnosticError` and `DiagnosticWarning` faces; could be disabled with `lsp-inline-diagnostics-disable` command
* `lsp-formatting` command to format current buffer
@@ -193,6 +193,19 @@ method = "textDocument/documentSymbol"
' "${kak_session}" "${kak_client}" "${kak_buffile}" "${kak_timestamp}" | ${kak_opt_lsp_cmd}) > /dev/null 2>&1 < /dev/null & }
}

def lsp-workspace-symbol -params 1 -docstring "Open buffer with a list of project-wide symbols matching the query" %{
lsp-did-change
nop %sh{ (printf '
session = "%s"
client = "%s"
buffile = "%s"
version = %d
method = "workspace/symbol"
[params]
query = "%s"
' "${kak_session}" "${kak_client}" "${kak_buffile}" "${kak_timestamp}" "${1}" | ${kak_opt_lsp_cmd}) > /dev/null 2>&1 < /dev/null & }
}

def lsp-capabilities -docstring "List available commands for current filetype" %{
lsp-did-change
nop %sh{ (printf '
@@ -345,6 +358,10 @@ def -hidden lsp-show-document-symbol -params 2 -docstring "Render document symbo
}
}

def -hidden lsp-show-workspace-symbol -params 2 -docstring "Render workspace symbols" %{
lsp-show-document-symbol %arg{1} %arg{2}
}

def -hidden lsp-show-signature-help -params 2 -docstring "Render signature help" %{
echo %arg{2}
}
@@ -462,7 +479,7 @@ def lsp -params 1.. %sh{
else echo "-shell-script-candidates";
fi
} %{
for cmd in start hover definition references signature-help diagnostics document-symbol\
for cmd in start hover definition references signature-help diagnostics document-symbol workspace-symbol\
capabilities stop formatting highlight-references inline-diagnostics-enable inline-diagnostics-disable\
diagnostic-lines-enable diagnostics-lines-disable auto-hover-enable auto-hover-disable\
auto-hover-insert-mode-enable auto-hover-insert-mode-disable auto-signature-help-enable\
@@ -481,6 +498,7 @@ map global lsp h '<esc>:lsp-hover<ret>' -docstring 'hover'
map global lsp r '<esc>:lsp-references<ret>' -docstring 'references'
map global lsp s '<esc>:lsp-signature-help<ret>' -docstring 'signature help'
map global lsp S '<esc>:lsp-document-symbol<ret>' -docstring 'document symbols'
map global lsp p '<esc>:lsp-workspace-symbol ' -docstring 'workspace symbols'


lsp-stop-on-exit-enable
@@ -353,6 +353,9 @@ fn dispatch_editor_request(request: EditorRequest, mut ctx: &mut Context) {
request::Formatting::METHOD => {
formatting::text_document_formatting(params, meta, &mut ctx);
}
request::WorkspaceSymbol::METHOD => {
workspace::workspace_symbol(params, meta, &mut ctx);
}
"textDocument/diagnostics" => {
diagnostics::editor_diagnostics(params, meta, &mut ctx);
}
@@ -472,7 +475,10 @@ fn dispatch_server_response(
.expect("Failed to parse initialized response")
.capabilities,
);
ctx.notify(notification::Initialized::METHOD.into(), InitializedParams {});
ctx.notify(
notification::Initialized::METHOD.into(),
InitializedParams {},
);
let mut requests = Vec::with_capacity(ctx.pending_requests.len());
for msg in ctx.pending_requests.drain(..) {
requests.push(msg);
@@ -482,6 +488,14 @@ fn dispatch_server_response(
dispatch_editor_request(msg, &mut ctx);
}
}
request::WorkspaceSymbol::METHOD => {
workspace::editor_workspace_symbol(
meta,
serde_json::from_value(response)
.expect("Failed to parse workspace symbol response"),
&mut ctx,
);
}
"textDocument/referencesHighlight" => {
references::editor_references_highlight(
meta,
@@ -76,6 +76,13 @@ pub fn capabilities(_params: EditorParams, meta: &EditorMeta, ctx: &mut Context)
features.push("lsp-references");
}

if server_capabilities
.workspace_symbol_provider
.unwrap_or(false)
{
features.push("lsp-workspace-symbol");
}

if server_capabilities
.document_formatting_provider
.unwrap_or(false)
@@ -3,6 +3,7 @@ use languageserver_types::request::Request;
use languageserver_types::*;
use types::*;
use url::Url;
use util::*;

pub fn text_document_document_symbol(params: EditorParams, meta: &EditorMeta, ctx: &mut Context) {
let req_params = DocumentSymbolParams {
@@ -38,34 +39,7 @@ pub fn editor_document_symbol(
if result.is_empty() {
return;
}
let content = result
.into_iter()
.map(|symbol| {
let SymbolInformation {
location,
name,
kind,
..
} = symbol;
let filename = location.uri.to_file_path().unwrap();
let filename = filename
.strip_prefix(&ctx.root_path)
.ok()
.and_then(|p| Some(p.to_str().unwrap()))
.or_else(|| filename.to_str())
.unwrap();

let position = location.range.start;
let description = format!("{:?} {}", kind, name);
format!(
"{}:{}:{}:{}",
filename,
position.line + 1,
position.character + 1,
description
)
}).collect::<Vec<_>>()
.join("\n");
let content = format_symbol_information(result, ctx);
let command = format!(
"lsp-show-document-symbol %§{}§ %§{}§",
ctx.root_path, content,
@@ -1,3 +1,4 @@
use context::*;
use languageserver_types::*;
use std::os::unix::fs::DirBuilderExt;
use std::{env, fs, path};
@@ -34,3 +35,34 @@ pub fn lsp_range_to_kakoune(range: Range) -> String {
end_char,
)
}

pub fn format_symbol_information(items: Vec<SymbolInformation>, ctx: &Context) -> String {
items
.into_iter()
.map(|symbol| {
let SymbolInformation {
location,
name,
kind,
..
} = symbol;
let filename = location.uri.to_file_path().unwrap();
let filename = filename
.strip_prefix(&ctx.root_path)
.ok()
.and_then(|p| Some(p.to_str().unwrap()))
.or_else(|| filename.to_str())
.unwrap();

let position = location.range.start;
let description = format!("{:?} {}", kind, name);
format!(
"{}:{}:{}:{}",
filename,
position.line + 1,
position.character + 1,
description
)
}).collect::<Vec<_>>()
.join("\n")

This comment has been minimized.

@matklad

matklad Oct 11, 2018

Contributor

BTW, itertools has join for Iterators (which allows to bypass the intermediate Vec): https://docs.rs/itertools/0.7.8/itertools/trait.Itertools.html#method.join

This comment has been minimized.

@ul

ul Oct 12, 2018

Author Owner

Thanks, fixed in 5fb0bab

}
@@ -1,8 +1,11 @@
use context::*;
use languageserver_types::DidChangeConfigurationParams;
use languageserver_types::request::Request;
use languageserver_types::*;
use serde::Deserialize;
use serde_json;
use toml;
use types::*;
use util::*;

use languageserver_types::notification::{self, Notification};

@@ -82,3 +85,42 @@ pub fn did_change_configuration(params: EditorParams, _meta: &EditorMeta, ctx: &
};
ctx.notify(notification::DidChangeConfiguration::METHOD.into(), params);
}

pub fn workspace_symbol(params: EditorParams, meta: &EditorMeta, ctx: &mut Context) {
let req_params = WorkspaceSymbolParams::deserialize(params.clone());
if req_params.is_err() {
error!("Params should follow WorkspaceSymbolParams structure");
return;
}
let req_params = req_params.unwrap();
let id = ctx.next_request_id();
ctx.response_waitlist.insert(
id.clone(),
(
meta.clone(),
request::WorkspaceSymbol::METHOD.into(),
params,
),
);
ctx.call(id, request::WorkspaceSymbol::METHOD.into(), req_params);
}

pub fn editor_workspace_symbol(
meta: &EditorMeta,
result: Option<Vec<SymbolInformation>>,
ctx: &mut Context,
) {
if result.is_none() {
return;
}
let result = result.unwrap();
if result.is_empty() {
return;
}
let content = format_symbol_information(result, ctx);
let command = format!(
"lsp-show-workspace-symbol %§{}§ %§{}§",
ctx.root_path, content,
);
ctx.exec(meta.clone(), command);
}

0 comments on commit dd339ef

Please sign in to comment.
You can’t perform that action at this time.