Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Don't panic on unknown paths #93

Merged
merged 1 commit into from
Apr 17, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 16 additions & 19 deletions src/lsp_typst_boundary/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! Conversions between Typst and LSP types and representations

use std::collections::HashMap;
use std::io;

use tower_lsp::lsp_types::{self, Url};
use tower_lsp::lsp_types;

pub mod world;

Expand Down Expand Up @@ -54,14 +53,12 @@ pub type TypstCompletion = typst::ide::Completion;
pub type TypstCompletionKind = typst::ide::CompletionKind;

pub mod lsp_to_typst {
use std::path::PathBuf;

use super::*;

// TODO: these URL <-> Path functions are a quick hack to make things work. They should be
// replaced by a more comprehensive system to reliably convert `LspUri`s to `TypstPath`s
pub fn uri_to_path(lsp_uri: &LspUri) -> TypstPathOwned {
lsp_uri.to_file_path().unwrap_or_else(|_| PathBuf::new())
pub fn uri_to_path(lsp_uri: &LspUri) -> anyhow::Result<TypstPathOwned> {
lsp_uri
.to_file_path()
.map_err(|()| anyhow::anyhow!("could not get path for URI {lsp_uri}"))
}

pub fn position_to_offset(
Expand Down Expand Up @@ -127,7 +124,6 @@ pub mod typst_to_lsp {
use tower_lsp::lsp_types::{
DiagnosticSeverity, InsertTextFormat, LanguageString, MarkedString,
};
use typst::util::PathExt;
use typst::World;
use typst_library::prelude::EcoString;

Expand All @@ -136,12 +132,11 @@ pub mod typst_to_lsp {
use super::world::WorkspaceWorld;
use super::*;

// TODO: these URL <-> Path functions are a quick hack to make things work. They should be
// replaced by a more comprehensive system to reliably convert `LspUri`s to `TypstPath`s
pub fn path_to_uri(typst_path: &TypstPath) -> io::Result<LspUri> {
let normalized_path = typst_path.normalize();
let lsp_uri = Url::from_file_path(normalized_path).unwrap();
Ok(lsp_uri)
pub fn path_to_uri(typst_path: &TypstPath) -> anyhow::Result<LspUri> {
LspUri::from_file_path(typst_path).map_err(|()| {
let path = typst_path.to_string_lossy();
anyhow::anyhow!("could not get URI for path {path}")
})
}

pub fn offset_to_position(
Expand Down Expand Up @@ -233,7 +228,7 @@ pub mod typst_to_lsp {
typst_error: &TypstSourceError,
world: &WorkspaceWorld,
const_config: &ConstConfig,
) -> (Url, LspDiagnostic) {
) -> Option<(LspUri, LspDiagnostic)> {
let typst_span = typst_error.span;
let typst_source = world.source(typst_span.source());

Expand All @@ -249,9 +244,9 @@ pub mod typst_to_lsp {
..Default::default()
};

let uri = path_to_uri(typst_source.path()).unwrap();
let uri = path_to_uri(typst_source.path()).ok()?;

(uri, diagnostic)
Some((uri, diagnostic))
}

pub fn source_errors_to_diagnostics<'a>(
Expand All @@ -261,7 +256,9 @@ pub mod typst_to_lsp {
) -> LspDiagnostics {
errors
.into_iter()
.map(|error| typst_to_lsp::source_error_to_diagnostic(error, world, const_config))
.filter_map(|error| {
typst_to_lsp::source_error_to_diagnostic(error, world, const_config)
})
.into_group_map()
}

Expand Down
8 changes: 5 additions & 3 deletions src/lsp_typst_boundary/world.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use comemo::Prehashed;
use tokio::sync::OwnedRwLockReadGuard;
use typst::diag::FileResult;
use typst::diag::{FileError, FileResult};
use typst::eval::Library;
use typst::font::{Font, FontBook};
use typst::util::Buffer;
Expand Down Expand Up @@ -37,7 +37,8 @@ impl World for WorkspaceWorld {
}

fn resolve(&self, typst_path: &TypstPath) -> FileResult<TypstSourceId> {
let lsp_uri = typst_to_lsp::path_to_uri(typst_path).unwrap();
let lsp_uri = typst_to_lsp::path_to_uri(typst_path)
.map_err(|_| FileError::NotFound(typst_path.to_owned()))?;
self.get_workspace().sources.cache(lsp_uri).map(Into::into)
}

Expand All @@ -59,7 +60,8 @@ impl World for WorkspaceWorld {
}

fn file(&self, typst_path: &TypstPath) -> FileResult<Buffer> {
let lsp_uri = typst_to_lsp::path_to_uri(typst_path).unwrap();
let lsp_uri = typst_to_lsp::path_to_uri(typst_path)
.map_err(|_| FileError::NotFound(typst_path.to_owned()))?;
let mut resources = self.get_workspace().resources.write();
let lsp_resource = resources.get_or_insert_resource(lsp_uri)?;
Ok(lsp_resource.into())
Expand Down
5 changes: 4 additions & 1 deletion src/server/lsp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,10 @@ impl LanguageServer for TypstServer {
let text = params.text_document.text;

let mut workspace = self.workspace.write().await;
workspace.sources.insert_open(&uri, text);
if let Err(error) = workspace.sources.insert_open(&uri, text) {
self.client.log_message(MessageType::ERROR, error).await;
return;
}

let workspace = workspace.downgrade();
let config = self.config.read().await;
Expand Down
4 changes: 3 additions & 1 deletion src/workspace/font_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,9 +182,11 @@ impl Builder {
if let Ok(file) = File::open(&path) {
if let Ok(mmap) = unsafe { Mmap::map(&file) } {
for (i, info) in FontInfo::iter(&mmap).enumerate() {
let Ok(uri) = Url::from_file_path(&path) else { continue; };

self.book.push(info);
self.fonts.push(FontSlot {
uri: Some(Url::from_file_path(&path).unwrap()),
uri: Some(uri),
index: i as u32,
font: OnceCell::new(),
});
Expand Down
8 changes: 4 additions & 4 deletions src/workspace/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ pub struct Source {
}

impl Source {
pub fn new(id: SourceId, uri: &Url, text: String) -> Self {
let typst_path = lsp_to_typst::uri_to_path(uri);
pub fn new(id: SourceId, uri: &Url, text: String) -> anyhow::Result<Self> {
let typst_path = lsp_to_typst::uri_to_path(uri)?;

Self {
Ok(Self {
inner: TypstSource::new(id.into(), &typst_path, text),
}
})
}

pub fn new_detached() -> Self {
Expand Down
12 changes: 7 additions & 5 deletions src/workspace/source_manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,21 +87,23 @@ impl SourceManager {
SourceId(self.sources.len() as u16)
}

pub fn insert_open(&mut self, uri: &Url, text: String) {
pub fn insert_open(&mut self, uri: &Url, text: String) -> anyhow::Result<()> {
let next_id = self.get_next_id();

match self.ids.as_mut().entry(uri.clone()) {
Entry::Occupied(entry) => {
let existing_id = *entry.get();
let source = Source::new(existing_id, uri, text);
let source = Source::new(existing_id, uri, text)?;
*self.get_mut_inner_source(existing_id) = InnerSource::Open(source);
}
Entry::Vacant(entry) => {
entry.insert(next_id);
let source = Source::new(next_id, uri, text);
let source = Source::new(next_id, uri, text)?;
self.sources.push(Box::new(InnerSource::Open(source)));
}
}

Ok(())
}

pub fn close(&mut self, uri: &Url) {
Expand All @@ -124,13 +126,13 @@ impl SourceManager {
}

fn read_source_from_file(id: SourceId, uri: &Url) -> FileResult<Source> {
let path = lsp_to_typst::uri_to_path(uri);
let path = lsp_to_typst::uri_to_path(uri).map_err(|_| FileError::Other)?;
let text = fs::read_to_string(&path).map_err(|error| match error.kind() {
io::ErrorKind::NotFound => FileError::NotFound(path),
io::ErrorKind::PermissionDenied => FileError::AccessDenied,
_ => FileError::Other,
})?;
Ok(Source::new(id, uri, text))
Source::new(id, uri, text).map_err(|_| FileError::Other)
}

pub fn cache(&self, uri: Url) -> FileResult<SourceId> {
Expand Down