pub fn start(
    to_editor: Sender<EditorResponse>,
    from_editor: Receiver<EditorRequest>,
    route: &Route,
    initial_request: EditorRequest,
    config: Config,
) {
    let lang_srv: language_server_transport::LanguageServerTransport;
    let options;
    let offset_encoding;
    {
        // should be fine to unwrap because request was already routed which means language is configured
        let lang = &config.language[&route.language];
        options = lang.initialization_options.clone();
        offset_encoding = lang.offset_encoding.clone();
        lang_srv = language_server_transport::start(&lang.command, &lang.args);
    }

    let initial_request_meta = initial_request.meta.clone();

    let mut ctx = Context::new(
        &route.language,
        initial_request,
        lang_srv.to_lang_server.sender().clone(),
        to_editor,
        config,
        route.root.clone(),
        offset_encoding,
    );

    general::initialize(&route.root, options, initial_request_meta, &mut ctx);

    'event_loop: loop {
        select! {
            recv(from_editor) -> msg => {
                if msg.is_err() {
                    break 'event_loop;
                }
                let msg = msg.unwrap();
                // initialize request must be first request from client to language server
                // initialized response contains capabilities which we save for future use
                // capabilities also serve as a marker of completing initialization
                // we park all requests from editor before initialization is complete
                // and then dispatch them
                if ctx.capabilities.is_some() {
                    dispatch_editor_request(msg, &mut ctx);
                } else {
                    debug!("Language server is not initialized, parking request");
                    {
                        let method: &str = &msg.method;
                        match method {
                            notification::DidOpenTextDocument::METHOD => (),
                            notification::DidChangeTextDocument::METHOD => (),
                            notification::DidCloseTextDocument::METHOD => (),
                            notification::DidSaveTextDocument::METHOD => (),
                            // TODO if auto-hover or auto-hl-references is not enabled we might want warning about parking as well
                            request::HoverRequest::METHOD => (),
                            request::DocumentHighlightRequest::METHOD => (),
                            _ => ctx.exec(
                                msg.meta.clone(),
                                "lsp-show-error 'Language server is not initialized, parking request'"
                                    .to_string(),
                            ),
                        }
                    }
                    ctx.pending_requests.push(msg);
                }
            }
            recv(lang_srv.from_lang_server.receiver()) -> msg => {
                if msg.is_err() {
                    break 'event_loop;
                }
                let msg = msg.unwrap();
                match msg {
                    ServerMessage::Request(call) => {
                        match call {
                            Call::MethodCall(request) => {
                              dispatch_server_request(request, &mut ctx);
                            }
                            Call::Notification(notification) => {
                                dispatch_server_notification(
                                    &notification.method,
                                    notification.params,
                                    &mut ctx,
                                );
                            }
                            Call::Invalid {id} => {
                                error!("Invalid call from language server: {:?}", id);
                            }
                        }
                    }
                    ServerMessage::Response(output) => {
                        match output {
                            Output::Success(success) => {
                                if let Some((meta, _, batch_id)) = ctx.response_waitlist.remove(&success.id) {
                                    if let Some((batch_amt, mut vals, callback)) = ctx.batches.remove(&batch_id) {
                                        vals.push(success.result);
                                        if batch_amt == 1 {
                                            callback(&mut ctx, meta, vals);
                                        } else {
                                            ctx.batches.insert(batch_id, (batch_amt - 1, vals, callback));
                                        }
                                    }
                                } else {
                                    error!("Id {:?} is not in waitlist!", success.id);
                                }
                            }
                            Output::Failure(failure) => {
                                error!("Error response from server: {:?}", failure);
                                if let Some(request) = ctx.response_waitlist.remove(&failure.id) {
                                    let (meta, method, _) = request;
                                    match failure.error.code {
                                        ErrorCode::ServerError(CONTENT_MODIFIED) => {},
                                        code => {
                                            let msg = match code {
                                                ErrorCode::MethodNotFound => format!(
                                                    "{} language server doesn't support method {}",
                                                    ctx.language_id, method
                                                ),
                                                _ => format!(
                                                    "{} language server error: {}",
                                                    ctx.language_id, editor_quote(&failure.error.message)
                                                ),
                                            };
                                            ctx.exec(meta, format!("lsp-show-error {}", editor_quote(&msg)));
                                        }
                                    }
                                } else {
                                    error!("Id {:?} is not in waitlist!", failure.id);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
/// Start controller.
///
/// Controller spawns language server for the given language and project root (passed as `route`).
/// Then it takes care of dispatching editor requests to this language server and dispatching
/// responses back to editor.
Start controller.
Controller spawns language server for the given language and project root (passed as `route`).
Then it takes care of dispatching editor requests to this language server and dispatching
responses back to editor.
Start controller . Controller spawns language server for the given language and project root ( passed as ` route ` ) . Then it takes care of dispatching editor requests to this language server and dispatching responses back to editor .
pub fn start(
    to_editor: Sender<EditorResponse>,
    from_editor: Receiver<EditorRequest>,
    route: &Route,
    initial_request: EditorRequest,
    config: Config,
) {
    let lang_srv: language_server_transport::LanguageServerTransport;
    let options;
    let offset_encoding;
    {
        // should be fine to unwrap because request was already routed which means language is configured
        let lang = &config.language[&route.language];
        options = lang.initialization_options.clone();
        offset_encoding = lang.offset_encoding.clone();
        lang_srv = language_server_transport::start(&lang.command, &lang.args);
    }
    let initial_request_meta = initial_request.meta.clone();
    let mut ctx = Context::new(
        &route.language,
        initial_request,
        lang_srv.to_lang_server.sender().clone(),
        to_editor,
        config,
        route.root.clone(),
        offset_encoding,
    );
    general::initialize(&route.root, options, initial_request_meta, &mut ctx);
    'event_loop: loop {
        select! {
            recv(from_editor) -> msg => {
                if msg.is_err() {
                    break 'event_loop;
                }
                let msg = msg.unwrap();
                // initialize request must be first request from client to language server
                // initialized response contains capabilities which we save for future use
                // capabilities also serve as a marker of completing initialization
                // we park all requests from editor before initialization is complete
                // and then dispatch them
                if ctx.capabilities.is_some() {
                    dispatch_editor_request(msg, &mut ctx);
                } else {
                    debug!("Language server is not initialized, parking request");
                    {
                        let method: &str = &msg.method;
                        match method {
                            notification::DidOpenTextDocument::METHOD => (),
                            notification::DidChangeTextDocument::METHOD => (),
                            notification::DidCloseTextDocument::METHOD => (),
                            notification::DidSaveTextDocument::METHOD => (),
                            // TODO if auto-hover or auto-hl-references is not enabled we might want warning about parking as well
                            request::HoverRequest::METHOD => (),
                            request::DocumentHighlightRequest::METHOD => (),
                            _ => ctx.exec(
                                msg.meta.clone(),
                                "lsp-show-error 'Language server is not initialized, parking request'"
                                    .to_string(),
                            ),
                        }
                    }
                    ctx.pending_requests.push(msg);
                }
            }
            recv(lang_srv.from_lang_server.receiver()) -> msg => {
                if msg.is_err() {
                    break 'event_loop;
                }
                let msg = msg.unwrap();
                match msg {
                    ServerMessage::Request(call) => {
                        match call {
                            Call::MethodCall(request) => {
                              dispatch_server_request(request, &mut ctx);
                            }
                            Call::Notification(notification) => {
                                dispatch_server_notification(
                                    &notification.method,
                                    notification.params,
                                    &mut ctx,
                                );
                            }
                            Call::Invalid {id} => {
                                error!("Invalid call from language server: {:?}", id);
                            }
                        }
                    }
                    ServerMessage::Response(output) => {
                        match output {
                            Output::Success(success) => {
                                if let Some((meta, _, batch_id)) = ctx.response_waitlist.remove(&success.id) {
                                    if let Some((batch_amt, mut vals, callback)) = ctx.batches.remove(&batch_id) {
                                        vals.push(success.result);
                                        if batch_amt == 1 {
                                            callback(&mut ctx, meta, vals);
                                        } else {
                                            ctx.batches.insert(batch_id, (batch_amt - 1, vals, callback));
                                        }
                                    }
                                } else {
                                    error!("Id {:?} is not in waitlist!", success.id);
                                }
                            }
                            Output::Failure(failure) => {
                                error!("Error response from server: {:?}", failure);
                                if let Some(request) = ctx.response_waitlist.remove(&failure.id) {
                                    let (meta, method, _) = request;
                                    match failure.error.code {
                                        ErrorCode::ServerError(CONTENT_MODIFIED) => {},
                                        code => {
                                            let msg = match code {
                                                ErrorCode::MethodNotFound => format!(
                                                    "{} language server doesn't support method {}",
                                                    ctx.language_id, method
                                                ),
                                                _ => format!(
                                                    "{} language server error: {}",
                                                    ctx.language_id, editor_quote(&failure.error.message)
                                                ),
                                            };
                                            ctx.exec(meta, format!("lsp-show-error {}", editor_quote(&msg)));
                                        }
                                    }
                                } else {
                                    error!("Id {:?} is not in waitlist!", failure.id);
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
pub fn start ( to_editor : Sender < EditorResponse > , from_editor : Receiver < EditorRequest > , route : & Route , initial_request : EditorRequest , config : Config , ) { let lang_srv : language_server_transport :: LanguageServerTransport ; let options ; let offset_encoding ; { // should be fine to unwrap because request was already routed which means language is configured let lang = & config . language [ & route . language ] ; options = lang . initialization_options . clone ( ) ; offset_encoding = lang . offset_encoding . clone ( ) ; lang_srv = language_server_transport :: start ( & lang . command , & lang . args ) ; } let initial_request_meta = initial_request . meta . clone ( ) ; let mut ctx = Context :: new ( & route . language , initial_request , lang_srv . to_lang_server . sender ( ) . clone ( ) , to_editor , config , route . root . clone ( ) , offset_encoding , ) ; general :: initialize ( & route . root , options , initial_request_meta , & mut ctx ) ; ' event_loop : loop { select ! { recv ( from_editor ) msg { if msg is_err ( ) { break ' event_loop } let msg msg unwrap ( ) // initialize request must be first request from client to language server // initialized response contains capabilities which we save for future use // capabilities also serve as a marker of completing initialization // we park all requests from editor before initialization is complete // and then dispatch them if ctx capabilities is_some ( ) { dispatch_editor_request ( msg mut ctx ) } else { debug ( " " ) { let method str msg method match method { notification DidOpenTextDocument METHOD ( ) notification DidChangeTextDocument METHOD ( ) notification DidCloseTextDocument METHOD ( ) notification DidSaveTextDocument METHOD ( ) // TODO if auto-hover or auto-hl-references is not enabled we might want warning about parking as well request HoverRequest METHOD ( ) request DocumentHighlightRequest METHOD ( ) ctx exec ( msg meta clone ( ) " " to_string ( ) ) } } ctx pending_requests push ( msg ) } } recv ( lang_srv from_lang_server receiver ( ) ) msg { if msg is_err ( ) { break ' event_loop } let msg msg unwrap ( ) match msg { ServerMessage Request ( call ) { match call { Call MethodCall ( request ) { dispatch_server_request ( request mut ctx ) } Call Notification ( notification ) { dispatch_server_notification ( notification method notification params mut ctx ) } Call Invalid { id } { error ( " " id ) } } } ServerMessage Response ( output ) { match output { Output Success ( success ) { if let Some ( ( meta batch_id ) ) ctx response_waitlist remove ( success id ) { if let Some ( ( batch_amt mut vals callback ) ) ctx batches remove ( batch_id ) { vals push ( success result ) if batch_amt 1 { callback ( mut ctx meta vals ) } else { ctx batches insert ( batch_id ( batch_amt 1 vals callback ) ) } } } else { error ( " " success id ) } } Output Failure ( failure ) { error ( " " failure ) if let Some ( request ) ctx response_waitlist remove ( failure id ) { let ( meta method ) request match failure error code { ErrorCode ServerError ( CONTENT_MODIFIED ) { } code { let msg match code { ErrorCode MethodNotFound format ( " " ctx language_id method ) format ( " " ctx language_id editor_quote ( failure error message ) ) } ctx exec ( meta format ( " " editor_quote ( msg ) ) ) } } } else { error ( " " failure id ) } } } } } } } } }
Start controller.
Start controller .
to_editor
Sender<EditorResponse>
from_editor
Receiver<EditorRequest>
route
&Route
initial_request
EditorRequest
config
Config
to_editor
Sender<EditorResponse>
from_editor
Receiver<EditorRequest>
route
&Route
initial_request
EditorRequest
config
Config