use {
crate::{
Partitions, Uri,
protocol::{
jsonrpc,
lsp::{LSPAny, LanguageServer},
},
scheduler::task::TaskContext,
},
serde_json::Value,
};
pub async fn handle_query_source_cache<P: Partitions, T: LanguageServer<P>>(
arguments: &[Value],
ctx: &mut TaskContext<P, T>,
) -> jsonrpc::Result<Option<LSPAny>> {
let arg = arguments.first().ok_or_else(|| {
otel::exception!(
"invalid_params",
jsonrpc::Error::invalid_params("Missing arguments object")
)
})?;
let uri_str = arg.get("uri").and_then(|v| v.as_str()).ok_or_else(|| {
otel::exception!(
"invalid_params",
jsonrpc::Error::invalid_params("Missing 'uri' field")
)
})?;
let uri = Uri::parse(uri_str).map_err(|e| {
otel::exception!(
"invalid_uri",
jsonrpc::Error::invalid_params(format!("Invalid URI: {}", e)),
"uri_str" = uri_str.to_string()
)
})?;
let properties =
arg.get("properties").and_then(|v| v.as_array()).map(|arr| {
arr
.iter()
.filter_map(|v| v.as_str().map(|s| s.to_string()))
.collect::<Vec<_>>()
});
otel::event!(
"query_source_cache.start",
"uri" = uri.to_string(),
"property_count" = properties.as_ref().map(|p| p.len() as i64).unwrap_or(0)
);
let source_cache = ctx.source_cache();
let cache = source_cache.read();
if let Some(source) = cache.get_source_by_uri(&uri) {
otel::event!("cache.hit", "uri" = uri.to_string());
let mut response = serde_json::Map::new();
let include_all = properties.is_none();
let props = properties.as_ref();
let should_include = |prop: &str| -> bool {
include_all || props.is_some_and(|p| p.contains(&prop.to_string()))
};
if should_include("uri") {
response.insert(
"uri".to_string(),
serde_json::json!(source.uri().to_string()),
);
}
if should_include("content")
&& let Some(content) = source.reify()
{
response.insert("content".to_string(), serde_json::json!(content));
}
if should_include("version") {
let version = cache
.get_latest_lsp_version(&uri)
.unwrap_or(source.version() as i32);
response.insert("version".to_string(), serde_json::json!(version));
}
if should_include("isOpen") {
let is_open = cache.is_file_open_in_editor(&uri);
response.insert("isOpen".to_string(), serde_json::json!(is_open));
}
Ok(Some(serde_json::Value::Object(response)))
} else {
otel::event!("cache.miss", "uri" = uri.to_string());
Err(otel::exception!(
"source_not_found",
jsonrpc::Error {
code: jsonrpc::ErrorCode::ServerError(10404),
message: format!("Source not found for URI: {}", uri).into(),
data: None,
},
"uri" = uri.to_string()
))
}
}