laburnum 1.17.1

An LSP framework for building language servers and compilers, powered by an incremental query tree with content-addressed storage, task-based dataflow, and parallel queries.
Documentation
// Copyright Two Neutron Stars Incorporated and contributors
// SPDX-License-Identifier: BlueOak-1.0.0

use {
  crate::{
    Partitions,
    TRACER,
    database::PartitionKey,
    partitions::Diagnostics,
    protocol::{
      jsonrpc,
      lsp::{
        LSPAny,
        LanguageServer,
      },
    },
    record::LaburnumRecordRef,
    scheduler::task::TaskContext,
  },
  opentelemetry::trace::FutureExt,
  serde_json::Value,
};

pub async fn handle_ariadne_diagnostics<
  P: Partitions,
  T: LanguageServer<P>,
>(
  arguments: &[Value],
  ctx: &mut TaskContext<P, T>,
) -> jsonrpc::Result<Option<LSPAny>> {
  let arg = arguments.first();

  let color = arg
    .and_then(|a| a.get("color"))
    .and_then(|v| v.as_bool())
    .unwrap_or(true);

  let partition_key = Diagnostics::KEY;

  let cx = otel::span!(^
    "handle_ariadne_diagnostics",
    "color" = color,
  );

  let query_client = ctx.query_client();
  let query_results = query_client
    .prefix_internal(partition_key, String::new())
    .with_context(cx)
    .await;

  let mut source_cache_reader = ctx.source_cache_reader();
  let mut formatted_errors: Vec<String> = Vec::new();

  for record_meta in query_results.records().iter() {
    let Some(record_ref) = query_results.get(record_meta) else {
      continue;
    };

    let Some(diagnostic) = record_ref.as_dyn_diagnostic() else {
      continue;
    };

    let report = diagnostic.to_ariadne_report(&source_cache_reader);
    let mut buffer = Vec::new();

    if let Ok(()) = report.write(&mut source_cache_reader, &mut buffer)
      && let Ok(text) = String::from_utf8(buffer)
    {
      let output = if color {
        text
      } else {
        anstream::adapter::strip_str(&text).to_string()
      };
      formatted_errors.push(output);
    }
  }

  Ok(Some(serde_json::json!(formatted_errors)))
}