Repository: lapce/lapce
File: lapce-proxy/src/lsp.rs (Rust)

Code before:
                return vals;
            }
        };

        let binary = match option["binary"].as_object() {
            Some(binary) => binary,
            None => return vals,
        };

        let option = match binary.get("binary_args") {
            Some(binary_args) => binary_args,
            None => return vals,
        };

        let option = if let Some(option) = option.as_array() {
            option
        } else {
            println!("binary_args value should be of type [String].");
            return vals;
        };

        for val in option {
            vals.push(String::from(val.as_str().unwrap()));
        }

        return vals;
    }

    pub fn new_buffer(
        &self,
        buffer_id: &BufferId,
        path: &str,
        language_id: &str,
        text: String,
    ) {
        let document_uri = Url::from_file_path(path).unwrap();
        if let Some(client) = self.clients.get(language_id) {
            client.send_did_open(buffer_id, document_uri, language_id, text);
        }
    }

    pub fn save_buffer(&self, buffer: &Buffer) {
        if let Some(client) = self.clients.get(&buffer.language_id) {
            let uri = client.get_uri(buffer);
            client.send_did_save(uri);
        }
    }

    pub fn get_semantic_tokens(&self, buffer: &Buffer) {
        let buffer_id = buffer.id;
        let path = buffer.path.clone();

Review comment (refactor):
 - You don't need to spell out the `return`
 - I think with the above comment you can avoid the `vals` variable completely
 - If this function returned `Option<Vec...` instead, you might simplify the early returns into `?`s. Also this would help differentiating between "no args" and the error cases.

Code after:
        let option = option?;

        match option["binary"].as_object()?.get("args")?.as_array() {
            Some(options) => {
                return Some(
                    options
                        .iter()
                        .filter_map(Value::as_str)
                        .map(ToString::to_string)
                        .collect::<Vec<_>>(),
                )
            }
            None => {
                log::warn!("args value should be of type [String].");
            }
        };

        None
    }

    pub fn new_buffer(
        &self,
        buffer_id: &BufferId,
        path: &str,
        language_id: &str,
        text: String,
    ) {
        let document_uri = Url::from_file_path(path).unwrap();
        if let Some(client) = self.clients.get(language_id) {
            client.send_did_open(buffer_id, document_uri, language_id, text);
        }
    }

    pub fn save_buffer(&self, buffer: &Buffer) {
        if let Some(client) = self.clients.get(&buffer.language_id) {
            let uri = client.get_uri(buffer);
            client.send_did_save(uri);
        }
    }

    pub fn get_semantic_tokens(&self, buffer: &Buffer) {
        let buffer_id = buffer.id;
        let path = buffer.path.clone();
        let rev = buffer.rev;
        let len = buffer.len();
        if let Some(client) = self.clients.get(&buffer.language_id) {
            let uri = client.get_uri(buffer);
            let local_dispatcher = self.dispatcher.clone().unwrap();
            client.request_semantic_tokens(uri, move |lsp_client, result| {
                if let Ok(res) = result {
                    let buffers = local_dispatcher.buffers.lock();