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

Code before:
            }
        };

        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();
        let rev = buffer.rev;

Review comment (suggestion):
I feel entire function would benefit in changing return type from `Vec<String>` to `Option<Vec<String>>` and handling None outside with `.unwrap_or_default()`

At least 3 sections can be change to

```
let option = option["binary"]
    .as_object()?
    .get("binary_args")?
    .as_array()?;
```


Code after:

        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();
                    let buffer = buffers.get(&buffer_id).unwrap();