From ae7e850a1390b93dd11e3ec394c5b2f505247aa1 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 26 Oct 2016 17:44:52 +0100 Subject: [PATCH 01/16] Changes to use languageserver-types crate --- Cargo.lock | 52 +++++++ Cargo.toml | 1 + src/actions_ls.rs | 100 ++++++------- src/ide.rs | 1 + src/ls_server.rs | 57 ++++---- src/lsp_data.rs | 349 ++++++++++++++-------------------------------- src/main.rs | 3 + 7 files changed, 245 insertions(+), 318 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 81477149112..3aa8eedd644 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,6 +5,7 @@ dependencies = [ "derive-new 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", + "languageserver-types 0.3.0 (git+https://github.com/gluon-lang/languageserver-types)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "racer 1.2.10 (git+https://github.com/phildawes/racer)", "rls-analysis 0.1.0 (git+https://github.com/nrc/rls-analysis)", @@ -81,6 +82,14 @@ name = "dtoa" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "enum_primitive" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "env_logger" version = "0.3.5" @@ -162,6 +171,17 @@ name = "language-tags" version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "languageserver-types" +version = "0.3.0" +source = "git+https://github.com/gluon-lang/languageserver-types#05c7e9cfcaf4ee088826796bbb044f19b104cc1a" +dependencies = [ + "enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_derive 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", + "serde_json 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.17" @@ -198,6 +218,33 @@ name = "multimap" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "num" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-integer" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "num-iter" +version = "0.1.32" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)", + "num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "num-traits" version = "0.1.36" @@ -622,6 +669,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum derive-new 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "9b37e74c2a0347b1a7c2d2dc55c84c017241b6cb1df9acbe07c8efc12a3ebf0c" "checksum diff 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)" = "e48977eec6d3b7707462c2dc2e1363ad91b5dd822cf942537ccdc2085dc87587" "checksum dtoa 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "0dd841b58510c9618291ffa448da2e4e0f699d984d436122372f446dae62263d" +"checksum enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f79eff5be92a4d7d5bddf7daa7d650717ea71628634efe6ca7bcda85b2183c23" "checksum env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "15abd780e45b3ea4f76b4e9a26ff4843258dd8a3eed2775a0e7368c2e7936c2f" "checksum getopts 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)" = "d9047cfbd08a437050b363d35ef160452c5fe8ea5187ae0a624708c91581d685" "checksum hpack 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d2da7d3a34cf6406d9d700111b8eafafe9a251de41ae71d8052748259343b58" @@ -632,12 +680,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" +"checksum languageserver-types 0.3.0 (git+https://github.com/gluon-lang/languageserver-types)" = "" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd" "checksum memchr 0.1.11 (registry+https://github.com/rust-lang/crates.io-index)" = "d8b629fb514376c675b98c1421e80b151d3817ac42d7c667717d282761418d20" "checksum mime 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "b5c93a4bd787ddc6e7833c519b73a50883deb5863d76d9b71eb8216fb7f94e66" "checksum multimap 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "9223f4774d08e06185e44e555b9a7561243d387bac49c78a6205c42d6975fbf2" +"checksum num 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "bde7c03b09e7c6a301ee81f6ddf66d7a28ec305699e3d3b056d2fc56470e3120" +"checksum num-integer 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "fb24d9bfb3f222010df27995441ded1e954f8f69cd35021f6bef02ca9552fb92" +"checksum num-iter 0.1.32 (registry+https://github.com/rust-lang/crates.io-index)" = "287a1c9969a847055e1122ec0ea7a5c5d6f72aad97934e131c83d5c08ab4e45c" "checksum num-traits 0.1.36 (registry+https://github.com/rust-lang/crates.io-index)" = "a16a42856a256b39c6d3484f097f6713e14feacd9bfb02290917904fae46c81c" "checksum num_cpus 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "cee7e88156f3f9e19bdd598f8d6c9db7bf4078f99f8381f43a55b09648d1a6e3" "checksum quote 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4c5cf478fe1006dbcc72567121d23dbdae5f1632386068c5c86ff4f645628504" diff --git a/Cargo.toml b/Cargo.toml index 43da4e25dab..217adfbb612 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,6 +13,7 @@ serde = "0.8" serde_json = "0.8" serde_derive = "0.8" derive-new = "0.1" +languageserver-types = { version = "0.3.0", git = "https://github.com/gluon-lang/languageserver-types" } [dev-dependencies] env_logger = "0.3.0" diff --git a/src/actions_ls.rs b/src/actions_ls.rs index 302bc8734e7..cfd30438ce3 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -18,7 +18,6 @@ use serde_json; use build::*; use lsp_data::*; -use ide::VscodeKind; use ls_server::{ResponseData, Output, Logger}; use std::collections::HashMap; @@ -52,11 +51,15 @@ impl ActionHandler { } } - pub fn init(&self, root_path: PathBuf, out: &Output) { + pub fn init(&self, root_path: Option, out: &Output) { { let mut results = self.previous_build_results.lock().unwrap(); results.clear(); } + let root_path = match root_path { + Some(some) => some, + None => return + }; { let mut current_project = self.current_project.lock().unwrap(); *current_project = Some(root_path.clone()); @@ -86,16 +89,17 @@ impl ActionHandler { continue; } let mut diag = Diagnostic { - range: Range::from_span(&method.spans[0]), - severity: if method.level == "error" { + range: RangeUtil::from_span(&method.spans[0]), + severity: Some(if method.level == "error" { DiagnosticSeverity::Error } else { DiagnosticSeverity::Warning - }, - code: match method.code { + }), + code: Some(NumberOrString::String(match method.code { Some(c) => c.code.clone(), None => String::new(), - }, + })), + source: Some("rustc".into()), message: method.message.clone(), }; @@ -162,7 +166,7 @@ impl ActionHandler { let fname: PathBuf = Url::parse(&change.textDocument.uri).unwrap().to_file_path().unwrap(); let changes: Vec = change.contentChanges.iter().map(move |i| { Change { - span: i.range.to_span(fname.clone()), + span: RangeUtil::to_span(i.range, fname.clone()), text: i.text.clone() } }).collect(); @@ -189,15 +193,16 @@ impl ActionHandler { let analysis = self.analysis.clone(); let rustw_handle = thread::spawn(move || { - let file_name = doc.textDocument.file_name(); + let file_name = uri_string_to_file_name(&doc.text_document.uri); let symbols = analysis.symbols(&file_name).unwrap_or(vec![]); t.unpark(); symbols.into_iter().map(|s| { SymbolInformation { name: s.name, - kind: VscodeKind::from(s.kind) as u32, - location: Location::from_span(&s.span), + kind: sk_from_def_kind(s.kind), + location: LocationUtil::from_span(&s.span), + container_name: None // TODO: more info could be added here } }).collect() }); @@ -212,7 +217,7 @@ impl ActionHandler { let vfs: &Vfs = &self.vfs; let result: Vec = panic::catch_unwind(move || { let pos = adjust_vscode_pos_for_racer(params.position); - let file_path = ¶ms.textDocument.file_name(); + let file_path = &uri_string_to_file_name(¶ms.text_document.uri); let cache = core::FileCache::new(); let session = core::Session::from_path(&cache, file_path, file_path); @@ -222,13 +227,13 @@ impl ActionHandler { let src = session.load_file(file_path); - let pos = session.load_file(file_path).coords_to_point(pos.line, pos.character).unwrap(); + let pos = session.load_file(file_path).coords_to_point(to_usize(pos.line), to_usize(pos.character)).unwrap(); let results = complete_from_file(&src.code, file_path, pos, &session); - results.map(|comp| CompletionItem { - label: comp.matchstr.clone(), - detail: comp.contextstr.clone(), - }).collect() + results.map(|comp| new_completion_item( + comp.matchstr.clone(), + comp.contextstr.clone(), + )).collect() }).unwrap_or(vec![]); out.success(id, ResponseData::CompletionItems(result)); @@ -236,7 +241,7 @@ impl ActionHandler { pub fn rename(&self, id: usize, params: RenameParams, out: &Output) { let t = thread::current(); - let span = self.convert_pos_to_span(¶ms.textDocument, ¶ms.position); + let span = self.convert_pos_to_span(¶ms.text_document, ¶ms.position); let analysis = self.analysis.clone(); let rustw_handle = thread::spawn(move || { @@ -253,10 +258,10 @@ impl ActionHandler { let mut edits: HashMap> = HashMap::new(); for item in result.iter() { - let loc = Location::from_span(&item); + let loc = LocationUtil::from_span(&item); edits.entry(loc.uri).or_insert(vec![]).push(TextEdit { range: loc.range, - newText: params.newName.clone(), + new_text: params.new_name.clone(), }); } @@ -265,7 +270,7 @@ impl ActionHandler { pub fn find_all_refs(&self, id: usize, params: ReferenceParams, out: &Output) { let t = thread::current(); - let span = self.convert_pos_to_span(¶ms.textDocument, ¶ms.position); + let span = self.convert_pos_to_span(¶ms.text_document, ¶ms.position); let analysis = self.analysis.clone(); let rustw_handle = thread::spawn(move || { @@ -278,7 +283,7 @@ impl ActionHandler { thread::park_timeout(Duration::from_millis(::COMPILER_TIMEOUT)); let result = rustw_handle.join().ok().and_then(|t| t.ok()).unwrap_or(vec![]); - let refs: Vec<_> = result.iter().map(|item| Location::from_span(&item)).collect(); + let refs: Vec<_> = result.iter().map(|item| LocationUtil::from_span(&item)).collect(); out.success(id, ResponseData::Locations(refs)); } @@ -286,7 +291,7 @@ impl ActionHandler { pub fn goto_def(&self, id: usize, params: TextDocumentPositionParams, out: &Output) { // Save-analysis thread. let t = thread::current(); - let span = self.convert_pos_to_span(¶ms.textDocument, ¶ms.position); + let span = self.convert_pos_to_span(¶ms.text_document, ¶ms.position); let analysis = self.analysis.clone(); let vfs = self.vfs.clone(); @@ -301,7 +306,7 @@ impl ActionHandler { // Racer thread. let racer_handle = thread::spawn(move || { let pos = adjust_vscode_pos_for_racer(params.position); - let file_path = ¶ms.textDocument.file_name(); + let file_path = &uri_string_to_file_name(¶ms.text_document.uri); let cache = core::FileCache::new(); let session = core::Session::from_path(&cache, file_path, file_path); @@ -313,7 +318,7 @@ impl ActionHandler { find_definition(&src.code, file_path, - src.coords_to_point(pos.line, pos.character).unwrap(), + src.coords_to_point(to_usize(pos.line), to_usize(pos.character)).unwrap(), &session) .and_then(|mtch| { let source_path = &mtch.filepath; @@ -321,7 +326,7 @@ impl ActionHandler { let (line, col) = session.load_file(source_path) .point_to_coords(mtch.point) .unwrap(); - Some(Location::from_position(source_path, + Some(LocationUtil::from_position(source_path, adjust_racer_line_for_vscode(line), col)) } else { @@ -335,7 +340,7 @@ impl ActionHandler { let compiler_result = compiler_handle.join(); match compiler_result { Ok(Ok(r)) => { - let result = vec![Location::from_span(&r)]; + let result = vec![LocationUtil::from_span(&r)]; self.logger.log(&format!("\nGOING TO: {:?}\n", result)); out.success(id, ResponseData::Locations(result)); } @@ -357,7 +362,7 @@ impl ActionHandler { pub fn hover(&self, id: usize, params: HoverParams, out: &Output) { let t = thread::current(); - let span = self.convert_pos_to_span(¶ms.textDocument, ¶ms.position); + let span = self.convert_pos_to_span(¶ms.text_document, ¶ms.position); self.logger.log(&format!("\nHovering span: {:?}\n", span)); @@ -370,16 +375,17 @@ impl ActionHandler { let mut contents = vec![]; if !docs.is_empty() { - contents.push(MarkedString { language: "markdown".into(), value: docs }); + contents.push(MarkedString::LanguageString { language: "markdown".into(), value: docs }); } if !doc_url.is_empty() { - contents.push(MarkedString { language: "url".into(), value: doc_url }); + contents.push(MarkedString::LanguageString { language: "url".into(), value: doc_url }); } if !ty.is_empty() { - contents.push(MarkedString { language: "rust".into(), value: ty }); + contents.push(MarkedString::LanguageString { language: "rust".into(), value: ty }); } - HoverSuccessContents { - contents: contents + Hover { + contents: contents, + range: None, // TODO: maybe add? } }); @@ -399,7 +405,7 @@ impl ActionHandler { pub fn reformat(&self, id: usize, doc: TextDocumentIdentifier, out: &Output) { self.logger.log(&format!("Reformat: {} {:?}\n", id, doc)); - let path = &doc.file_name(); + let path = &uri_string_to_file_name(&doc.uri); let input = match self.vfs.load_file(path) { Ok(s) => FmtInput::Text(s), Err(e) => { @@ -426,11 +432,11 @@ impl ActionHandler { character: 0, }, end: Position { - line: text.lines().count(), + line: from_usize(text.lines().count()), character: 0, }, }, - newText: text, + new_text: text, }]; out.success(id, ResponseData::TextEdit(result)) } @@ -441,18 +447,18 @@ impl ActionHandler { } } - fn convert_pos_to_span(&self, doc: &Document, pos: &Position) -> Span { - let fname = doc.file_name(); + fn convert_pos_to_span(&self, doc: &TextDocumentIdentifier, pos: &Position) -> Span { + let fname = uri_string_to_file_name(&doc.uri); self.logger.log(&format!("\nWorking on: {:?} {:?}", fname, pos)); - let line = self.vfs.load_line(&fname, pos.line); + let line = self.vfs.load_line(&fname, to_usize(pos.line)); self.logger.log(&format!("\nGOT LINE: {:?}", line)); let start_pos = { let mut tmp = Position { line: pos.line, character: 1 }; for (i, c) in line.clone().unwrap().chars().enumerate() { if !(c.is_alphanumeric() || c == '_') { - tmp.character = i + 1; + tmp.character = from_usize(i + 1); } - if i == pos.character { + if from_usize(i) == pos.character { break; } } @@ -461,21 +467,21 @@ impl ActionHandler { let end_pos = { let mut tmp = Position { line: pos.line, character: pos.character }; - for (i, c) in line.unwrap().chars().skip(pos.character).enumerate() { + for (i, c) in line.unwrap().chars().skip(to_usize(pos.character)).enumerate() { if !(c.is_alphanumeric() || c == '_') { break; } - tmp.character = i + pos.character + 1; + tmp.character = from_usize(i) + pos.character + 1; } tmp }; Span { file_name: fname.to_owned(), - line_start: start_pos.line, - column_start: start_pos.character, - line_end: end_pos.line, - column_end: end_pos.character, + line_start: to_usize(start_pos.line), + column_start: to_usize(start_pos.character), + line_end: to_usize(end_pos.line), + column_end: to_usize(end_pos.character), } } } diff --git a/src/ide.rs b/src/ide.rs index 4684531c1e0..93d72c75041 100644 --- a/src/ide.rs +++ b/src/ide.rs @@ -74,6 +74,7 @@ pub fn parse_string(input: &[u8]) -> Result { serde_json::from_str(&s) } +// TODO: deprecate/remove in favor of ls_types::SymbolKind ? #[allow(dead_code)] #[derive(Debug, Serialize)] pub enum VscodeKind { diff --git a/src/ls_server.rs b/src/ls_server.rs index c28a59b9a2b..282a669d3cd 100644 --- a/src/ls_server.rs +++ b/src/ls_server.rs @@ -23,6 +23,7 @@ use std::io::{self, Read, Write, ErrorKind}; use std::sync::{Arc, Mutex}; use std::sync::atomic::{AtomicBool, Ordering}; use std::thread; +use std::path::PathBuf; #[derive(Debug, new)] @@ -61,7 +62,7 @@ enum Method { #[derive(Debug)] enum Notification { - CancelRequest(usize), + CancelRequest(NumberOrString), Change(ChangeParams), } @@ -91,13 +92,13 @@ macro_rules! serializable_enum { } serializable_enum!(ResponseData, - Init(InitializeCapabilities), + Init(InitializeResult), SymbolInfo(Vec), CompletionItems(Vec), WorkspaceEdit(WorkspaceEdit), TextEdit([TextEdit; 1]), Locations(Vec), - HoverSuccess(HoverSuccessContents) + HoverSuccess(Hover) ); // FIXME(45) generate this function. @@ -251,34 +252,36 @@ impl LsService { } fn init(&self, id: usize, init: InitializeParams) { - let result = InitializeCapabilities { + let result = InitializeResult { capabilities: ServerCapabilities { - textDocumentSync: DocumentSyncKind::Incremental as usize, - hoverProvider: true, - completionProvider: CompletionOptions { - resolveProvider: true, - triggerCharacters: vec![".".to_string()], - }, + text_document_sync: Some(TextDocumentSyncKind::Incremental), + hover_provider: Some(true), + completion_provider: Some(CompletionOptions { + resolve_provider: Some(true), + trigger_characters: vec![".".to_string()], + }), // TODO - signatureHelpProvider: SignatureHelpOptions { - triggerCharacters: vec![], - }, - definitionProvider: true, - referencesProvider: true, + signature_help_provider: Some(SignatureHelpOptions { + trigger_characters: Some(vec![]), + }), + definition_provider: Some(true), + references_provider: Some(true), // TODO - documentHighlightProvider: false, - documentSymbolProvider: true, - workshopSymbolProvider: true, - codeActionProvider: false, + document_highlight_provider: Some(false), + document_symbol_provider: Some(true), + workspace_symbol_provider: Some(true), + code_action_provider: Some(false), // TODO maybe? - codeLensProvider: false, - documentFormattingProvider: true, - documentRangeFormattingProvider: true, - renameProvider: true, + code_lens_provider: None, + document_formatting_provider: Some(true), + document_range_formatting_provider: Some(true), + document_on_type_formatting_provider: None, // TODO: review this, maybe add? + rename_provider: Some(true), } }; self.output.success(id, ResponseData::Init(result)); - self.handler.init(init.rootPath, &*self.output); + let root_path = init.root_path.map(|str| PathBuf::from(str)); + self.handler.init(root_path, &*self.output); } pub fn handle_message(this: Arc) -> ServerStateChange { @@ -292,7 +295,7 @@ impl LsService { // FIXME(45) refactor to generate this match. match parse_message(&c) { Ok(ServerMessage::Notification(Notification::CancelRequest(id))) => { - this.logger.log(&format!("request to cancel {}\n", id)); + this.logger.log(&format!("request to cancel {:?}\n", id)); }, Ok(ServerMessage::Notification(Notification::Change(change))) => { this.logger.log(&format!("notification(change): {:?}\n", change)); @@ -339,13 +342,13 @@ impl LsService { Method::Reformat(params) => { // FIXME take account of options. this.logger.log(&format!("command(reformat): {:?}\n", params)); - this.handler.reformat(id, params.textDocument, &*this.output); + this.handler.reformat(id, params.text_document, &*this.output); } Method::ReformatRange(params) => { // FIXME reformats the whole file, not just a range. // FIXME take account of options. this.logger.log(&format!("command(reformat): {:?}\n", params)); - this.handler.reformat(id, params.textDocument, &*this.output); + this.handler.reformat(id, params.text_document, &*this.output); } } } diff --git a/src/lsp_data.rs b/src/lsp_data.rs index 2ad81bbe019..7b9f18e21f8 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -8,77 +8,79 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::collections::HashMap; use std::fmt::Debug; use std::path::{Path, PathBuf}; +use std::convert::TryFrom; + use analysis::Span; +use analysis::raw; use hyper::Url; -use serde::{Serialize, Serializer}; +use serde::{Serialize}; macro_rules! impl_file_name { ($ty_name: ty) => { impl $ty_name { pub fn file_name(&self) -> PathBuf { - let uri = Url::parse(&self.uri).unwrap(); - uri.to_file_path().unwrap() + uri_string_to_file_name(&self.uri) } } } } -/// Position in a text document expressed as zero-based line and character offset. -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Position { - pub line: usize, - pub character: usize, +pub fn uri_string_to_file_name(uri: &str) -> PathBuf { + let uri = Url::parse(&uri).unwrap(); + uri.to_file_path().unwrap() +} + +pub fn from_usize(pos: usize) -> u64 { + TryFrom::try_from(pos).unwrap() // XXX: Should we do error handling or assume it's ok? } -/// A range in a text document expressed as (zero-based) start and end positions. -#[derive(Clone, Debug, Deserialize, Serialize)] -pub struct Range { - pub start: Position, - /// End position is exclusive - pub end: Position, +pub fn to_usize(pos: u64) -> usize { + TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking } -impl Range { +pub use ls_types::Position; + +pub use ls_types::Range; + +pub struct RangeUtil; + +impl RangeUtil { pub fn from_span(span: &Span) -> Range { Range { start: Position { - line: span.line_start, - character: span.column_start, + line: from_usize(span.line_start), + character: from_usize(span.column_start), }, end: Position { - line: span.line_end, - character: span.column_end, + line: from_usize(span.line_end), + character: from_usize(span.column_end), }, } } - pub fn to_span(&self, fname: PathBuf) -> Span { + pub fn to_span(this: Range, fname: PathBuf) -> Span { Span { file_name: fname, - line_start: self.start.line, - column_start: self.start.character, - line_end: self.end.line, - column_end: self.end.character, + line_start: to_usize(this.start.line), + column_start: to_usize(this.start.character), + line_end: to_usize(this.end.line), + column_end: to_usize(this.end.character), } } } -/// Represents a location inside a resource, such as a line inside a text file. -#[derive(Debug, Deserialize, Serialize)] -pub struct Location { - pub uri: String, - pub range: Range, -} +pub use ls_types::Location; + +pub struct LocationUtil; -impl Location { +impl LocationUtil { pub fn from_span(span: &Span) -> Location { Location { uri: Url::from_file_path(&span.file_name).unwrap().into_string(), - range: Range::from_span(span), + range: RangeUtil::from_span(span), } } @@ -87,47 +89,23 @@ impl Location { uri: Url::from_file_path(&file_name).unwrap().into_string(), range: Range { start: Position { - line: line, - character: col, + line: from_usize(line), + character: from_usize(col), }, end: Position { - line: line, - character: col, + line: from_usize(line), + character: from_usize(col), }, }, } } } -/// The initialize request is sent as the first request from the client to the server. -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct InitializeParams { - pub processId: usize, - pub rootPath: PathBuf -} +pub use ls_types::InitializeParams; +pub use ls_types::NumberOrString; -#[derive(Debug, Deserialize)] -pub struct Document { - pub uri: String -} - -impl_file_name!(Document); - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct TextDocumentIdentifier { - pub uri: String -} - -impl_file_name!(TextDocumentIdentifier); - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct VersionedTextDocumentIdentifier { - pub version: u64, - pub uri: String -} +pub use ls_types::TextDocumentIdentifier; +pub use ls_types::VersionedTextDocumentIdentifier; /// An event describing a change to a text document. If range and rangeLength are omitted /// the new text is considered to be the full content of the document. @@ -138,21 +116,34 @@ pub struct TextDocumentContentChangeEvent { pub rangeLength: Option, pub text: String } - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct ReferenceContext { - pub includeDeclaration: bool, +//pub use ls_types::TextDocumentContentChangeEvent; + + +pub use ls_types::ReferenceContext; + +pub use ls_types::SymbolInformation; +pub use ls_types::SymbolKind; + +pub fn sk_from_def_kind(k: raw::DefKind) -> SymbolKind { + match k { + raw::DefKind::Enum => SymbolKind::Enum, + raw::DefKind::Tuple => SymbolKind::Array, + raw::DefKind::Struct => SymbolKind::Class, + raw::DefKind::Trait => SymbolKind::Interface, + raw::DefKind::Function => SymbolKind::Function, + raw::DefKind::Method => SymbolKind::Function, + raw::DefKind::Macro => SymbolKind::Function, + raw::DefKind::Mod => SymbolKind::Module, + raw::DefKind::Type => SymbolKind::Interface, + raw::DefKind::Local => SymbolKind::Variable, + raw::DefKind::Static => SymbolKind::Variable, + raw::DefKind::Const => SymbolKind::Variable, + raw::DefKind::Field => SymbolKind::Variable, + raw::DefKind::Import => SymbolKind::Module, + } } -/// Represents information about programming constructs like variables, classes, -/// interfaces etc. -#[derive(Debug, Serialize)] -pub struct SymbolInformation { - pub name: String, - pub kind: u32, // can be made to numeric enum - pub location: Location, -} + #[derive(Debug, Deserialize)] pub struct CompilerMessageCode { @@ -167,37 +158,9 @@ pub struct CompilerMessage { pub spans: Vec, } -/// Represents a diagnostic, such as a compiler error or warning. -/// Diagnostic objects are only valid in the scope of a resource. -#[derive(Debug, Clone, Serialize)] -pub struct Diagnostic { - pub range: Range, - pub severity: DiagnosticSeverity, - pub code: String, - pub message: String, -} - -#[derive(Debug, Clone, Copy)] -pub enum DiagnosticSeverity { - Error = 1, - Warning = 2, -// Information = 3, -// Hint = 4 -} - -impl Serialize for DiagnosticSeverity { - fn serialize(&self, serializer: &mut S) -> Result<(), S::Error> - where S: Serializer - { - serializer.serialize_u8(*self as u8) - } -} - -#[derive(Debug, Serialize)] -pub struct PublishDiagnosticsParams { - pub uri: String, - pub diagnostics: Vec, -} +pub use ls_types::Diagnostic; +pub use ls_types::DiagnosticSeverity; +pub use ls_types::PublishDiagnosticsParams; /// An event-like (no response needed) notification message. #[derive(Debug, Serialize)] @@ -219,26 +182,10 @@ impl NotificationMessage where T: Debug + Serialize { } } -/// A workspace edit represents changes to many resources managed in the workspace. -#[derive(Debug, Serialize)] -pub struct WorkspaceEdit { - pub changes: HashMap>, -} +pub use ls_types::WorkspaceEdit; -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct ReferenceParams { - pub textDocument: Document, - pub position: Position, - pub context: ReferenceContext, -} - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct TextDocumentPositionParams { - pub textDocument: Document, - pub position: Position, -} +pub use ls_types::ReferenceParams; +pub use ls_types::TextDocumentPositionParams; #[allow(non_snake_case)] #[derive(Debug, Deserialize)] @@ -247,130 +194,44 @@ pub struct ChangeParams { pub contentChanges: Vec } -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct HoverParams { - pub textDocument: Document, - pub position: Position -} +pub type HoverParams = TextDocumentPositionParams; +pub use ls_types::RenameParams; +pub use ls_types::DocumentSymbolParams; -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct RenameParams { - pub textDocument: Document, - pub position: Position, - pub newName: String, -} -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct DocumentSymbolParams { - pub textDocument: Document, -} +pub use ls_types::CancelParams; +pub use ls_types::TextDocumentSyncKind; -#[derive(Debug, Deserialize)] -pub struct CancelParams { - pub id: usize -} +pub use ls_types::MarkedString; -/// Defines how the host (editor) should sync document changes to the language server. -#[derive(Debug, Serialize)] -pub enum DocumentSyncKind { - // None = 0, - /// Documents are synced by always sending the full content of the document. - // Full = 1, - /// Documents are synced by sending the full content on open. After that only incremental - /// updates to the document are sent. - Incremental = 2, -} +pub use ls_types::Hover; +pub use ls_types::InitializeResult; -#[derive(Debug, Serialize)] -pub struct MarkedString { - pub language: String, - pub value: String -} +pub use ls_types::CompletionItem; -#[derive(Debug, Serialize)] -pub struct HoverSuccessContents { - pub contents: Vec +pub fn new_completion_item(label: String, detail: String) -> CompletionItem { + CompletionItem { + label : label, + kind: None, + detail: Some(detail), + documentation: None, + sort_text: None, + filter_text: None, + insert_text: None, + text_edit: None, + additional_text_edits: None, + command: None, + data: None, + } } -#[derive(Debug, Serialize)] -pub struct InitializeCapabilities { - pub capabilities: ServerCapabilities -} +pub use ls_types::TextEdit; +pub use ls_types::CompletionOptions; -#[derive(Debug, Serialize, Deserialize)] -pub struct CompletionItem { - pub label: String, - pub detail: String, -} +pub use ls_types::SignatureHelpOptions; -#[allow(non_snake_case)] -#[derive(Debug, Serialize)] -pub struct TextEdit { - pub range: Range, - pub newText: String, -} +pub use ls_types::DocumentFormattingParams; +pub use ls_types::DocumentRangeFormattingParams; +pub use ls_types::FormattingOptions; -#[allow(non_snake_case)] -#[derive(Debug, Serialize)] -pub struct CompletionOptions { - /// The server provides support to resolve additional information for a completion item. - pub resolveProvider: bool, - pub triggerCharacters: Vec, -} - -#[allow(non_snake_case)] -#[derive(Debug, Serialize)] -pub struct SignatureHelpOptions { - pub triggerCharacters: Vec, -} - -// #[allow(non_snake_case)] -// #[derive(Debug, Serialize)] -// pub struct CodeLensOptions { -// pub resolveProvider: bool, -// } - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct DocumentFormattingParams { - pub textDocument: TextDocumentIdentifier, - pub options: FormattingOptions, -} - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct DocumentRangeFormattingParams { - pub textDocument: TextDocumentIdentifier, - pub range: Range, - pub options: FormattingOptions, -} - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct FormattingOptions { - pub tabSize: u32, - pub insertSpaces: bool, -} - -#[allow(non_snake_case)] -#[derive(Debug, Serialize)] -pub struct ServerCapabilities { - pub textDocumentSync: usize, - pub hoverProvider: bool, - pub completionProvider: CompletionOptions, - pub signatureHelpProvider: SignatureHelpOptions, - pub definitionProvider: bool, - pub referencesProvider: bool, - pub documentHighlightProvider: bool, - pub documentSymbolProvider: bool, - pub workshopSymbolProvider: bool, - pub codeActionProvider: bool, - pub codeLensProvider: bool, - pub documentFormattingProvider: bool, - pub documentRangeFormattingProvider: bool, - // pub documentOnTypeFormattingProvider - pub renameProvider: bool, -} +pub use ls_types::ServerCapabilities; diff --git a/src/main.rs b/src/main.rs index bf9dbc38943..5a8274d6d1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,6 +10,7 @@ #![feature(rustc_private)] #![feature(proc_macro)] +#![feature(try_from)] #[macro_use] extern crate hyper; @@ -24,6 +25,8 @@ extern crate derive_new; extern crate racer; extern crate rustfmt; +extern crate languageserver_types as ls_types; + use std::sync::Arc; mod actions_http; From d87d7dbb23a80fa569b522fec6a99eb2f699fabd Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 26 Oct 2016 20:29:02 +0100 Subject: [PATCH 02/16] Complete usage of languageserver-types. Note that a case of DidChangeTextDocumentParams need handling. Closes #52 --- src/actions_ls.rs | 19 ++++++-- src/ls_server.rs | 4 +- src/lsp_data.rs | 110 +++++++++++----------------------------------- 3 files changed, 42 insertions(+), 91 deletions(-) diff --git a/src/actions_ls.rs b/src/actions_ls.rs index cfd30438ce3..7aac67003e1 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -162,11 +162,22 @@ impl ActionHandler { } } - pub fn on_change(&self, change: ChangeParams, out: &Output) { - let fname: PathBuf = Url::parse(&change.textDocument.uri).unwrap().to_file_path().unwrap(); - let changes: Vec = change.contentChanges.iter().map(move |i| { + pub fn on_change(&self, change: DidChangeTextDocumentParams, out: &Output) { + let fname: PathBuf = Url::parse(&change.text_document.uri).unwrap().to_file_path().unwrap(); + let changes: Vec = change.content_changes.iter().map(move |i| { + let range = match i.range { + Some(some) => { some } + None => { + // In this case the range is considered to be the whole document, + // as specified by LSP + + // FIXME: to do, endpos must be the end of the document, this is not correct + let end_pos = new_pos(0, 0); + Range{ start : new_pos(0, 0), end : end_pos } + } + }; Change { - span: RangeUtil::to_span(i.range, fname.clone()), + span: RangeUtil::to_span(range, fname.clone()), text: i.text.clone() } }).collect(); diff --git a/src/ls_server.rs b/src/ls_server.rs index 282a669d3cd..8e69092cd6a 100644 --- a/src/ls_server.rs +++ b/src/ls_server.rs @@ -63,7 +63,7 @@ enum Method { #[derive(Debug)] enum Notification { CancelRequest(NumberOrString), - Change(ChangeParams), + Change(DidChangeTextDocumentParams), } /// Creates an public enum whose variants all contain a single serializable payload @@ -127,7 +127,7 @@ fn parse_message(input: &str) -> Result { Ok(ServerMessage::Request(Request{id: id, method: Method::Hover(method)})) } "textDocument/didChange" => { - let method: ChangeParams = + let method: DidChangeTextDocumentParams = serde_json::from_value(params.unwrap().to_owned()).unwrap(); Ok(ServerMessage::Notification(Notification::Change(method))) } diff --git a/src/lsp_data.rs b/src/lsp_data.rs index 7b9f18e21f8..d766d354f25 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -18,6 +18,9 @@ use analysis::raw; use hyper::Url; use serde::{Serialize}; + +pub use ls_types::*; + macro_rules! impl_file_name { ($ty_name: ty) => { impl $ty_name { @@ -41,9 +44,9 @@ pub fn to_usize(pos: u64) -> usize { TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking } -pub use ls_types::Position; - -pub use ls_types::Range; +pub fn new_pos(line: u64, character: u64,) -> Position { + Position { line: line, character: character } +} pub struct RangeUtil; @@ -72,8 +75,6 @@ impl RangeUtil { } } -pub use ls_types::Location; - pub struct LocationUtil; impl LocationUtil { @@ -101,29 +102,6 @@ impl LocationUtil { } } -pub use ls_types::InitializeParams; -pub use ls_types::NumberOrString; - -pub use ls_types::TextDocumentIdentifier; -pub use ls_types::VersionedTextDocumentIdentifier; - -/// An event describing a change to a text document. If range and rangeLength are omitted -/// the new text is considered to be the full content of the document. -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct TextDocumentContentChangeEvent { - pub range: Range, - pub rangeLength: Option, - pub text: String -} -//pub use ls_types::TextDocumentContentChangeEvent; - - -pub use ls_types::ReferenceContext; - -pub use ls_types::SymbolInformation; -pub use ls_types::SymbolKind; - pub fn sk_from_def_kind(k: raw::DefKind) -> SymbolKind { match k { raw::DefKind::Enum => SymbolKind::Enum, @@ -143,7 +121,25 @@ pub fn sk_from_def_kind(k: raw::DefKind) -> SymbolKind { } } +pub fn new_completion_item(label: String, detail: String) -> CompletionItem { + CompletionItem { + label : label, + kind: None, + detail: Some(detail), + documentation: None, + sort_text: None, + filter_text: None, + insert_text: None, + text_edit: None, + additional_text_edits: None, + command: None, + data: None, + } +} +pub type HoverParams = TextDocumentPositionParams; + +/* ----------------- These are not LSP types: ----------------- */ #[derive(Debug, Deserialize)] pub struct CompilerMessageCode { @@ -158,9 +154,7 @@ pub struct CompilerMessage { pub spans: Vec, } -pub use ls_types::Diagnostic; -pub use ls_types::DiagnosticSeverity; -pub use ls_types::PublishDiagnosticsParams; +/* ----------------- These are not LSP types either, but JSON-RPC stuff : ----------------- */ /// An event-like (no response needed) notification message. #[derive(Debug, Serialize)] @@ -181,57 +175,3 @@ impl NotificationMessage where T: Debug + Serialize { } } } - -pub use ls_types::WorkspaceEdit; - -pub use ls_types::ReferenceParams; -pub use ls_types::TextDocumentPositionParams; - -#[allow(non_snake_case)] -#[derive(Debug, Deserialize)] -pub struct ChangeParams { - pub textDocument: VersionedTextDocumentIdentifier, - pub contentChanges: Vec -} - -pub type HoverParams = TextDocumentPositionParams; -pub use ls_types::RenameParams; -pub use ls_types::DocumentSymbolParams; - - -pub use ls_types::CancelParams; -pub use ls_types::TextDocumentSyncKind; - -pub use ls_types::MarkedString; - -pub use ls_types::Hover; -pub use ls_types::InitializeResult; - -pub use ls_types::CompletionItem; - -pub fn new_completion_item(label: String, detail: String) -> CompletionItem { - CompletionItem { - label : label, - kind: None, - detail: Some(detail), - documentation: None, - sort_text: None, - filter_text: None, - insert_text: None, - text_edit: None, - additional_text_edits: None, - command: None, - data: None, - } -} - -pub use ls_types::TextEdit; -pub use ls_types::CompletionOptions; - -pub use ls_types::SignatureHelpOptions; - -pub use ls_types::DocumentFormattingParams; -pub use ls_types::DocumentRangeFormattingParams; -pub use ls_types::FormattingOptions; - -pub use ls_types::ServerCapabilities; From ea098daa6e05973fba93f2b4126a7f3dd273d044 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 09:47:52 +0100 Subject: [PATCH 03/16] Replaced tabs --- src/actions_ls.rs | 26 +++++++++++++------------- src/lsp_data.rs | 10 +++++----- 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/actions_ls.rs b/src/actions_ls.rs index 7aac67003e1..f604493b9ea 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -57,8 +57,8 @@ impl ActionHandler { results.clear(); } let root_path = match root_path { - Some(some) => some, - None => return + Some(some) => some, + None => return }; { let mut current_project = self.current_project.lock().unwrap(); @@ -165,17 +165,17 @@ impl ActionHandler { pub fn on_change(&self, change: DidChangeTextDocumentParams, out: &Output) { let fname: PathBuf = Url::parse(&change.text_document.uri).unwrap().to_file_path().unwrap(); let changes: Vec = change.content_changes.iter().map(move |i| { - let range = match i.range { - Some(some) => { some } - None => { - // In this case the range is considered to be the whole document, - // as specified by LSP - - // FIXME: to do, endpos must be the end of the document, this is not correct - let end_pos = new_pos(0, 0); - Range{ start : new_pos(0, 0), end : end_pos } - } - }; + let range = match i.range { + Some(some) => { some } + None => { + // In this case the range is considered to be the whole document, + // as specified by LSP + + // FIXME: to do, endpos must be the end of the document, this is not correct + let end_pos = new_pos(0, 0); + Range{ start : new_pos(0, 0), end : end_pos } + } + }; Change { span: RangeUtil::to_span(range, fname.clone()), text: i.text.clone() diff --git a/src/lsp_data.rs b/src/lsp_data.rs index d766d354f25..507202151f1 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -37,15 +37,15 @@ pub fn uri_string_to_file_name(uri: &str) -> PathBuf { } pub fn from_usize(pos: usize) -> u64 { - TryFrom::try_from(pos).unwrap() // XXX: Should we do error handling or assume it's ok? + TryFrom::try_from(pos).unwrap() // XXX: Should we do error handling or assume it's ok? } pub fn to_usize(pos: u64) -> usize { - TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking + TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking } pub fn new_pos(line: u64, character: u64,) -> Position { - Position { line: line, character: character } + Position { line: line, character: character } } pub struct RangeUtil; @@ -122,7 +122,7 @@ pub fn sk_from_def_kind(k: raw::DefKind) -> SymbolKind { } pub fn new_completion_item(label: String, detail: String) -> CompletionItem { - CompletionItem { + CompletionItem { label : label, kind: None, detail: Some(detail), @@ -134,7 +134,7 @@ pub fn new_completion_item(label: String, detail: String) -> CompletionItem { additional_text_edits: None, command: None, data: None, - } + } } pub type HoverParams = TextDocumentPositionParams; From d6af2ed9068de76befb87797a47bd0ae2c8eebd3 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 10:22:39 +0100 Subject: [PATCH 04/16] Use MarkedString constructor --- Cargo.toml | 2 +- src/actions_ls.rs | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 217adfbb612..2b434980bd6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ serde = "0.8" serde_json = "0.8" serde_derive = "0.8" derive-new = "0.1" -languageserver-types = { version = "0.3.0", git = "https://github.com/gluon-lang/languageserver-types" } +languageserver-types = { version = "0.3.1", git = "https://github.com/gluon-lang/languageserver-types" } [dev-dependencies] env_logger = "0.3.0" diff --git a/src/actions_ls.rs b/src/actions_ls.rs index f604493b9ea..408827d41f2 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -386,13 +386,13 @@ impl ActionHandler { let mut contents = vec![]; if !docs.is_empty() { - contents.push(MarkedString::LanguageString { language: "markdown".into(), value: docs }); + contents.push(MarkedString::from_markdown(docs.into())); } if !doc_url.is_empty() { - contents.push(MarkedString::LanguageString { language: "url".into(), value: doc_url }); + contents.push(MarkedString::from_language_code("url".into(), doc_url.into())); } if !ty.is_empty() { - contents.push(MarkedString::LanguageString { language: "rust".into(), value: ty }); + contents.push(MarkedString::from_language_code("rust".into(), ty.into())); } Hover { contents: contents, From abee2695fa3dcb1dfb4a6fb31366fe831dd2cdac Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 11:54:22 +0100 Subject: [PATCH 05/16] Use Position::new --- src/actions_ls.rs | 18 ++++++------------ src/lsp_data.rs | 19 ++++++++----------- 2 files changed, 14 insertions(+), 23 deletions(-) diff --git a/src/actions_ls.rs b/src/actions_ls.rs index 408827d41f2..dbc6e08f796 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -172,8 +172,8 @@ impl ActionHandler { // as specified by LSP // FIXME: to do, endpos must be the end of the document, this is not correct - let end_pos = new_pos(0, 0); - Range{ start : new_pos(0, 0), end : end_pos } + let end_pos = Position::new(0, 0); + Range{ start : Position::new(0, 0), end : end_pos } } }; Change { @@ -438,14 +438,8 @@ impl ActionHandler { let text = String::from_utf8(buf).unwrap(); let result = [TextEdit { range: Range { - start: Position { - line: 0, - character: 0, - }, - end: Position { - line: from_usize(text.lines().count()), - character: 0, - }, + start: Position::new(0, 0), + end: Position::new(from_usize(text.lines().count()), 0), }, new_text: text, }]; @@ -464,7 +458,7 @@ impl ActionHandler { let line = self.vfs.load_line(&fname, to_usize(pos.line)); self.logger.log(&format!("\nGOT LINE: {:?}", line)); let start_pos = { - let mut tmp = Position { line: pos.line, character: 1 }; + let mut tmp = Position::new(pos.line, 1); for (i, c) in line.clone().unwrap().chars().enumerate() { if !(c.is_alphanumeric() || c == '_') { tmp.character = from_usize(i + 1); @@ -477,7 +471,7 @@ impl ActionHandler { }; let end_pos = { - let mut tmp = Position { line: pos.line, character: pos.character }; + let mut tmp = Position::new(pos.line, pos.character); for (i, c) in line.unwrap().chars().skip(to_usize(pos.character)).enumerate() { if !(c.is_alphanumeric() || c == '_') { break; diff --git a/src/lsp_data.rs b/src/lsp_data.rs index 507202151f1..fd1d48c0403 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -44,23 +44,20 @@ pub fn to_usize(pos: u64) -> usize { TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking } -pub fn new_pos(line: u64, character: u64,) -> Position { - Position { line: line, character: character } -} pub struct RangeUtil; impl RangeUtil { pub fn from_span(span: &Span) -> Range { Range { - start: Position { - line: from_usize(span.line_start), - character: from_usize(span.column_start), - }, - end: Position { - line: from_usize(span.line_end), - character: from_usize(span.column_end), - }, + start: Position::new( + from_usize(span.line_start), + from_usize(span.column_start), + ), + end: Position::new( + from_usize(span.line_end), + from_usize(span.column_end), + ), } } From 59044aa17e230ce85a13aec3c3dcba1333470896 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 12:02:12 +0100 Subject: [PATCH 06/16] symbol_kind_from_def_kind and ls_util module --- src/actions_ls.rs | 16 ++++++++-------- src/lsp_data.rs | 28 ++++++++++++++-------------- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/actions_ls.rs b/src/actions_ls.rs index dbc6e08f796..b200bc827ef 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -89,7 +89,7 @@ impl ActionHandler { continue; } let mut diag = Diagnostic { - range: RangeUtil::from_span(&method.spans[0]), + range: ls_util::range_from_span(&method.spans[0]), severity: Some(if method.level == "error" { DiagnosticSeverity::Error } else { @@ -177,7 +177,7 @@ impl ActionHandler { } }; Change { - span: RangeUtil::to_span(range, fname.clone()), + span: ls_util::range_to_span(range, fname.clone()), text: i.text.clone() } }).collect(); @@ -211,8 +211,8 @@ impl ActionHandler { symbols.into_iter().map(|s| { SymbolInformation { name: s.name, - kind: sk_from_def_kind(s.kind), - location: LocationUtil::from_span(&s.span), + kind: source_kind_from_def_kind(s.kind), + location: ls_util::location_from_span(&s.span), container_name: None // TODO: more info could be added here } }).collect() @@ -269,7 +269,7 @@ impl ActionHandler { let mut edits: HashMap> = HashMap::new(); for item in result.iter() { - let loc = LocationUtil::from_span(&item); + let loc = ls_util::location_from_span(&item); edits.entry(loc.uri).or_insert(vec![]).push(TextEdit { range: loc.range, new_text: params.new_name.clone(), @@ -294,7 +294,7 @@ impl ActionHandler { thread::park_timeout(Duration::from_millis(::COMPILER_TIMEOUT)); let result = rustw_handle.join().ok().and_then(|t| t.ok()).unwrap_or(vec![]); - let refs: Vec<_> = result.iter().map(|item| LocationUtil::from_span(&item)).collect(); + let refs: Vec<_> = result.iter().map(|item| ls_util::location_from_span(&item)).collect(); out.success(id, ResponseData::Locations(refs)); } @@ -337,7 +337,7 @@ impl ActionHandler { let (line, col) = session.load_file(source_path) .point_to_coords(mtch.point) .unwrap(); - Some(LocationUtil::from_position(source_path, + Some(ls_util::location_from_position(source_path, adjust_racer_line_for_vscode(line), col)) } else { @@ -351,7 +351,7 @@ impl ActionHandler { let compiler_result = compiler_handle.join(); match compiler_result { Ok(Ok(r)) => { - let result = vec![LocationUtil::from_span(&r)]; + let result = vec![ls_util::location_from_span(&r)]; self.logger.log(&format!("\nGOING TO: {:?}\n", result)); out.success(id, ResponseData::Locations(result)); } diff --git a/src/lsp_data.rs b/src/lsp_data.rs index fd1d48c0403..d3825630e5b 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -9,7 +9,7 @@ // except according to those terms. use std::fmt::Debug; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::convert::TryFrom; @@ -45,10 +45,14 @@ pub fn to_usize(pos: u64) -> usize { } -pub struct RangeUtil; +pub mod ls_util { + use super::*; + use std::path::{Path, PathBuf}; -impl RangeUtil { - pub fn from_span(span: &Span) -> Range { + use analysis::Span; + use hyper::Url; + + pub fn range_from_span(span: &Span) -> Range { Range { start: Position::new( from_usize(span.line_start), @@ -61,7 +65,7 @@ impl RangeUtil { } } - pub fn to_span(this: Range, fname: PathBuf) -> Span { + pub fn range_to_span(this: Range, fname: PathBuf) -> Span { Span { file_name: fname, line_start: to_usize(this.start.line), @@ -70,19 +74,15 @@ impl RangeUtil { column_end: to_usize(this.end.character), } } -} - -pub struct LocationUtil; - -impl LocationUtil { - pub fn from_span(span: &Span) -> Location { + + pub fn location_from_span(span: &Span) -> Location { Location { uri: Url::from_file_path(&span.file_name).unwrap().into_string(), - range: RangeUtil::from_span(span), + range: range_from_span(span), } } - pub fn from_position(file_name: &Path, line: usize, col: usize) -> Location { + pub fn location_from_position(file_name: &Path, line: usize, col: usize) -> Location { Location { uri: Url::from_file_path(&file_name).unwrap().into_string(), range: Range { @@ -99,7 +99,7 @@ impl LocationUtil { } } -pub fn sk_from_def_kind(k: raw::DefKind) -> SymbolKind { +pub fn source_kind_from_def_kind(k: raw::DefKind) -> SymbolKind { match k { raw::DefKind::Enum => SymbolKind::Enum, raw::DefKind::Tuple => SymbolKind::Array, From 627bb03a728b37e34ce710bd210a08376887b361 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 12:10:36 +0100 Subject: [PATCH 07/16] CompletionItem::new_simple, removed HoverParams alias --- src/actions_ls.rs | 4 ++-- src/ls_server.rs | 4 ++-- src/lsp_data.rs | 18 ------------------ 3 files changed, 4 insertions(+), 22 deletions(-) diff --git a/src/actions_ls.rs b/src/actions_ls.rs index b200bc827ef..e1c6ea218a0 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -241,7 +241,7 @@ impl ActionHandler { let pos = session.load_file(file_path).coords_to_point(to_usize(pos.line), to_usize(pos.character)).unwrap(); let results = complete_from_file(&src.code, file_path, pos, &session); - results.map(|comp| new_completion_item( + results.map(|comp| CompletionItem::new_simple( comp.matchstr.clone(), comp.contextstr.clone(), )).collect() @@ -371,7 +371,7 @@ impl ActionHandler { } } - pub fn hover(&self, id: usize, params: HoverParams, out: &Output) { + pub fn hover(&self, id: usize, params: TextDocumentPositionParams, out: &Output) { let t = thread::current(); let span = self.convert_pos_to_span(¶ms.text_document, ¶ms.position); diff --git a/src/ls_server.rs b/src/ls_server.rs index 8e69092cd6a..54e4f421417 100644 --- a/src/ls_server.rs +++ b/src/ls_server.rs @@ -49,7 +49,7 @@ struct Request { enum Method { Shutdown, Initialize(InitializeParams), - Hover(HoverParams), + Hover(TextDocumentPositionParams), GotoDef(TextDocumentPositionParams), FindAllRef(ReferenceParams), Symbols(DocumentSymbolParams), @@ -122,7 +122,7 @@ fn parse_message(input: &str) -> Result { } "textDocument/hover" => { let id = ls_command.lookup("id").unwrap().as_u64().unwrap() as usize; - let method: HoverParams = + let method: TextDocumentPositionParams = serde_json::from_value(params.unwrap().to_owned()).unwrap(); Ok(ServerMessage::Request(Request{id: id, method: Method::Hover(method)})) } diff --git a/src/lsp_data.rs b/src/lsp_data.rs index d3825630e5b..be53bfe02ea 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -118,24 +118,6 @@ pub fn source_kind_from_def_kind(k: raw::DefKind) -> SymbolKind { } } -pub fn new_completion_item(label: String, detail: String) -> CompletionItem { - CompletionItem { - label : label, - kind: None, - detail: Some(detail), - documentation: None, - sort_text: None, - filter_text: None, - insert_text: None, - text_edit: None, - additional_text_edits: None, - command: None, - data: None, - } -} - -pub type HoverParams = TextDocumentPositionParams; - /* ----------------- These are not LSP types: ----------------- */ #[derive(Debug, Deserialize)] From 6eb2ce4b926b3ebe9e4e922007dccd1360e9bb58 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 12:54:34 +0100 Subject: [PATCH 08/16] fix tests --- src/test/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test/mod.rs b/src/test/mod.rs index ad2824ed0a0..17b0a89b23e 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -92,7 +92,7 @@ fn test_simple_goto_def_ls() { let source_file_path = Path::new("src").join("main.rs"); let messages = vec![Message::new("initialize", - vec![("processId", "0".to_owned()), ("rootPath", format!("{}", + vec![("processId", "0".to_owned()), ("capabilities", "null".to_owned()), ("rootPath", format!("{}", serde_json::to_string(&cache.abs_path(Path::new("."))).expect("couldn't convert path to JSON") ))]), Message::new("textDocument/definition", From 038087ee3c0e3cf013b7d2b47f7bb7e5a0771c8a Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 12:58:54 +0100 Subject: [PATCH 09/16] Cargo.lock --- Cargo.lock | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 3aa8eedd644..519bab0cf8a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ dependencies = [ "derive-new 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.3.0 (git+https://github.com/gluon-lang/languageserver-types)", + "languageserver-types 0.3.1 (git+https://github.com/gluon-lang/languageserver-types)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "racer 1.2.10 (git+https://github.com/phildawes/racer)", "rls-analysis 0.1.0 (git+https://github.com/nrc/rls-analysis)", @@ -173,8 +173,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "languageserver-types" -version = "0.3.0" -source = "git+https://github.com/gluon-lang/languageserver-types#05c7e9cfcaf4ee088826796bbb044f19b104cc1a" +version = "0.3.1" +source = "git+https://github.com/gluon-lang/languageserver-types#f7f8a666d903a071c9f1c7a1cc0b04036c920862" dependencies = [ "enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -680,7 +680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum languageserver-types 0.3.0 (git+https://github.com/gluon-lang/languageserver-types)" = "" +"checksum languageserver-types 0.3.1 (git+https://github.com/gluon-lang/languageserver-types)" = "" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd" From 75fa8e5cb2bd47b490b6e8912c4b1120b34235d6 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Thu, 27 Oct 2016 16:51:00 +0100 Subject: [PATCH 10/16] languageserver-types 0.4.0, which has some fixes. --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 519bab0cf8a..43db547da1f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ dependencies = [ "derive-new 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.3.1 (git+https://github.com/gluon-lang/languageserver-types)", + "languageserver-types 0.4.0 (git+https://github.com/gluon-lang/languageserver-types)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "racer 1.2.10 (git+https://github.com/phildawes/racer)", "rls-analysis 0.1.0 (git+https://github.com/nrc/rls-analysis)", @@ -173,8 +173,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "languageserver-types" -version = "0.3.1" -source = "git+https://github.com/gluon-lang/languageserver-types#f7f8a666d903a071c9f1c7a1cc0b04036c920862" +version = "0.4.0" +source = "git+https://github.com/gluon-lang/languageserver-types#4d826b673fa19487e6c2058c47d8263fff99cce8" dependencies = [ "enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", @@ -680,7 +680,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum languageserver-types 0.3.1 (git+https://github.com/gluon-lang/languageserver-types)" = "" +"checksum languageserver-types 0.4.0 (git+https://github.com/gluon-lang/languageserver-types)" = "" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd" diff --git a/Cargo.toml b/Cargo.toml index 2b434980bd6..c27e67c156c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ serde = "0.8" serde_json = "0.8" serde_derive = "0.8" derive-new = "0.1" -languageserver-types = { version = "0.3.1", git = "https://github.com/gluon-lang/languageserver-types" } +languageserver-types = { version = "0.4.0", git = "https://github.com/gluon-lang/languageserver-types" } [dev-dependencies] env_logger = "0.3.0" From 0440f36c203b2acf8c13169e04604d18fdf155d6 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Fri, 28 Oct 2016 11:02:17 +0100 Subject: [PATCH 11/16] comment about VscodeKind deprecation --- src/ide.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/ide.rs b/src/ide.rs index 93d72c75041..a23fd672bda 100644 --- a/src/ide.rs +++ b/src/ide.rs @@ -75,6 +75,8 @@ pub fn parse_string(input: &[u8]) -> Result { } // TODO: deprecate/remove in favor of ls_types::SymbolKind ? +// This type is at the moment only used by the HTTP server interface, +// which is planned to be removed, according to @nrc #[allow(dead_code)] #[derive(Debug, Serialize)] pub enum VscodeKind { From a08f071dbd6dd01a6d6b110538947d6303698995 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Tue, 8 Nov 2016 19:45:05 +0000 Subject: [PATCH 12/16] ls-types 0.5.0 (URI fields) --- Cargo.lock | 10 ++++++---- Cargo.toml | 2 +- src/actions_ls.rs | 22 +++++++++++----------- src/lsp_data.rs | 15 ++++++++++----- 4 files changed, 28 insertions(+), 21 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 43db547da1f..088f7159c9a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ dependencies = [ "derive-new 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", "hyper 0.9.10 (registry+https://github.com/rust-lang/crates.io-index)", - "languageserver-types 0.4.0 (git+https://github.com/gluon-lang/languageserver-types)", + "languageserver-types 0.5.0 (git+https://github.com/gluon-lang/languageserver-types)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "racer 1.2.10 (git+https://github.com/phildawes/racer)", "rls-analysis 0.1.0 (git+https://github.com/nrc/rls-analysis)", @@ -173,13 +173,14 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "languageserver-types" -version = "0.4.0" -source = "git+https://github.com/gluon-lang/languageserver-types#4d826b673fa19487e6c2058c47d8263fff99cce8" +version = "0.5.0" +source = "git+https://github.com/gluon-lang/languageserver-types#f4829150da4a8b38b957adf7b2442dd09377615e" dependencies = [ "enum_primitive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde_derive 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", "serde_json 0.8.3 (registry+https://github.com/rust-lang/crates.io-index)", + "url 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -628,6 +629,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "idna 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 0.8.13 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -680,7 +682,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" "checksum itoa 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "ae3088ea4baeceb0284ee9eea42f591226e6beaecf65373e41b38d95a1b8e7a1" "checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d" "checksum language-tags 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a91d884b6667cd606bb5a69aa0c99ba811a115fc68915e7056ec08a46e93199a" -"checksum languageserver-types 0.4.0 (git+https://github.com/gluon-lang/languageserver-types)" = "" +"checksum languageserver-types 0.5.0 (git+https://github.com/gluon-lang/languageserver-types)" = "" "checksum libc 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "044d1360593a78f5c8e5e710beccdc24ab71d1f01bc19a29bcacdba22e8475d8" "checksum log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "ab83497bf8bf4ed2a74259c1c802351fcd67a65baa86394b6ba73c36f4838054" "checksum matches 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc3ad8109fa4b522f9b0cd81440422781f564aaf8c195de6b9d6642177ad0dd" diff --git a/Cargo.toml b/Cargo.toml index c27e67c156c..b972f210769 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -13,7 +13,7 @@ serde = "0.8" serde_json = "0.8" serde_derive = "0.8" derive-new = "0.1" -languageserver-types = { version = "0.4.0", git = "https://github.com/gluon-lang/languageserver-types" } +languageserver-types = { version = "0.5.0", git = "https://github.com/gluon-lang/languageserver-types" } [dev-dependencies] env_logger = "0.3.0" diff --git a/src/actions_ls.rs b/src/actions_ls.rs index e1c6ea218a0..dc06b7ff076 100644 --- a/src/actions_ls.rs +++ b/src/actions_ls.rs @@ -130,10 +130,10 @@ impl ActionHandler { for (k, v) in results.iter() { notifications.push(NotificationMessage::new( "textDocument/publishDiagnostics".to_string(), - PublishDiagnosticsParams { - uri: Url::from_file_path(project_path.join(k)).unwrap().into_string(), - diagnostics: v.clone() - } + PublishDiagnosticsParams::new( + Url::from_file_path(project_path.join(k)).unwrap(), + v.clone(), + ) )); } } @@ -163,7 +163,7 @@ impl ActionHandler { } pub fn on_change(&self, change: DidChangeTextDocumentParams, out: &Output) { - let fname: PathBuf = Url::parse(&change.text_document.uri).unwrap().to_file_path().unwrap(); + let fname: PathBuf = parse_file_path(&change.text_document.uri).unwrap(); let changes: Vec = change.content_changes.iter().map(move |i| { let range = match i.range { Some(some) => { some } @@ -204,7 +204,7 @@ impl ActionHandler { let analysis = self.analysis.clone(); let rustw_handle = thread::spawn(move || { - let file_name = uri_string_to_file_name(&doc.text_document.uri); + let file_name = parse_file_path(&doc.text_document.uri).unwrap(); let symbols = analysis.symbols(&file_name).unwrap_or(vec![]); t.unpark(); @@ -228,7 +228,7 @@ impl ActionHandler { let vfs: &Vfs = &self.vfs; let result: Vec = panic::catch_unwind(move || { let pos = adjust_vscode_pos_for_racer(params.position); - let file_path = &uri_string_to_file_name(¶ms.text_document.uri); + let file_path = &parse_file_path(¶ms.text_document.uri).unwrap(); let cache = core::FileCache::new(); let session = core::Session::from_path(&cache, file_path, file_path); @@ -266,7 +266,7 @@ impl ActionHandler { let result = rustw_handle.join().ok().and_then(|t| t.ok()).unwrap_or(vec![]); - let mut edits: HashMap> = HashMap::new(); + let mut edits: HashMap> = HashMap::new(); for item in result.iter() { let loc = ls_util::location_from_span(&item); @@ -317,7 +317,7 @@ impl ActionHandler { // Racer thread. let racer_handle = thread::spawn(move || { let pos = adjust_vscode_pos_for_racer(params.position); - let file_path = &uri_string_to_file_name(¶ms.text_document.uri); + let file_path = &parse_file_path(¶ms.text_document.uri).unwrap(); let cache = core::FileCache::new(); let session = core::Session::from_path(&cache, file_path, file_path); @@ -416,7 +416,7 @@ impl ActionHandler { pub fn reformat(&self, id: usize, doc: TextDocumentIdentifier, out: &Output) { self.logger.log(&format!("Reformat: {} {:?}\n", id, doc)); - let path = &uri_string_to_file_name(&doc.uri); + let path = &parse_file_path(&doc.uri).unwrap(); let input = match self.vfs.load_file(path) { Ok(s) => FmtInput::Text(s), Err(e) => { @@ -453,7 +453,7 @@ impl ActionHandler { } fn convert_pos_to_span(&self, doc: &TextDocumentIdentifier, pos: &Position) -> Span { - let fname = uri_string_to_file_name(&doc.uri); + let fname = parse_file_path(&doc.uri).unwrap(); self.logger.log(&format!("\nWorking on: {:?} {:?}", fname, pos)); let line = self.vfs.load_line(&fname, to_usize(pos.line)); self.logger.log(&format!("\nGOT LINE: {:?}", line)); diff --git a/src/lsp_data.rs b/src/lsp_data.rs index be53bfe02ea..878c2dc7d21 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -12,6 +12,7 @@ use std::fmt::Debug; use std::path::PathBuf; use std::convert::TryFrom; +use std::error::Error; use analysis::Span; use analysis::raw; @@ -31,9 +32,13 @@ macro_rules! impl_file_name { } } -pub fn uri_string_to_file_name(uri: &str) -> PathBuf { - let uri = Url::parse(&uri).unwrap(); - uri.to_file_path().unwrap() +pub fn parse_file_path(uri: &Url) -> Result> { + + if uri.scheme() != "file" { + return Err("URI scheme is not `file`".into()); + } + + uri.to_file_path().map_err(|_err| "Invalid file path in URI".into()) } pub fn from_usize(pos: usize) -> u64 { @@ -77,14 +82,14 @@ pub mod ls_util { pub fn location_from_span(span: &Span) -> Location { Location { - uri: Url::from_file_path(&span.file_name).unwrap().into_string(), + uri: Url::from_file_path(&span.file_name).unwrap(), range: range_from_span(span), } } pub fn location_from_position(file_name: &Path, line: usize, col: usize) -> Location { Location { - uri: Url::from_file_path(&file_name).unwrap().into_string(), + uri: Url::from_file_path(&file_name).unwrap(), range: Range { start: Position { line: from_usize(line), From a6487c8c6c39ca6b3338f381cf92c896917b5e1d Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 9 Nov 2016 12:50:13 +0000 Subject: [PATCH 13/16] Removed VscodeKind since it was only used by HTTP server --- src/ide.rs | 50 -------------------------------------------------- 1 file changed, 50 deletions(-) diff --git a/src/ide.rs b/src/ide.rs index 4d5f9dd40c0..5f38cbaa2b6 100644 --- a/src/ide.rs +++ b/src/ide.rs @@ -50,53 +50,3 @@ pub struct SaveInput { pub project_path: PathBuf, pub saved_file: PathBuf, } - -// TODO: deprecate/remove in favor of ls_types::SymbolKind ? -// This type is at the moment only used by the HTTP server interface, -// which is planned to be removed, according to @nrc -#[allow(dead_code)] -#[derive(Debug, Serialize)] -pub enum VscodeKind { - File, - Module, - Namespace, - Package, - Class, - Method, - Property, - Field, - Constructor, - Enum, - Interface, - Function, - Variable, - Constant, - String, - Number, - Boolean, - Array, - Object, - Key, - Null -} - -impl From for VscodeKind { - fn from(k: raw::DefKind) -> VscodeKind { - match k { - raw::DefKind::Enum => VscodeKind::Enum, - raw::DefKind::Tuple => VscodeKind::Array, - raw::DefKind::Struct => VscodeKind::Class, - raw::DefKind::Trait => VscodeKind::Interface, - raw::DefKind::Function => VscodeKind::Function, - raw::DefKind::Method => VscodeKind::Function, - raw::DefKind::Macro => VscodeKind::Function, - raw::DefKind::Mod => VscodeKind::Module, - raw::DefKind::Type => VscodeKind::Interface, - raw::DefKind::Local => VscodeKind::Variable, - raw::DefKind::Static => VscodeKind::Variable, - raw::DefKind::Const => VscodeKind::Variable, - raw::DefKind::Field => VscodeKind::Variable, - raw::DefKind::Import => VscodeKind::Module, - } - } -} From c3f6670ab77b3d62f7af04ab17e3e57c0fab8d6a Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 9 Nov 2016 13:06:28 +0000 Subject: [PATCH 14/16] fix test failures? --- src/test/mod.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/test/mod.rs b/src/test/mod.rs index ab6dfb6731e..af54f7cd866 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -58,6 +58,7 @@ fn test_abs_path() { let text_doc = format!("{{\"uri\":{}}}", serde_json::to_string(&url.as_str().to_owned()) .expect("couldn't convert path to JSON")); let messages = vec![Message::new("initialize", vec![("processId", "0".to_owned()), + ("capabilities", "null".to_owned()), ("rootPath", root_path)]), Message::new("textDocument/definition", vec![("textDocument", text_doc), @@ -92,6 +93,7 @@ fn test_simple_goto_def() { let text_doc = format!("{{\"uri\":{}}}", serde_json::to_string(&url.as_str().to_owned()) .expect("couldn't convert path to JSON")); let messages = vec![Message::new("initialize", vec![("processId", "0".to_owned()), + ("capabilities", "null".to_owned()), ("rootPath", root_path)]), Message::new("textDocument/definition", vec![("textDocument", text_doc), From 09165774f681027a37ce36cf82bc3c4f275cc985 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Fri, 11 Nov 2016 16:32:49 +0000 Subject: [PATCH 15/16] fix tests for logging crate --- src/test/mod.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/test/mod.rs b/src/test/mod.rs index 6e1dc97837c..552f12360c5 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -128,8 +128,7 @@ fn test_parse_error_on_malformed_input() { let reader = Box::new(NoneMsgReader); let output = Box::new(RecordOutput::new()); let results = output.output.clone(); - let logger = Arc::new(ls_server::Logger::new()); - let server = ls_server::LsService::new(analysis, vfs, build_queue, reader, output, logger); + let server = ls_server::LsService::new(analysis, vfs, build_queue, reader, output); assert_eq!(ls_server::LsService::handle_message(server.clone()), ls_server::ServerStateChange::Break); @@ -166,8 +165,7 @@ fn mock_lsp_server(messages: Vec) -> (Arc, LsResu let reader = Box::new(MockMsgReader { messages: messages, cur: AtomicUsize::new(0) }); let output = Box::new(RecordOutput::new()); let results = output.output.clone(); - let logger = Arc::new(ls_server::Logger::new()); - (ls_server::LsService::new(analysis, vfs, build_queue, reader, output, logger), results) + (ls_server::LsService::new(analysis, vfs, build_queue, reader, output), results) } // Despite the use of AtomicUsize and thus being Sync, this struct is not properly From 948eb0ad70a8e95ddd871a1d1f522fbc16471907 Mon Sep 17 00:00:00 2001 From: Bruno Medeiros Date: Wed, 16 Nov 2016 14:18:24 +0000 Subject: [PATCH 16/16] Second round of review changes. --- src/actions.rs | 28 +++++++++------------------- src/ide.rs | 2 +- src/lsp_data.rs | 27 ++++++++++++++++++--------- src/main.rs | 1 - src/server.rs | 4 +++- 5 files changed, 31 insertions(+), 31 deletions(-) diff --git a/src/actions.rs b/src/actions.rs index 8b936197eb3..c2c9752e10d 100644 --- a/src/actions.rs +++ b/src/actions.rs @@ -48,15 +48,11 @@ impl ActionHandler { } } - pub fn init(&self, root_path: Option, out: &Output) { + pub fn init(&self, root_path: PathBuf, out: &Output) { { let mut results = self.previous_build_results.lock().unwrap(); results.clear(); } - let root_path = match root_path { - Some(some) => some, - None => return - }; { let mut current_project = self.current_project.lock().unwrap(); *current_project = Some(root_path.clone()); @@ -161,17 +157,11 @@ impl ActionHandler { pub fn on_change(&self, change: DidChangeTextDocumentParams, out: &Output) { let fname: PathBuf = parse_file_path(&change.text_document.uri).unwrap(); let changes: Vec = change.content_changes.iter().map(move |i| { - let range = match i.range { - Some(some) => { some } - None => { - // In this case the range is considered to be the whole document, - // as specified by LSP - - // FIXME: to do, endpos must be the end of the document, this is not correct - let end_pos = Position::new(0, 0); - Range{ start : Position::new(0, 0), end : end_pos } - } - }; + let range = i.range.unwrap_or_else(|| { + // In this case the range is considered to be the whole document, + // as specified by LSP + ls_util::range_from_vfs_file(&self.vfs, &fname) + }); Change { span: ls_util::range_to_span(range, fname.clone()), text: i.text.clone() @@ -209,7 +199,7 @@ impl ActionHandler { name: s.name, kind: source_kind_from_def_kind(s.kind), location: ls_util::location_from_span(&s.span), - container_name: None // TODO: more info could be added here + container_name: None // FIXME: more info could be added here } }).collect() }); @@ -357,8 +347,8 @@ impl ActionHandler { .point_to_coords(mtch.point) .unwrap(); Some(ls_util::location_from_position(source_path, - adjust_racer_line_for_vscode(line), - col)) + adjust_racer_line_for_vscode(line), + col)) } else { None } diff --git a/src/ide.rs b/src/ide.rs index 5f38cbaa2b6..5d1ff683d19 100644 --- a/src/ide.rs +++ b/src/ide.rs @@ -10,7 +10,7 @@ use std::path::PathBuf; -use analysis::{raw, Span}; +use analysis::{Span}; use vfs::Change; diff --git a/src/lsp_data.rs b/src/lsp_data.rs index 878c2dc7d21..e6a40217f2e 100644 --- a/src/lsp_data.rs +++ b/src/lsp_data.rs @@ -11,7 +11,6 @@ use std::fmt::Debug; use std::path::PathBuf; -use std::convert::TryFrom; use std::error::Error; use analysis::Span; @@ -33,24 +32,25 @@ macro_rules! impl_file_name { } pub fn parse_file_path(uri: &Url) -> Result> { - if uri.scheme() != "file" { - return Err("URI scheme is not `file`".into()); + Err("URI scheme is not `file`".into()) + } else { + uri.to_file_path().map_err(|_err| "Invalid file path in URI".into()) } - - uri.to_file_path().map_err(|_err| "Invalid file path in URI".into()) } pub fn from_usize(pos: usize) -> u64 { - TryFrom::try_from(pos).unwrap() // XXX: Should we do error handling or assume it's ok? + pos as u64 } pub fn to_usize(pos: u64) -> usize { - TryFrom::try_from(pos).unwrap() // FIXME: for this one we definitely need to add error checking + pos as usize // Truncation might happen if usize is 32 bits. } pub mod ls_util { + use vfs::Vfs; + use super::*; use std::path::{Path, PathBuf}; @@ -80,6 +80,13 @@ pub mod ls_util { } } + pub fn range_from_vfs_file(_vfs: &Vfs, _fname: &Path) -> Range { + // FIXME: todo, endpos must be the end of the document, this is not correct + + let end_pos = Position::new(0, 0); + Range{ start : Position::new(0, 0), end : end_pos } + } + pub fn location_from_span(span: &Span) -> Location { Location { uri: Url::from_file_path(&span.file_name).unwrap(), @@ -123,7 +130,8 @@ pub fn source_kind_from_def_kind(k: raw::DefKind) -> SymbolKind { } } -/* ----------------- These are not LSP types: ----------------- */ +/* ----------------- Compiler message ----------------- */ +// FIXME: These types are not LSP related, should be moved to a different module. #[derive(Debug, Deserialize)] pub struct CompilerMessageCode { @@ -138,7 +146,8 @@ pub struct CompilerMessage { pub spans: Vec, } -/* ----------------- These are not LSP types either, but JSON-RPC stuff : ----------------- */ +/* ----------------- JSON-RPC protocol types ----------------- */ +// FIXME: These types are not directly LSP related, should be moved to a JSON-RPC module. /// An event-like (no response needed) notification message. #[derive(Debug, Serialize)] diff --git a/src/main.rs b/src/main.rs index 86816dba650..7ed6d3c8ec6 100644 --- a/src/main.rs +++ b/src/main.rs @@ -10,7 +10,6 @@ #![feature(rustc_private)] #![feature(proc_macro)] -#![feature(try_from)] #[macro_use] extern crate derive_new; diff --git a/src/server.rs b/src/server.rs index 363e62381ca..2200a67d3dc 100644 --- a/src/server.rs +++ b/src/server.rs @@ -237,7 +237,9 @@ impl LsService { }; self.output.success(id, ResponseData::Init(result)); let root_path = init.root_path.map(|str| PathBuf::from(str)); - self.handler.init(root_path, &*self.output); + if let Some(root_path) = root_path { + self.handler.init(root_path, &*self.output); + } } pub fn handle_message(this: Arc) -> ServerStateChange {