Repository: rust-analyzer/rust-analyzer
Pull request #1739 (2019-08-30 14:24:23)

move lsp-server to a separate repository


Patch:
diff --git a/Cargo.lock b/Cargo.lock
index 93814bedc9..17e60aa821 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -214,23 +214,6 @@ dependencies = [
  "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
-[[package]]
-name = "console"
-version = "0.7.7"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-dependencies = [
- "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)",
- "clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "encode_unicode 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
- "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)",
- "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "regex 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "termios 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "unicode-width 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "winapi 0.3.7 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "console"
 version = "0.8.0"
@@ -472,18 +455,6 @@ name = "fuchsia-zircon-sys"
 version = "0.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 
-[[package]]
-name = "gen_lsp_server"
-version = "0.2.0"
-dependencies = [
- "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
- "flexi_logger 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
- "lsp-types 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
- "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
-]
-
 [[package]]
 name = "getrandom"
 version = "0.1.10"
@@ -539,7 +510,7 @@ name = "indicatif"
 version = "0.11.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 dependencies = [
- "console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "number_prefix 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -689,6 +660,17 @@ dependencies = [
  "cfg-if 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
+[[package]]
+name = "lsp-server"
+version = "0.1.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
+ "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde 1.0.99 (registry+https://github.com/rust-lang/crates.io-index)",
+ "serde_json 1.0.40 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
 [[package]]
 name = "lsp-types"
 version = "0.60.0"
@@ -1092,8 +1074,8 @@ version = "0.1.0"
 dependencies = [
  "crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
  "flexi_logger 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
- "gen_lsp_server 0.2.0",
  "log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lsp-server 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "lsp-types 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "ra_ide_api 0.1.0",
@@ -1899,7 +1881,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9"
 "checksum clicolors-control 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)" = "73abfd4c73d003a674ce5d2933fca6ce6c42480ea84a5ffe0a2dc39ed56300f9"
 "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
-"checksum console 0.7.7 (registry+https://github.com/rust-lang/crates.io-index)" = "8ca57c2c14b8a2bf3105bc9d15574aad80babf6a9c44b1058034cdf8bd169628"
 "checksum console 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "b147390a412132d75d10dd3b7b175a69cf5fd95032f7503c7091b8831ba10242"
 "checksum crossbeam 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)" = "2d818a4990769aac0c7ff1360e233ef3a41adcb009ebb2036bf6915eb0f6b23c"
 "checksum crossbeam-channel 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "c8ec7fcd21571dc78f96cc96243cab8d8f035247c3efd16c687be154c3fa9efa"
@@ -1956,6 +1937,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83"
 "checksum lock_api 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "f8912e782533a93a167888781b836336a6ca5da6175c05944c86cf28c31104dc"
 "checksum log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)" = "14b6052be84e6b71ab17edffc2eeabf5c2c3ae1fdb464aae35ac50c67a44e1f7"
+"checksum lsp-server 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "47632ec528046c1a39f14448f1ee7d66d4b7b83e1771590b62e6c08665dea053"
 "checksum lsp-types 0.60.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fe3edefcd66dde1f7f1df706f46520a3c93adc5ca4bc5747da6621195e894efd"
 "checksum matches 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)" = "7ffc5c5338469d4d3ea17d269fa8ea3512ad247247c30bd2df69e68309ed0a08"
 "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e"
diff --git a/crates/gen_lsp_server/Cargo.toml b/crates/gen_lsp_server/Cargo.toml
deleted file mode 100644
index 7011aa1bfb..0000000000
--- a/crates/gen_lsp_server/Cargo.toml
+++ /dev/null
@@ -1,18 +0,0 @@
-[package]
-edition = "2018"
-name = "gen_lsp_server"
-version = "0.2.0"
-authors = ["rust-analyzer developers"]
-repository = "https://github.com/rust-analyzer/rust-analyzer"
-license = "MIT OR Apache-2.0"
-description = "Generic LSP server scaffold."
-
-[dependencies]
-lsp-types = "0.60.0"
-log = "0.4.3"
-serde_json = "1.0.34"
-serde = { version = "1.0.83", features = ["derive"] }
-crossbeam-channel = "0.3.5"
-
-[dev-dependencies]
-flexi_logger = "0.14.0"
diff --git a/crates/gen_lsp_server/examples/01_gen_lsp_server.rs b/crates/gen_lsp_server/examples/01_gen_lsp_server.rs
deleted file mode 100644
index f499650649..0000000000
--- a/crates/gen_lsp_server/examples/01_gen_lsp_server.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use std::error::Error;
-
-use crossbeam_channel::{Receiver, Sender};
-use gen_lsp_server::{handle_shutdown, run_server, stdio_transport, RawMessage, RawResponse};
-use lsp_types::{
-    request::{GotoDefinition, GotoDefinitionResponse},
-    InitializeParams, ServerCapabilities,
-};
-
-fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
-    let (receiver, sender, io_threads) = stdio_transport();
-    run_server(ServerCapabilities::default(), receiver, sender, main_loop)?;
-    io_threads.join()?;
-    Ok(())
-}
-
-fn main_loop(
-    _params: InitializeParams,
-    receiver: &Receiver<RawMessage>,
-    sender: &Sender<RawMessage>,
-) -> Result<(), Box<dyn Error + Sync + Send>> {
-    for msg in receiver {
-        match msg {
-            RawMessage::Request(req) => {
-                let req = match handle_shutdown(req, sender) {
-                    None => return Ok(()),
-                    Some(req) => req,
-                };
-                match req.cast::<GotoDefinition>() {
-                    Ok((id, _params)) => {
-                        let resp = RawResponse::ok::<GotoDefinition>(
-                            id,
-                            &Some(GotoDefinitionResponse::Array(Vec::new())),
-                        );
-                        sender.send(RawMessage::Response(resp))?;
-                        continue;
-                    }
-                    Err(req) => req,
-                };
-                // ...
-            }
-            RawMessage::Response(_resp) => (),
-            RawMessage::Notification(_not) => (),
-        }
-    }
-    Ok(())
-}
diff --git a/crates/gen_lsp_server/examples/02_gen_lsp_server_with_logging.rs b/crates/gen_lsp_server/examples/02_gen_lsp_server_with_logging.rs
deleted file mode 100644
index 3c48106c5f..0000000000
--- a/crates/gen_lsp_server/examples/02_gen_lsp_server_with_logging.rs
+++ /dev/null
@@ -1,120 +0,0 @@
-//! A minimal example LSP server that can only respond to the `gotoDefinition` request. To use
-//! this example, execute it and then send an `initialize` request.
-//!
-//! ```no_run
-//! Content-Length: 85
-//!
-//! {"jsonrpc": "2.0", "method": "initialize", "id": 1, "params": {"capabilities": {}}}
-//! ```
-//!
-//! This will respond with a server respose. Then send it a `initialized` notification which will
-//! have no response.
-//!
-//! ```no_run
-//! Content-Length: 59
-//!
-//! {"jsonrpc": "2.0", "method": "initialized", "params": {}}
-//! ```
-//!
-//! Once these two are sent, then we enter the main loop of the server. The only request this
-//! example can handle is `gotoDefinition`:
-//!
-//! ```no_run
-//! Content-Length: 159
-//!
-//! {"jsonrpc": "2.0", "method": "textDocument/definition", "id": 2, "params": {"textDocument": {"uri": "file://temp"}, "position": {"line": 1, "character": 1}}}
-//! ```
-//!
-//! To finish up without errors, send a shutdown request:
-//!
-//! ```no_run
-//! Content-Length: 67
-//!
-//! {"jsonrpc": "2.0", "method": "shutdown", "id": 3, "params": null}
-//! ```
-//!
-//! The server will exit the main loop and finally we send a `shutdown` notification to stop
-//! the server.
-//!
-//! ```
-//! Content-Length: 54
-//!
-//! {"jsonrpc": "2.0", "method": "exit", "params": null}
-//! ```
-
-use std::error::Error;
-
-use crossbeam_channel::{Receiver, Sender};
-use gen_lsp_server::{
-    handle_shutdown, run_server, stdio_transport, RawMessage, RawRequest, RawResponse,
-};
-use log::info;
-use lsp_types::{
-    request::{GotoDefinition, GotoDefinitionResponse},
-    InitializeParams, ServerCapabilities,
-};
-
-fn main() -> Result<(), Box<dyn Error + Sync + Send>> {
-    // Set up logging. Because `stdio_transport` gets a lock on stdout and stdin, we must have
-    // our logging only write out to stderr.
-    flexi_logger::Logger::with_str("info").start().unwrap();
-    info!("starting generic LSP server");
-
-    // Create the transport. Includes the stdio (stdin and stdout) versions but this could
-    // also be implemented to use sockets or HTTP.
-    let (receiver, sender, io_threads) = stdio_transport();
-
-    // Run the server and wait for the two threads to end (typically by trigger LSP Exit event).
-    run_server(ServerCapabilities::default(), receiver, sender, main_loop)?;
-    io_threads.join()?;
-
-    // Shut down gracefully.
-    info!("shutting down server");
-    Ok(())
-}
-
-fn main_loop(
-    _params: InitializeParams,
-    receiver: &Receiver<RawMessage>,
-    sender: &Sender<RawMessage>,
-) -> Result<(), Box<dyn Error + Sync + Send>> {
-    info!("starting example main loop");
-    for msg in receiver {
-        info!("got msg: {:?}", msg);
-        match msg {
-            RawMessage::Request(req) => {
-                let req = match log_handle_shutdown(req, sender) {
-                    None => return Ok(()),
-                    Some(req) => req,
-                };
-                info!("got request: {:?}", req);
-                match req.cast::<GotoDefinition>() {
-                    Ok((id, params)) => {
-                        info!("got gotoDefinition request #{}: {:?}", id, params);
-                        let resp = RawResponse::ok::<GotoDefinition>(
-                            id,
-                            &Some(GotoDefinitionResponse::Array(Vec::new())),
-                        );
-                        info!("sending gotoDefinition response: {:?}", resp);
-                        sender.send(RawMessage::Response(resp))?;
-                        continue;
-                    }
-                    Err(req) => req,
-                };
-                // ...
-            }
-            RawMessage::Response(resp) => {
-                info!("got response: {:?}", resp);
-            }
-            RawMessage::Notification(not) => {
-                info!("got notification: {:?}", not);
-            }
-        }
-    }
-    Ok(())
-}
-
-pub fn log_handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> {
-    info!("handle_shutdown: {:?}", req);
-    handle_shutdown(req, sender)
-}
diff --git a/crates/gen_lsp_server/src/lib.rs b/crates/gen_lsp_server/src/lib.rs
deleted file mode 100644
index 0984e3e25a..0000000000
--- a/crates/gen_lsp_server/src/lib.rs
+++ /dev/null
@@ -1,136 +0,0 @@
-//! A language server scaffold, exposing a synchronous crossbeam-channel based API.
-//! This crate handles protocol handshaking and parsing messages, while you
-//! control the message dispatch loop yourself.
-//!
-//! Run with `RUST_LOG=gen_lsp_server=debug` to see all the messages.
-//!
-//! ```no_run
-//! use std::error::Error;
-//! use crossbeam_channel::{Sender, Receiver};
-//! use lsp_types::{ServerCapabilities, InitializeParams, request::{GotoDefinition, GotoDefinitionResponse}};
-//! use gen_lsp_server::{run_server, stdio_transport, handle_shutdown, RawMessage, RawResponse};
-//!
-//! fn main() -> Result<(), Box<dyn Error + Send + Sync>> {
-//!     let (receiver, sender, io_threads) = stdio_transport();
-//!     run_server(
-//!         ServerCapabilities::default(),
-//!         receiver,
-//!         sender,
-//!         main_loop,
-//!     )?;
-//!     io_threads.join()?;
-//!     Ok(())
-//! }
-//!
-//! fn main_loop(
-//!     _params: InitializeParams,
-//!     receiver: &Receiver<RawMessage>,
-//!     sender: &Sender<RawMessage>,
-//! ) -> Result<(), Box<dyn Error + Send + Sync>> {
-//!     for msg in receiver {
-//!         match msg {
-//!             RawMessage::Request(req) => {
-//!                 let req = match handle_shutdown(req, sender) {
-//!                     None => return Ok(()),
-//!                     Some(req) => req,
-//!                 };
-//!                 match req.cast::<GotoDefinition>() {
-//!                     Ok((id, _params)) => {
-//!                         let resp = RawResponse::ok::<GotoDefinition>(
-//!                             id,
-//!                             &Some(GotoDefinitionResponse::Array(Vec::new())),
-//!                         );
-//!                         sender.send(RawMessage::Response(resp))?;
-//!                         continue;
-//!                     },
-//!                     Err(req) => req,
-//!                 };
-//!                 // ...
-//!             }
-//!             RawMessage::Response(_resp) => (),
-//!             RawMessage::Notification(_not) => (),
-//!         }
-//!     }
-//!     Ok(())
-//! }
-//! ```
-
-use std::error::Error;
-
-mod msg;
-mod stdio;
-
-use crossbeam_channel::{Receiver, Sender};
-use lsp_types::{
-    notification::{Exit, Initialized},
-    request::{Initialize, Shutdown},
-    InitializeParams, InitializeResult, ServerCapabilities,
-};
-
-pub type Result<T> = std::result::Result<T, Box<dyn Error + Send + Sync>>;
-pub use crate::{
-    msg::{ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse, RawResponseError},
-    stdio::{stdio_transport, Threads},
-};
-
-/// Main entry point: runs the server from initialization to shutdown.
-/// To attach server to standard input/output streams, use the `stdio_transport`
-/// function to create corresponding `sender` and `receiver` pair.
-///
-/// `server` should use the `handle_shutdown` function to handle the `Shutdown`
-/// request.
-pub fn run_server(
-    caps: ServerCapabilities,
-    receiver: Receiver<RawMessage>,
-    sender: Sender<RawMessage>,
-    server: impl FnOnce(InitializeParams, &Receiver<RawMessage>, &Sender<RawMessage>) -> Result<()>,
-) -> Result<()> {
-    log::info!("lsp server initializes");
-    let params = initialize(&receiver, &sender, caps)?;
-    log::info!("lsp server initialized, serving requests");
-    server(params, &receiver, &sender)?;
-    log::info!("lsp server waiting for exit notification");
-    match receiver.recv() {
-        Ok(RawMessage::Notification(n)) => n
-            .cast::<Exit>()
-            .map_err(|n| format!("unexpected notification during shutdown: {:?}", n))?,
-        m => Err(format!("unexpected message during shutdown: {:?}", m))?,
-    }
-    log::info!("lsp server shutdown complete");
-    Ok(())
-}
-
-/// If `req` is `Shutdown`, respond to it and return `None`, otherwise return `Some(req)`
-pub fn handle_shutdown(req: RawRequest, sender: &Sender<RawMessage>) -> Option<RawRequest> {
-    match req.cast::<Shutdown>() {
-        Ok((id, ())) => {
-            let resp = RawResponse::ok::<Shutdown>(id, &());
-            let _ = sender.send(RawMessage::Response(resp));
-            None
-        }
-        Err(req) => Some(req),
-    }
-}
-
-fn initialize(
-    receiver: &Receiver<RawMessage>,
-    sender: &Sender<RawMessage>,
-    caps: ServerCapabilities,
-) -> Result<InitializeParams> {
-    let (id, params) = match receiver.recv() {
-        Ok(RawMessage::Request(req)) => match req.cast::<Initialize>() {
-            Err(req) => Err(format!("expected initialize request, got {:?}", req))?,
-            Ok(req) => req,
-        },
-        msg => Err(format!("expected initialize request, got {:?}", msg))?,
-    };
-    let resp = RawResponse::ok::<Initialize>(id, &InitializeResult { capabilities: caps });
-    sender.send(RawMessage::Response(resp)).unwrap();
-    match receiver.recv() {
-        Ok(RawMessage::Notification(n)) => {
-            n.cast::<Initialized>().map_err(|_| "expected initialized notification")?;
-        }
-        _ => Err("expected initialized notification".to_string())?,
-    }
-    Ok(params)
-}
diff --git a/crates/gen_lsp_server/src/msg.rs b/crates/gen_lsp_server/src/msg.rs
deleted file mode 100644
index 2928e4f8bd..0000000000
--- a/crates/gen_lsp_server/src/msg.rs
+++ /dev/null
@@ -1,205 +0,0 @@
-use std::io::{BufRead, Write};
-
-use lsp_types::{notification::Notification, request::Request};
-use serde::{Deserialize, Serialize};
-use serde_json::{from_str, from_value, to_string, to_value, Value};
-
-use crate::Result;
-
-#[derive(Serialize, Deserialize, Debug, Clone)]
-#[serde(untagged)]
-pub enum RawMessage {
-    Request(RawRequest),
-    Notification(RawNotification),
-    Response(RawResponse),
-}
-
-impl From<RawRequest> for RawMessage {
-    fn from(raw: RawRequest) -> RawMessage {
-        RawMessage::Request(raw)
-    }
-}
-
-impl From<RawNotification> for RawMessage {
-    fn from(raw: RawNotification) -> RawMessage {
-        RawMessage::Notification(raw)
-    }
-}
-
-impl From<RawResponse> for RawMessage {
-    fn from(raw: RawResponse) -> RawMessage {
-        RawMessage::Response(raw)
-    }
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct RawRequest {
-    pub id: u64,
-    pub method: String,
-    pub params: Value,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct RawResponse {
-    // JSON RPC allows this to be null if it was impossible
-    // to decode the request's id. Ignore this special case
-    // and just die horribly.
-    pub id: u64,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub result: Option<Value>,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub error: Option<RawResponseError>,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct RawResponseError {
-    pub code: i32,
-    pub message: String,
-    #[serde(skip_serializing_if = "Option::is_none")]
-    pub data: Option<Value>,
-}
-
-#[derive(Clone, Copy, Debug)]
-#[allow(unused)]
-pub enum ErrorCode {
-    ParseError = -32700,
-    InvalidRequest = -32600,
-    MethodNotFound = -32601,
-    InvalidParams = -32602,
-    InternalError = -32603,
-    ServerErrorStart = -32099,
-    ServerErrorEnd = -32000,
-    ServerNotInitialized = -32002,
-    UnknownErrorCode = -32001,
-    RequestCanceled = -32800,
-    ContentModified = -32801,
-}
-
-#[derive(Debug, Serialize, Deserialize, Clone)]
-pub struct RawNotification {
-    pub method: String,
-    pub params: Value,
-}
-
-impl RawMessage {
-    pub fn read(r: &mut impl BufRead) -> Result<Option<RawMessage>> {
-        let text = match read_msg_text(r)? {
-            None => return Ok(None),
-            Some(text) => text,
-        };
-        let msg = from_str(&text)?;
-        Ok(Some(msg))
-    }
-    pub fn write(self, w: &mut impl Write) -> Result<()> {
-        #[derive(Serialize)]
-        struct JsonRpc {
-            jsonrpc: &'static str,
-            #[serde(flatten)]
-            msg: RawMessage,
-        }
-        let text = to_string(&JsonRpc { jsonrpc: "2.0", msg: self })?;
-        write_msg_text(w, &text)?;
-        Ok(())
-    }
-}
-
-impl RawRequest {
-    pub fn new<R>(id: u64, params: &R::Params) -> RawRequest
-    where
-        R: Request,
-        R::Params: serde::Serialize,
-    {
-        RawRequest { id, method: R::METHOD.to_string(), params: to_value(params).unwrap() }
-    }
-    pub fn cast<R>(self) -> ::std::result::Result<(u64, R::Params), RawRequest>
-    where
-        R: Request,
-        R::Params: serde::de::DeserializeOwned,
-    {
-        if self.method != R::METHOD {
-            return Err(self);
-        }
-        let id = self.id;
-        let params: R::Params = from_value(self.params).unwrap();
-        Ok((id, params))
-    }
-}
-
-impl RawResponse {
-    pub fn ok<R>(id: u64, result: &R::Result) -> RawResponse
-    where
-        R: Request,
-        R::Result: serde::Serialize,
-    {
-        RawResponse { id, result: Some(to_value(&result).unwrap()), error: None }
-    }
-    pub fn err(id: u64, code: i32, message: String) -> RawResponse {
-        let error = RawResponseError { code, message, data: None };
-        RawResponse { id, result: None, error: Some(error) }
-    }
-}
-
-impl RawNotification {
-    pub fn new<N>(params: &N::Params) -> RawNotification
-    where
-        N: Notification,
-        N::Params: serde::Serialize,
-    {
-        RawNotification { method: N::METHOD.to_string(), params: to_value(params).unwrap() }
-    }
-    pub fn is<N>(&self) -> bool
-    where
-        N: Notification,
-    {
-        self.method == N::METHOD
-    }
-    pub fn cast<N>(self) -> ::std::result::Result<N::Params, RawNotification>
-    where
-        N: Notification,
-        N::Params: serde::de::DeserializeOwned,
-    {
-        if !self.is::<N>() {
-            return Err(self);
-        }
-        Ok(from_value(self.params).unwrap())
-    }
-}
-
-fn read_msg_text(inp: &mut impl BufRead) -> Result<Option<String>> {
-    let mut size = None;
-    let mut buf = String::new();
-    loop {
-        buf.clear();
-        if inp.read_line(&mut buf)? == 0 {
-            return Ok(None);
-        }
-        if !buf.ends_with("\r\n") {
-            Err(format!("malformed header: {:?}", buf))?;
-        }
-        let buf = &buf[..buf.len() - 2];
-        if buf.is_empty() {
-            break;
-        }
-        let mut parts = buf.splitn(2, ": ");
-        let header_name = parts.next().unwrap();
-        let header_value = parts.next().ok_or_else(|| format!("malformed header: {:?}", buf))?;
-        if header_name == "Content-Length" {
-            size = Some(header_value.parse::<usize>()?);
-        }
-    }
-    let size = size.ok_or("no Content-Length")?;
-    let mut buf = buf.into_bytes();
-    buf.resize(size, 0);
-    inp.read_exact(&mut buf)?;
-    let buf = String::from_utf8(buf)?;
-    log::debug!("< {}", buf);
-    Ok(Some(buf))
-}
-
-fn write_msg_text(out: &mut impl Write, msg: &str) -> Result<()> {
-    log::debug!("> {}", msg);
-    write!(out, "Content-Length: {}\r\n\r\n", msg.len())?;
-    out.write_all(msg.as_bytes())?;
-    out.flush()?;
-    Ok(())
-}
diff --git a/crates/gen_lsp_server/src/stdio.rs b/crates/gen_lsp_server/src/stdio.rs
deleted file mode 100644
index f8931f2dce..0000000000
--- a/crates/gen_lsp_server/src/stdio.rs
+++ /dev/null
@@ -1,57 +0,0 @@
-use std::{
-    io::{stdin, stdout},
-    thread,
-};
-
-use crossbeam_channel::{bounded, Receiver, Sender};
-use lsp_types::notification::Exit;
-
-use crate::{RawMessage, Result};
-
-pub fn stdio_transport() -> (Receiver<RawMessage>, Sender<RawMessage>, Threads) {
-    let (writer_sender, writer_receiver) = bounded::<RawMessage>(16);
-    let writer = thread::spawn(move || {
-        let stdout = stdout();
-        let mut stdout = stdout.lock();
-        writer_receiver.into_iter().try_for_each(|it| it.write(&mut stdout))?;
-        Ok(())
-    });
-    let (reader_sender, reader_receiver) = bounded::<RawMessage>(16);
-    let reader = thread::spawn(move || {
-        let stdin = stdin();
-        let mut stdin = stdin.lock();
-        while let Some(msg) = RawMessage::read(&mut stdin)? {
-            let is_exit = match &msg {
-                RawMessage::Notification(n) => n.is::<Exit>(),
-                _ => false,
-            };
-
-            reader_sender.send(msg).unwrap();
-
-            if is_exit {
-                break;
-            }
-        }
-        Ok(())
-    });
-    let threads = Threads { reader, writer };
-    (reader_receiver, writer_sender, threads)
-}
-
-pub struct Threads {
-    reader: thread::JoinHandle<Result<()>>,
-    writer: thread::JoinHandle<Result<()>>,
-}
-
-impl Threads {
-    pub fn join(self) -> Result<()> {
-        match self.reader.join() {
-            Ok(r) => r?,
-            Err(_) => Err("reader panicked")?,
-        }
-        match self.writer.join() {
-            Ok(r) => r,
-            Err(_) => Err("writer panicked")?,
-        }
-    }
-}
diff --git a/crates/ra_lsp_server/Cargo.toml b/crates/ra_lsp_server/Cargo.toml
index e271c257bc..084a20cd98 100644
--- a/crates/ra_lsp_server/Cargo.toml
+++ b/crates/ra_lsp_server/Cargo.toml
@@ -21,7 +21,7 @@ thread_worker = { path = "../thread_worker" }
 ra_syntax = { path = "../ra_syntax" }
 ra_text_edit = { path = "../ra_text_edit" }
 ra_ide_api = { path = "../ra_ide_api" }
-gen_lsp_server = { path = "../gen_lsp_server" }
+lsp-server = "0.1.0"
 ra_project_model = { path = "../ra_project_model" }
 ra_prof = { path = "../ra_prof" }
 ra_vfs_glob = { path = "../ra_vfs_glob" }
diff --git a/crates/ra_lsp_server/src/main.rs b/crates/ra_lsp_server/src/main.rs
index ae1392cb5d..1debe76608 100644
--- a/crates/ra_lsp_server/src/main.rs
+++ b/crates/ra_lsp_server/src/main.rs
@@ -1,5 +1,5 @@
 use flexi_logger::{Duplicate, Logger};
-use gen_lsp_server::{run_server, stdio_transport};
+use lsp_server::{run_server, stdio_transport, LspServerError};
 
 use ra_lsp_server::{show_message, Result, ServerConfig};
 use ra_prof;
@@ -29,9 +29,11 @@ fn main() -> Result<()> {
 }
 
 fn main_inner() -> Result<()> {
-    let (receiver, sender, threads) = stdio_transport();
+    let (sender, receiver, io_threads) = stdio_transport();
     let cwd = std::env::current_dir()?;
-    run_server(ra_lsp_server::server_capabilities(), receiver, sender, |params, r, s| {
+    let caps = serde_json::to_value(ra_lsp_server::server_capabilities()).unwrap();
+    run_server(caps, sender, receiver, |params, s, r| {
+        let params: lsp_types::InitializeParams = serde_json::from_value(params)?;
         let root = params.root_uri.and_then(|it| it.to_file_path().ok()).unwrap_or(cwd);
 
         let workspace_roots = params
@@ -62,9 +64,13 @@ fn main_inner() -> Result<()> {
             .unwrap_or_default();
 
         ra_lsp_server::main_loop(workspace_roots, params.capabilities, server_config, r, s)
+    })
+    .map_err(|err| match err {
+        LspServerError::ProtocolError(err) => err.into(),
+        LspServerError::ServerError(err) => err,
     })?;
     log::info!("shutting down IO...");
-    threads.join()?;
+    io_threads.join()?;
     log::info!("... IO is down");
     Ok(())
 }
diff --git a/crates/ra_lsp_server/src/main_loop.rs b/crates/ra_lsp_server/src/main_loop.rs
index 45bd52769b..fb357b36bb 100644
--- a/crates/ra_lsp_server/src/main_loop.rs
+++ b/crates/ra_lsp_server/src/main_loop.rs
@@ -5,9 +5,7 @@ pub(crate) mod pending_requests;
 use std::{error::Error, fmt, path::PathBuf, sync::Arc, time::Instant};
 
 use crossbeam_channel::{select, unbounded, Receiver, RecvError, Sender};
-use gen_lsp_server::{
-    handle_shutdown, ErrorCode, RawMessage, RawNotification, RawRequest, RawResponse,
-};
+use lsp_server::{handle_shutdown, ErrorCode, Message, Notification, Request, RequestId, Response};
 use lsp_types::{ClientCapabilities, NumberOrString};
 use ra_ide_api::{Canceled, FeatureFlags, FileId, LibraryData};
 use ra_prof::profile;
@@ -53,8 +51,8 @@ pub fn main_loop(
     ws_roots: Vec<PathBuf>,
     client_caps: ClientCapabilities,
     config: ServerConfig,
-    msg_receiver: &Receiver<RawMessage>,
-    msg_sender: &Sender<RawMessage>,
+    msg_receiver: &Receiver<Message>,
+    msg_sender: &Sender<Message>,
 ) -> Result<()> {
     log::info!("server_config: {:#?}", config);
     // FIXME: support dynamic workspace loading.
@@ -146,12 +144,12 @@ pub fn main_loop(
 
 #[derive(Debug)]
 enum Task {
-    Respond(RawResponse),
-    Notify(RawNotification),
+    Respond(Response),
+    Notify(Notification),
 }
 
 enum Event {
-    Msg(RawMessage),
+    Msg(Message),
     Task(Task),
     Vfs(VfsTask),
     Lib(LibraryData),
@@ -159,24 +157,28 @@ enum Event {
 
 impl fmt::Debug for Event {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        let debug_verbose_not = |not: &RawNotification, f: &mut fmt::Formatter| {
-            f.debug_struct("RawNotification").field("method", &not.method).finish()
+        let debug_verbose_not = |not: &Notification, f: &mut fmt::Formatter| {
+            f.debug_struct("Notification").field("method", &not.method).finish()
         };
 
         match self {
-            Event::Msg(RawMessage::Notification(not)) => {
-                if not.is::<req::DidOpenTextDocument>() || not.is::<req::DidChangeTextDocument>() {
+            Event::Msg(Message::Notification(not)) => {
+                if notification_is::<req::DidOpenTextDocument>(not)
+                    || notification_is::<req::DidChangeTextDocument>(not)
+                {
                     return debug_verbose_not(not, f);
                 }
             }
             Event::Task(Task::Notify(not)) => {
-                if not.is::<req::PublishDecorations>() || not.is::<req::PublishDiagnostics>() {
+                if notification_is::<req::PublishDecorations>(not)
+                    || notification_is::<req::PublishDiagnostics>(not)
+                {
                     return debug_verbose_not(not, f);
                 }
             }
             Event::Task(Task::Respond(resp)) => {
                 return f
-                    .debug_struct("RawResponse")
+                    .debug_struct("Response")
                     .field("id", &resp.id)
                     .field("error", &resp.error)
                     .finish();
@@ -194,8 +196,8 @@ impl fmt::Debug for Event {
 
 fn main_loop_inner(
     pool: &ThreadPool,
-    msg_sender: &Sender<RawMessage>,
-    msg_receiver: &Receiver<RawMessage>,
+    msg_sender: &Sender<Message>,
+    msg_receiver: &Receiver<Message>,
     task_sender: Sender<Task>,
     task_receiver: Receiver<Task>,
     state: &mut WorldState,
@@ -249,10 +251,9 @@ fn main_loop_inner(
                 in_flight_libraries -= 1;
             }
             Event::Msg(msg) => match msg {
-                RawMessage::Request(req) => {
-                    let req = match handle_shutdown(req, msg_sender) {
-                        Some(req) => req,
-                        None => return Ok(()),
+                Message::Request(req) => {
+                    if handle_shutdown(&req, msg_sender) {
+                        return Ok(());
                     };
                     on_request(
                         state,
@@ -264,11 +265,11 @@ fn main_loop_inner(
                         req,
                     )?
                 }
-                RawMessage::Notification(not) => {
+                Message::Notification(not) => {
                     on_notification(msg_sender, state, pending_requests, &mut subs, not)?;
                     state_changed = true;
                 }
-                RawMessage::Response(resp) => log::error!("unexpected response: {:?}", resp),
+                Message::Response(resp) => log::error!("unexpected response: {:?}", resp),
             },
         };
 
@@ -313,13 +314,13 @@ fn main_loop_inner(
 
 fn on_task(
     task: Task,
-    msg_sender: &Sender<RawMessage>,
+    msg_sender: &Sender<Message>,
     pending_requests: &mut PendingRequests,
     state: &mut WorldState,
 ) {
     match task {
         Task::Respond(response) => {
-            if let Some(completed) = pending_requests.finish(response.id) {
+            if let Some(completed) = pending_requests.finish(&response.id) {
                 log::info!("handled req#{} in {:?}", completed.id, completed.duration);
                 state.complete_request(completed);
                 msg_sender.send(response.into()).unwrap();
@@ -336,9 +337,9 @@ fn on_request(
     pending_requests: &mut PendingRequests,
     pool: &ThreadPool,
     sender: &Sender<Task>,
-    msg_sender: &Sender<RawMessage>,
+    msg_sender: &Sender<Message>,
     request_received: Instant,
-    req: RawRequest,
+    req: Request,
 ) -> Result<()> {
     let mut pool_dispatcher = PoolDispatcher {
         req: Some(req),
@@ -388,22 +389,20 @@ fn on_request(
 }
 
 fn on_notification(
-    msg_sender: &Sender<RawMessage>,
+    msg_sender: &Sender<Message>,
     state: &mut WorldState,
     pending_requests: &mut PendingRequests,
     subs: &mut Subscriptions,
-    not: RawNotification,
+    not: Notification,
 ) -> Result<()> {
-    let not = match not.cast::<req::Cancel>() {
+    let not = match notification_cast::<req::Cancel>(not) {
         Ok(params) => {
-            let id = match params.id {
-                NumberOrString::Number(id) => id,
-                NumberOrString::String(id) => {
-                    panic!("string id's not supported: {:?}", id);
-                }
+            let id: RequestId = match params.id {
+                NumberOrString::Number(id) => id.into(),
+                NumberOrString::String(id) => id.into(),
             };
-            if pending_requests.cancel(id) {
-                let response = RawResponse::err(
+            if pending_requests.cancel(&id) {
+                let response = Response::new_err(
                     id,
                     ErrorCode::RequestCanceled as i32,
                     "canceled by client".to_string(),
@@ -414,7 +413,7 @@ fn on_notification(
         }
         Err(not) => not,
     };
-    let not = match not.cast::<req::DidOpenTextDocument>() {
+    let not = match notification_cast::<req::DidOpenTextDocument>(not) {
         Ok(params) => {
             let uri = params.text_document.uri;
             let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -427,7 +426,7 @@ fn on_notification(
         }
         Err(not) => not,
     };
-    let not = match not.cast::<req::DidChangeTextDocument>() {
+    let not = match notification_cast::<req::DidChangeTextDocument>(not) {
         Ok(mut params) => {
             let uri = params.text_document.uri;
             let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -438,7 +437,7 @@ fn on_notification(
         }
         Err(not) => not,
     };
-    let not = match not.cast::<req::DidCloseTextDocument>() {
+    let not = match notification_cast::<req::DidCloseTextDocument>(not) {
         Ok(params) => {
             let uri = params.text_document.uri;
             let path = uri.to_file_path().map_err(|()| format!("invalid uri: {}", uri))?;
@@ -446,13 +445,13 @@ fn on_notification(
                 subs.remove_sub(FileId(file_id.0));
             }
             let params = req::PublishDiagnosticsParams { uri, diagnostics: Vec::new() };
-            let not = RawNotification::new::<req::PublishDiagnostics>(&params);
+            let not = notification_new::<req::PublishDiagnostics>(params);
             msg_sender.send(not.into()).unwrap();
             return Ok(());
         }
         Err(not) => not,
     };
-    let not = match not.cast::<req::DidChangeConfiguration>() {
+    let not = match notification_cast::<req::DidChangeConfiguration>(not) {
         Ok(_params) => {
             return Ok(());
         }
@@ -463,11 +462,11 @@ fn on_notification(
 }
 
 struct PoolDispatcher<'a> {
-    req: Option<RawRequest>,
+    req: Option<Request>,
     pool: &'a ThreadPool,
     world: &'a mut WorldState,
     pending_requests: &'a mut PendingRequests,
-    msg_sender: &'a Sender<RawMessage>,
+    msg_sender: &'a Sender<Message>,
     sender: &'a Sender<Task>,
     request_received: Instant,
 }
@@ -522,13 +521,13 @@ impl<'a> PoolDispatcher<'a> {
         Ok(self)
     }
 
-    fn parse<R>(&mut self) -> Option<(u64, R::Params)>
+    fn parse<R>(&mut self) -> Option<(RequestId, R::Params)>
     where
         R: req::Request + 'static,
         R::Params: DeserializeOwned + Send + 'static,
     {
         let req = self.req.take()?;
-        let (id, params) = match req.cast::<R>() {
+        let (id, params) = match req.extract::<R::Params>(R::METHOD) {
             Ok(it) => it,
             Err(req) => {
                 self.req = Some(req);
@@ -536,7 +535,7 @@ impl<'a> PoolDispatcher<'a> {
             }
         };
         self.pending_requests.start(PendingRequest {
-            id,
+            id: id.clone(),
             method: R::METHOD.to_string(),
             received: self.request_received,
         });
@@ -548,7 +547,7 @@ impl<'a> PoolDispatcher<'a> {
             None => (),
             Some(req) => {
                 log::error!("unknown request: {:?}", req);
-                let resp = RawResponse::err(
+                let resp = Response::new_err(
                     req.id,
                     ErrorCode::MethodNotFound as i32,
                     "unknown request".to_string(),
@@ -559,34 +558,30 @@ impl<'a> PoolDispatcher<'a> {
     }
 }
 
-fn result_to_task<R>(id: u64, result: Result<R::Result>) -> Task
+fn result_to_task<R>(id: RequestId, result: Result<R::Result>) -> Task
 where
     R: req::Request + 'static,
     R::Params: DeserializeOwned + Send + 'static,
     R::Result: Serialize + 'static,
 {
     let response = match result {
-        Ok(resp) => RawResponse::ok::<R>(id, &resp),
+        Ok(resp) => Response::new_ok(id, &resp),
         Err(e) => match e.downcast::<LspError>() {
-            Ok(lsp_error) => RawResponse::err(id, lsp_error.code, lsp_error.message),
+            Ok(lsp_error) => Response::new_err(id, lsp_error.code, lsp_error.message),
             Err(e) => {
                 if is_canceled(&e) {
                     // FIXME: When https://github.com/Microsoft/vscode-languageserver-node/issues/457
                     // gets fixed, we can return the proper response.
                     // This works around the issue where "content modified" error would continuously
                     // show an message pop-up in VsCode
-                    // RawResponse::err(
+                    // Response::err(
                     //     id,
                     //     ErrorCode::ContentModified as i32,
                     //     "content modified".to_string(),
                     // )
-                    RawResponse {
-                        id,
-                        result: Some(serde_json::to_value(&()).unwrap()),
-                        error: None,
-                    }
+                    Response::new_ok(id, ())
                 } else {
-                    RawResponse::err(id, ErrorCode::InternalError as i32, e.to_string())
+                    Response::new_err(id, ErrorCode::InternalError as i32, e.to_string())
                 }
             }
         },
@@ -613,7 +608,7 @@ fn update_file_notifications_on_threadpool(
                         }
                     }
                     Ok(params) => {
-                        let not = RawNotification::new::<req::PublishDiagnostics>(&params);
+                        let not = notification_new::<req::PublishDiagnostics>(params);
                         sender.send(Task::Notify(not)).unwrap();
                     }
                 }
@@ -626,7 +621,7 @@ fn update_file_notifications_on_threadpool(
                         }
                     }
                     Ok(params) => {
-                        let not = RawNotification::new::<req::PublishDecorations>(&params);
+                        let not = notification_new::<req::PublishDecorations>(params);
                         sender.send(Task::Notify(not)).unwrap();
                     }
                 }
@@ -635,17 +630,33 @@ fn update_file_notifications_on_threadpool(
     });
 }
 
-pub fn show_message(
-    typ: req::MessageType,
-    message: impl Into<String>,
-    sender: &Sender<RawMessage>,
-) {
+pub fn show_message(typ: req::MessageType, message: impl Into<String>, sender: &Sender<Message>) {
     let message = message.into();
     let params = req::ShowMessageParams { typ, message };
-    let not = RawNotification::new::<req::ShowMessage>(&params);
+    let not = notification_new::<req::ShowMessage>(params);
     sender.send(not.into()).unwrap();
 }
 
 fn is_canceled(e: &Box<dyn std::error::Error + Send + Sync>) -> bool {
     e.downcast_ref::<Canceled>().is_some()
 }
+
+fn notification_is<N: lsp_types::notification::Notification>(notification: &Notification) -> bool {
+    notification.method == N::METHOD
+}
+
+fn notification_cast<N>(notification: Notification) -> std::result::Result<N::Params, Notification>
+where
+    N: lsp_types::notification::Notification,
+    N::Params: DeserializeOwned,
+{
+    notification.extract(N::METHOD)
+}
+
+fn notification_new<N>(params: N::Params) -> Notification
+where
+    N: lsp_types::notification::Notification,
+    N::Params: Serialize,
+{
+    Notification::new(N::METHOD.to_string(), params)
+}
diff --git a/crates/ra_lsp_server/src/main_loop/handlers.rs b/crates/ra_lsp_server/src/main_loop/handlers.rs
index 3a559e845d..eb805a6d39 100644
--- a/crates/ra_lsp_server/src/main_loop/handlers.rs
+++ b/crates/ra_lsp_server/src/main_loop/handlers.rs
@@ -1,6 +1,6 @@
 use std::{fmt::Write as _, io::Write as _};
 
-use gen_lsp_server::ErrorCode;
+use lsp_server::ErrorCode;
 use lsp_types::{
     CodeAction, CodeActionResponse, CodeLens, Command, CompletionItem, Diagnostic,
     DocumentFormattingParams, DocumentHighlight, DocumentSymbol, FoldingRange, FoldingRangeKind,
diff --git a/crates/ra_lsp_server/src/main_loop/pending_requests.rs b/crates/ra_lsp_server/src/main_loop/pending_requests.rs
index 741770e456..7a99fc6799 100644
--- a/crates/ra_lsp_server/src/main_loop/pending_requests.rs
+++ b/crates/ra_lsp_server/src/main_loop/pending_requests.rs
@@ -1,17 +1,18 @@
 use std::time::{Duration, Instant};
 
+use lsp_server::RequestId;
 use rustc_hash::FxHashMap;
 
 #[derive(Debug)]
 pub struct CompletedRequest {
-    pub id: u64,
+    pub id: RequestId,
     pub method: String,
     pub duration: Duration,
 }
 
 #[derive(Debug)]
 pub(crate) struct PendingRequest {
-    pub(crate) id: u64,
+    pub(crate) id: RequestId,
     pub(crate) method: String,
     pub(crate) received: Instant,
 }
@@ -28,20 +29,20 @@ impl From<PendingRequest> for CompletedRequest {
 
 #[derive(Debug, Default)]
 pub(crate) struct PendingRequests {
-    map: FxHashMap<u64, PendingRequest>,
+    map: FxHashMap<RequestId, PendingRequest>,
 }
 
 impl PendingRequests {
     pub(crate) fn start(&mut self, request: PendingRequest) {
-        let id = request.id;
-        let prev = self.map.insert(id, request);
+        let id = request.id.clone();
+        let prev = self.map.insert(id.clone(), request);
         assert!(prev.is_none(), "duplicate request with id {}", id);
     }
-    pub(crate) fn cancel(&mut self, id: u64) -> bool {
-        self.map.remove(&id).is_some()
+    pub(crate) fn cancel(&mut self, id: &RequestId) -> bool {
+        self.map.remove(id).is_some()
     }
-    pub(crate) fn finish(&mut self, id: u64) -> Option<CompletedRequest> {
-        self.map.remove(&id).map(CompletedRequest::from)
+    pub(crate) fn finish(&mut self, id: &RequestId) -> Option<CompletedRequest> {
+        self.map.remove(id).map(CompletedRequest::from)
     }
 }
 
diff --git a/crates/ra_lsp_server/src/world.rs b/crates/ra_lsp_server/src/world.rs
index cc79644698..73d7f8fb9b 100644
--- a/crates/ra_lsp_server/src/world.rs
+++ b/crates/ra_lsp_server/src/world.rs
@@ -4,7 +4,7 @@ use std::{
 };
 
 use crossbeam_channel::{unbounded, Receiver};
-use gen_lsp_server::ErrorCode;
+use lsp_server::ErrorCode;
 use lsp_types::Url;
 use parking_lot::RwLock;
 use ra_ide_api::{


Test patch:
diff --git a/crates/ra_lsp_server/tests/heavy_tests/support.rs b/crates/ra_lsp_server/tests/heavy_tests/support.rs
index 055c8fff22..45b4cacf6a 100644
--- a/crates/ra_lsp_server/tests/heavy_tests/support.rs
+++ b/crates/ra_lsp_server/tests/heavy_tests/support.rs
@@ -8,13 +8,10 @@ use std::{
 
 use crossbeam_channel::{after, select, Receiver};
 use flexi_logger::Logger;
-use gen_lsp_server::{RawMessage, RawNotification, RawRequest};
+use lsp_server::{Message, Notification, Request};
 use lsp_types::{
-    notification::DidOpenTextDocument,
-    notification::{Notification, ShowMessage},
-    request::{Request, Shutdown},
-    ClientCapabilities, DidOpenTextDocumentParams, GotoCapability, TextDocumentClientCapabilities,
-    TextDocumentIdentifier, TextDocumentItem, Url,
+    request::Shutdown, ClientCapabilities, DidOpenTextDocumentParams, GotoCapability,
+    TextDocumentClientCapabilities, TextDocumentIdentifier, TextDocumentItem, Url,
 };
 use serde::Serialize;
 use serde_json::{to_string_pretty, Value};
@@ -84,9 +81,9 @@ pub fn project(fixture: &str) -> Server {
 
 pub struct Server {
     req_id: Cell<u64>,
-    messages: RefCell<Vec<RawMessage>>,
+    messages: RefCell<Vec<Message>>,
     dir: TempDir,
-    worker: Worker<RawMessage, RawMessage>,
+    worker: Worker<Message, Message>,
 }
 
 impl Server {
@@ -100,7 +97,7 @@ impl Server {
 
         let roots = if roots.is_empty() { vec![path] } else { roots };
 
-        let worker = Worker::<RawMessage, RawMessage>::spawn(
+        let worker = Worker::<Message, Message>::spawn(
             "test server",
             128,
             move |msg_receiver, msg_sender| {
@@ -128,7 +125,8 @@ impl Server {
         let res = Server { req_id: Cell::new(1), dir, messages: Default::default(), worker };
 
         for (path, text) in files {
-            res.send_notification(RawNotification::new::<DidOpenTextDocument>(
+            res.send_notification(Notification::new(
+                "textDocument/didOpen".to_string(),
                 &DidOpenTextDocumentParams {
                     text_document: TextDocumentItem {
                         uri: Url::from_file_path(path).unwrap(),
@@ -149,16 +147,16 @@ impl Server {
 
     pub fn notification<N>(&self, params: N::Params)
     where
-        N: Notification,
+        N: lsp_types::notification::Notification,
         N::Params: Serialize,
     {
-        let r = RawNotification::new::<N>(&params);
+        let r = Notification::new(N::METHOD.to_string(), params);
         self.send_notification(r)
     }
 
     pub fn request<R>(&self, params: R::Params, expected_resp: Value)
     where
-        R: Request,
+        R: lsp_types::request::Request,
         R::Params: Serialize,
     {
         let actual = self.send_request::<R>(params);
@@ -175,23 +173,23 @@ impl Server {
 
     pub fn send_request<R>(&self, params: R::Params) -> Value
     where
-        R: Request,
+        R: lsp_types::request::Request,
         R::Params: Serialize,
     {
         let id = self.req_id.get();
         self.req_id.set(id + 1);
 
-        let r = RawRequest::new::<R>(id, &params);
+        let r = Request::new(id.into(), R::METHOD.to_string(), params);
         self.send_request_(r)
     }
-    fn send_request_(&self, r: RawRequest) -> Value {
-        let id = r.id;
-        self.worker.sender().send(RawMessage::Request(r)).unwrap();
+    fn send_request_(&self, r: Request) -> Value {
+        let id = r.id.clone();
+        self.worker.sender().send(r.into()).unwrap();
         while let Some(msg) = self.recv() {
             match msg {
-                RawMessage::Request(req) => panic!("unexpected request: {:?}", req),
-                RawMessage::Notification(_) => (),
-                RawMessage::Response(res) => {
+                Message::Request(req) => panic!("unexpected request: {:?}", req),
+                Message::Notification(_) => (),
+                Message::Response(res) => {
                     assert_eq!(res.id, id);
                     if let Some(err) = res.error {
                         panic!("error response: {:#?}", err);
@@ -203,15 +201,16 @@ impl Server {
         panic!("no response");
     }
     pub fn wait_until_workspace_is_loaded(&self) {
-        self.wait_for_message_cond(1, &|msg: &RawMessage| match msg {
-            RawMessage::Notification(n) if n.method == ShowMessage::METHOD => {
-                let msg = n.clone().cast::<req::ShowMessage>().unwrap();
+        self.wait_for_message_cond(1, &|msg: &Message| match msg {
+            Message::Notification(n) if n.method == "window/showMessage" => {
+                let msg =
+                    n.clone().extract::<req::ShowMessageParams>("window/showMessage").unwrap();
                 msg.message.starts_with("workspace loaded")
             }
             _ => false,
         })
     }
-    fn wait_for_message_cond(&self, n: usize, cond: &dyn Fn(&RawMessage) -> bool) {
+    fn wait_for_message_cond(&self, n: usize, cond: &dyn Fn(&Message) -> bool) {
         let mut total = 0;
         for msg in self.messages.borrow().iter() {
             if cond(msg) {
@@ -225,14 +224,14 @@ impl Server {
             }
         }
     }
-    fn recv(&self) -> Option<RawMessage> {
+    fn recv(&self) -> Option<Message> {
         recv_timeout(&self.worker.receiver()).map(|msg| {
             self.messages.borrow_mut().push(msg.clone());
             msg
         })
     }
-    fn send_notification(&self, not: RawNotification) {
-        self.worker.sender().send(RawMessage::Notification(not)).unwrap();
+    fn send_notification(&self, not: Notification) {
+        self.worker.sender().send(Message::Notification(not)).unwrap();
     }
 
     pub fn path(&self) -> &Path {
@@ -246,7 +245,7 @@ impl Drop for Server {
     }
 }
 
-fn recv_timeout(receiver: &Receiver<RawMessage>) -> Option<RawMessage> {
+fn recv_timeout(receiver: &Receiver<Message>) -> Option<Message> {
     let timeout = Duration::from_secs(120);
     select! {
         recv(receiver) -> msg => msg.ok(),