From f2291d6a760f8a2d15074b5874facb03f5f838bc Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 11 Aug 2018 14:44:12 +0300 Subject: doc symbols --- crates/server/src/caps.rs | 2 +- crates/server/src/handlers.rs | 48 +++++++++++++++++++++++++++++++++++++++++-- crates/server/src/main.rs | 10 ++++++--- crates/server/src/req.rs | 4 ++-- crates/server/src/util.rs | 5 +++-- 5 files changed, 59 insertions(+), 10 deletions(-) (limited to 'crates/server/src') diff --git a/crates/server/src/caps.rs b/crates/server/src/caps.rs index 3d89c64a9..dca07ebc9 100644 --- a/crates/server/src/caps.rs +++ b/crates/server/src/caps.rs @@ -23,7 +23,7 @@ pub const SERVER_CAPABILITIES: ServerCapabilities = ServerCapabilities { implementation_provider: None, references_provider: None, document_highlight_provider: None, - document_symbol_provider: None, + document_symbol_provider: Some(true), workspace_symbol_provider: None, code_action_provider: None, code_lens_provider: None, diff --git a/crates/server/src/handlers.rs b/crates/server/src/handlers.rs index 8b7e00c92..51e940ef7 100644 --- a/crates/server/src/handlers.rs +++ b/crates/server/src/handlers.rs @@ -1,5 +1,5 @@ -use url::Url; -use languageserver_types::{Range, Position, Diagnostic, DiagnosticSeverity}; +use languageserver_types::{Range, Position, Diagnostic, DiagnosticSeverity, Url, DocumentSymbol, SymbolKind}; +use libsyntax2::SyntaxKind; use libanalysis::World; use libeditor::{self, LineIndex, LineCol, TextRange, TextUnit}; @@ -34,6 +34,50 @@ pub fn handle_extend_selection( Ok(req::ExtendSelectionResult { selections }) } +pub fn handle_document_symbol( + world: World, + params: req::DocumentSymbolParams, +) -> Result> { + let path = params.text_document.file_path()?; + let file = world.file_syntax(&path)?; + let line_index = world.file_line_index(&path)?; + + let mut res: Vec = Vec::new(); + + for symbol in libeditor::file_symbols(&file) { + let doc_symbol = DocumentSymbol { + name: symbol.name.clone(), + detail: Some(symbol.name), + kind: to_symbol_kind(symbol.kind), + deprecated: None, + range: to_vs_range(&line_index, symbol.node_range), + selection_range: to_vs_range(&line_index, symbol.name_range), + children: None, + }; + if let Some(idx) = symbol.parent { + let children = &mut res[idx].children; + if children.is_none() { + *children = Some(Vec::new()); + } + children.as_mut().unwrap().push(doc_symbol); + } else { + res.push(doc_symbol); + } + } + Ok(Some(req::DocumentSymbolResponse::Nested(res))) +} + +fn to_symbol_kind(kind: SyntaxKind) -> SymbolKind { + match kind { + SyntaxKind::FUNCTION => SymbolKind::Function, + SyntaxKind::STRUCT => SymbolKind::Struct, + SyntaxKind::ENUM => SymbolKind::Enum, + SyntaxKind::TRAIT => SymbolKind::Interface, + SyntaxKind::MODULE => SymbolKind::Module, + _ => SymbolKind::Variable, + } +} + pub fn publish_diagnostics(world: World, uri: Url) -> Result { let path = uri.file_path()?; let file = world.file_syntax(&path)?; diff --git a/crates/server/src/main.rs b/crates/server/src/main.rs index aeb4f807b..916638d49 100644 --- a/crates/server/src/main.rs +++ b/crates/server/src/main.rs @@ -11,11 +11,11 @@ extern crate crossbeam_channel; extern crate threadpool; #[macro_use] extern crate log; -extern crate url; extern crate url_serde; extern crate flexi_logger; extern crate libeditor; extern crate libanalysis; +extern crate libsyntax2; mod io; mod caps; @@ -27,12 +27,13 @@ mod util; use threadpool::ThreadPool; use crossbeam_channel::{bounded, Sender, Receiver}; use flexi_logger::Logger; -use url::Url; +use languageserver_types::Url; use libanalysis::{WorldState, World}; use ::{ io::{Io, RawMsg, RawRequest}, - handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics, publish_decorations}, + handlers::{handle_syntax_tree, handle_extend_selection, publish_diagnostics, publish_decorations, + handle_document_symbol}, util::{FilePath, FnBox} }; @@ -178,6 +179,9 @@ fn main_loop( handle_request_on_threadpool::( &mut req, pool, world, &sender, handle_extend_selection )?; + handle_request_on_threadpool::( + &mut req, pool, world, &sender, handle_document_symbol + )?; let mut shutdown = false; dispatch::handle_request::(&mut req, |(), resp| { resp.result(io, ())?; diff --git a/crates/server/src/req.rs b/crates/server/src/req.rs index 480fbabcd..6a0926084 100644 --- a/crates/server/src/req.rs +++ b/crates/server/src/req.rs @@ -1,11 +1,11 @@ use serde::{ser::Serialize, de::DeserializeOwned}; -use url::Url; -use languageserver_types::{TextDocumentIdentifier, Range}; +use languageserver_types::{TextDocumentIdentifier, Range, Url}; use url_serde; pub use languageserver_types::{ request::*, notification::*, InitializeResult, PublishDiagnosticsParams, + DocumentSymbolParams, DocumentSymbolResponse }; diff --git a/crates/server/src/util.rs b/crates/server/src/util.rs index 3691852f0..e4c226f93 100644 --- a/crates/server/src/util.rs +++ b/crates/server/src/util.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; -use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, TextDocumentIdentifier}; +use languageserver_types::{TextDocumentItem, VersionedTextDocumentIdentifier, + TextDocumentIdentifier, Url}; use ::{Result}; pub trait FnBox: Send { @@ -34,7 +35,7 @@ impl FilePath for TextDocumentIdentifier { } } -impl FilePath for ::url::Url { +impl FilePath for Url { fn file_path(&self) -> Result { self.to_file_path() .map_err(|()| format_err!("invalid uri: {}", self)) -- cgit v1.2.3