use log::{info, warn};
use lsp_types::{
DidChangeWatchedFilesRegistrationOptions, FileSystemWatcher, GlobPattern, Registration,
RegistrationParams, Unregistration, UnregistrationParams, WatchKind,
};
use crate::context::{ClientProxy, ServerContextSnapshot};
const WATCH_FILES_REGISTRATION_ID: &str = "cpp_ls_watched_files";
const WATCHED_GLOBS: &[&str] = &[
"**/*.{c,cc,cpp,cxx,c++,h,hh,hpp,hxx,h++,ipp,inl,tpp,tcc}",
"**/*.{cppm,ixx}",
"**/.cppls.toml",
"**/compile_commands.json",
"**/CMakeCache.txt",
];
pub async fn register_files_watch(context: ServerContextSnapshot) {
if !context
.lsp_features()
.supports_dynamic_watched_files_registration()
{
warn!(
"the client cannot be asked to watch files; changes made outside the editor will not be noticed"
);
return;
}
if context
.workspace_manager()
.lock()
.await
.watch_filter()
.is_none()
{
return;
}
register(context.client());
info!("asked the client to watch {} globs", WATCHED_GLOBS.len());
}
fn register(client: &ClientProxy) {
unregister(client);
let options = DidChangeWatchedFilesRegistrationOptions {
watchers: WATCHED_GLOBS
.iter()
.map(|glob| FileSystemWatcher {
glob_pattern: GlobPattern::String((*glob).to_string()),
kind: Some(WatchKind::Create | WatchKind::Change | WatchKind::Delete),
})
.collect(),
};
client.dynamic_register_capability(RegistrationParams {
registrations: vec![Registration {
id: WATCH_FILES_REGISTRATION_ID.to_string(),
method: "workspace/didChangeWatchedFiles".to_string(),
register_options: Some(
serde_json::to_value(options).expect("the registration options serialize"),
),
}],
});
}
fn unregister(client: &ClientProxy) {
client.dynamic_unregister_capability(UnregistrationParams {
unregisterations: vec![Unregistration {
id: WATCH_FILES_REGISTRATION_ID.to_string(),
method: "workspace/didChangeWatchedFiles".to_string(),
}],
});
}