Tailwind autocomplete (#2920)
Release Notes: - Added basic Tailwind CSS autocomplete support ([#746](https://github.com/zed-industries/community/issues/746)).
This commit is contained in:
commit
ddc6214216
43 changed files with 1075 additions and 280 deletions
|
@ -20,7 +20,7 @@ anyhow.workspace = true
|
|||
async-pipe = { git = "https://github.com/zed-industries/async-pipe-rs", rev = "82d00a04211cf4e1236029aa03e6b6ce2a74c553", optional = true }
|
||||
futures.workspace = true
|
||||
log.workspace = true
|
||||
lsp-types = "0.94"
|
||||
lsp-types = { git = "https://github.com/zed-industries/lsp-types", branch = "updated-completion-list-item-defaults" }
|
||||
parking_lot.workspace = true
|
||||
postage.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -4,7 +4,7 @@ pub use lsp_types::*;
|
|||
|
||||
use anyhow::{anyhow, Context, Result};
|
||||
use collections::HashMap;
|
||||
use futures::{channel::oneshot, io::BufWriter, AsyncRead, AsyncWrite};
|
||||
use futures::{channel::oneshot, io::BufWriter, AsyncRead, AsyncWrite, FutureExt};
|
||||
use gpui::{executor, AsyncAppContext, Task};
|
||||
use parking_lot::Mutex;
|
||||
use postage::{barrier, prelude::Stream};
|
||||
|
@ -26,12 +26,14 @@ use std::{
|
|||
atomic::{AtomicUsize, Ordering::SeqCst},
|
||||
Arc, Weak,
|
||||
},
|
||||
time::{Duration, Instant},
|
||||
};
|
||||
use std::{path::Path, process::Stdio};
|
||||
use util::{ResultExt, TryFutureExt};
|
||||
|
||||
const JSON_RPC_VERSION: &str = "2.0";
|
||||
const CONTENT_LEN_HEADER: &str = "Content-Length: ";
|
||||
const LSP_REQUEST_TIMEOUT: Duration = Duration::from_secs(60 * 2);
|
||||
|
||||
type NotificationHandler = Box<dyn Send + FnMut(Option<usize>, &str, AsyncAppContext)>;
|
||||
type ResponseHandler = Box<dyn Send + FnOnce(Result<String, Error>)>;
|
||||
|
@ -303,7 +305,7 @@ impl LanguageServer {
|
|||
stdout.read_exact(&mut buffer).await?;
|
||||
|
||||
if let Ok(message) = str::from_utf8(&buffer) {
|
||||
log::trace!("incoming message:{}", message);
|
||||
log::trace!("incoming message: {}", message);
|
||||
for handler in io_handlers.lock().values_mut() {
|
||||
handler(IoKind::StdOut, message);
|
||||
}
|
||||
|
@ -468,6 +470,14 @@ impl LanguageServer {
|
|||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
completion_list: Some(CompletionListCapability {
|
||||
item_defaults: Some(vec![
|
||||
"commitCharacters".to_owned(),
|
||||
"editRange".to_owned(),
|
||||
"insertTextMode".to_owned(),
|
||||
"data".to_owned(),
|
||||
]),
|
||||
}),
|
||||
..Default::default()
|
||||
}),
|
||||
rename: Some(RenameClientCapabilities {
|
||||
|
@ -740,7 +750,7 @@ impl LanguageServer {
|
|||
outbound_tx: &channel::Sender<String>,
|
||||
executor: &Arc<executor::Background>,
|
||||
params: T::Params,
|
||||
) -> impl 'static + Future<Output = Result<T::Result>>
|
||||
) -> impl 'static + Future<Output = anyhow::Result<T::Result>>
|
||||
where
|
||||
T::Result: 'static + Send,
|
||||
{
|
||||
|
@ -781,10 +791,25 @@ impl LanguageServer {
|
|||
.try_send(message)
|
||||
.context("failed to write to language server's stdin");
|
||||
|
||||
let mut timeout = executor.timer(LSP_REQUEST_TIMEOUT).fuse();
|
||||
let started = Instant::now();
|
||||
async move {
|
||||
handle_response?;
|
||||
send?;
|
||||
rx.await?
|
||||
|
||||
let method = T::METHOD;
|
||||
futures::select! {
|
||||
response = rx.fuse() => {
|
||||
let elapsed = started.elapsed();
|
||||
log::trace!("Took {elapsed:?} to recieve response to {method:?} id {id}");
|
||||
response?
|
||||
}
|
||||
|
||||
_ = timeout => {
|
||||
log::error!("Cancelled LSP request task for {method:?} id {id} which took over {LSP_REQUEST_TIMEOUT:?}");
|
||||
anyhow::bail!("LSP request timeout");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue