dev: convert diagnostics without analysis snapshot (#805)

This commit is contained in:
Myriad-Dreamin 2024-11-13 23:51:48 +08:00 committed by GitHub
parent cadc70ceec
commit 61f2273e2e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 73 additions and 41 deletions

View file

@ -26,8 +26,14 @@ mod prelude;
mod global;
pub use global::*;
use ecow::eco_format;
use lsp_types::Url;
use reflexo_typst::TypstFileId;
use typst::diag::FileError;
use typst::foundations::{Func, Value};
use crate::path_to_url;
pub(crate) trait ToFunc {
fn to_func(&self) -> Option<Func>;
}
@ -42,6 +48,22 @@ impl ToFunc for Value {
}
}
/// Extension trait for `typst::World`.
pub trait LspWorldExt {
/// Resolve the uri for a file id.
fn uri_for_id(&self, id: TypstFileId) -> Result<Url, FileError>;
}
impl LspWorldExt for tinymist_world::LspWorld {
/// Resolve the uri for a file id.
fn uri_for_id(&self, id: TypstFileId) -> Result<Url, FileError> {
self.path_for_id(id).and_then(|e| {
path_to_url(&e)
.map_err(|e| FileError::Other(Some(eco_format!("convert to url: {e:?}"))))
})
}
}
#[cfg(test)]
mod matcher_tests {

View file

@ -36,7 +36,7 @@ use crate::syntax::{
};
use crate::upstream::{tooltip_, Tooltip};
use crate::{
lsp_to_typst, path_to_url, typst_to_lsp, ColorTheme, LspPosition, LspRange, PositionEncoding,
lsp_to_typst, typst_to_lsp, ColorTheme, LspPosition, LspRange, LspWorldExt, PositionEncoding,
SemanticTokenContext, TypstRange, VersionedDocument,
};
@ -452,10 +452,7 @@ impl SharedContext {
/// Resolve the uri for a file id.
pub fn uri_for_id(&self, id: TypstFileId) -> Result<Url, FileError> {
self.path_for_id(id).and_then(|e| {
path_to_url(&e)
.map_err(|e| FileError::Other(Some(eco_format!("convert to url: {e:?}"))))
})
self.world.uri_for_id(id)
}
/// Get file's id by its path

View file

@ -1,19 +1,42 @@
use reflexo_typst::EntryReader;
use tinymist_world::LspWorld;
use crate::prelude::*;
use crate::{prelude::*, LspWorldExt};
/// Stores diagnostics for files.
pub type DiagnosticsMap = HashMap<Url, Vec<LspDiagnostic>>;
/// Context for converting Typst diagnostics to LSP diagnostics.
struct LocalDiagContext<'a> {
/// The world surface for Typst compiler.
pub world: &'a LspWorld,
/// The position encoding for the source.
pub position_encoding: PositionEncoding,
}
impl std::ops::Deref for LocalDiagContext<'_> {
type Target = LspWorld;
fn deref(&self) -> &Self::Target {
self.world
}
}
/// Converts a list of Typst diagnostics to LSP diagnostics.
pub fn convert_diagnostics<'a>(
ctx: &LocalContext,
world: &LspWorld,
errors: impl IntoIterator<Item = &'a TypstDiagnostic>,
position_encoding: PositionEncoding,
) -> DiagnosticsMap {
let ctx = LocalDiagContext {
world,
position_encoding,
};
errors
.into_iter()
.flat_map(|error| {
convert_diagnostic(ctx, error)
convert_diagnostic(&ctx, error)
.map_err(move |conversion_err| {
log::error!("could not convert Typst error to diagnostic: {conversion_err:?} error to convert: {error:?}");
})
@ -24,18 +47,17 @@ pub fn convert_diagnostics<'a>(
}
fn convert_diagnostic(
ctx: &LocalContext,
ctx: &LocalDiagContext,
typst_diagnostic: &TypstDiagnostic,
) -> anyhow::Result<(Url, LspDiagnostic)> {
let uri;
let lsp_range;
if let Some((id, span)) = diagnostic_span_id(typst_diagnostic) {
uri = ctx.uri_for_id(id)?;
let source = ctx.world().source(id)?;
lsp_range = diagnostic_range(&source, span, ctx.position_encoding());
let source = ctx.source(id)?;
lsp_range = diagnostic_range(&source, span, ctx.position_encoding);
} else {
let root = ctx
.world
.workspace_root()
.ok_or_else(|| anyhow::anyhow!("no workspace root"))?;
uri = path_to_url(&root)?;
@ -48,8 +70,7 @@ fn convert_diagnostic(
let typst_hints = &typst_diagnostic.hints;
let lsp_message = format!("{typst_message}{}", diagnostic_hints(typst_hints));
let tracepoints =
diagnostic_related_information(ctx, typst_diagnostic, ctx.position_encoding())?;
let tracepoints = diagnostic_related_information(ctx, typst_diagnostic, ctx.position_encoding)?;
let diagnostic = LspDiagnostic {
range: lsp_range,
@ -64,13 +85,13 @@ fn convert_diagnostic(
}
fn tracepoint_to_relatedinformation(
project: &LocalContext,
ctx: &LocalDiagContext,
tracepoint: &Spanned<Tracepoint>,
position_encoding: PositionEncoding,
) -> anyhow::Result<Option<DiagnosticRelatedInformation>> {
if let Some(id) = tracepoint.span.id() {
let uri = project.uri_for_id(id)?;
let source = project.world().source(id)?;
let uri = ctx.uri_for_id(id)?;
let source = ctx.source(id)?;
if let Some(typst_range) = source.range(tracepoint.span) {
let lsp_range = typst_to_lsp::range(typst_range, &source, position_encoding);
@ -89,7 +110,7 @@ fn tracepoint_to_relatedinformation(
}
fn diagnostic_related_information(
project: &LocalContext,
project: &LocalDiagContext,
typst_diagnostic: &TypstDiagnostic,
position_encoding: PositionEncoding,
) -> anyhow::Result<Vec<DiagnosticRelatedInformation>> {

View file

@ -15,7 +15,7 @@ pub mod syntax;
pub mod ty;
mod upstream;
pub use analysis::{LocalContext, LocalContextGuard};
pub use analysis::{LocalContext, LocalContextGuard, LspWorldExt};
pub use upstream::with_vm;
mod diagnostics;