Skip to content

Commit

Permalink
dev: reduce a bundle of ts usage in query crate (#72)
Browse files Browse the repository at this point in the history
  • Loading branch information
Myriad-Dreamin authored Mar 18, 2024
1 parent c650932 commit cc1f418
Show file tree
Hide file tree
Showing 25 changed files with 204 additions and 117 deletions.
5 changes: 5 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 14 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,23 @@ typst = "0.11.0"
typst-ide = "0.11.0"
typst-pdf = "0.11.0"
typst-assets = { git = "https://github.com/typst/typst-assets", rev = "4d1211a" }
reflexo = { version = "0.4.2-rc8", default-features = false, features = [
"flat-vector",
] }
typst-ts-core = { version = "0.4.2-rc8" }
typst-ts-compiler = { version = "0.4.2-rc8" }
typst-preview = { git = "https://github.com/Enter-tainer/typst-preview", rev = "18630ebda22339109ef675a885787f4fc8731ba8" }

# [features]
# rkyv = ["dep:rkyv", "rkyv/alloc", "rkyv/archive_le"]
# rkyv-validation = ["dep:rkyv", "rkyv/validation"]
# flat-vector = ["rkyv", "rkyv-validation"]

# __web = ["dep:wasm-bindgen", "dep:js-sys"]
# web = ["__web"]
# full = ["web", "flat-vector"]
# default = ["full"]

lsp-server = "0.7.6"
lsp-types = { version = "=0.95.0", features = ["proposed"] }
crossbeam-channel = "0.5.12"
Expand Down Expand Up @@ -113,6 +126,7 @@ typst-syntax = { git = "https://github.com/Myriad-Dreamin/typst.git", branch = "
# typst-syntax = { path = "../typst/crates/typst-syntax" }

typst-ts-svg-exporter = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "2fc877de0a4bcd7a8f057933546a97348e9621c7", package = "typst-ts-svg-exporter" }
reflexo = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "2fc877de0a4bcd7a8f057933546a97348e9621c7", package = "reflexo" }
typst-ts-core = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "2fc877de0a4bcd7a8f057933546a97348e9621c7", package = "typst-ts-core" }
typst-ts-compiler = { git = "https://github.com/Myriad-Dreamin/typst.ts", rev = "2fc877de0a4bcd7a8f057933546a97348e9621c7", package = "typst-ts-compiler" }

Expand Down
6 changes: 4 additions & 2 deletions crates/tinymist-query/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,16 +28,18 @@ fxhash.workspace = true
toml.workspace = true
walkdir.workspace = true
indexmap.workspace = true
ecow.workspace = true

typst.workspace = true
typst-ide.workspace = true

typst-ts-core = { version = "0.4.2-rc6", default-features = false, features = [
reflexo.workspace = true
typst-ts-compiler.workspace = true
typst-ts-core = { version = "0.4.2-rc8", default-features = false, features = [
"flat-vector",
"vector-bbox",
"no-content-hint",
] }
typst-ts-compiler.workspace = true

lsp-types.workspace = true

Expand Down
14 changes: 7 additions & 7 deletions crates/tinymist-query/src/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ pub use global::*;

#[cfg(test)]
mod module_tests {
use ecow::EcoVec;
use reflexo::path::unix_slash;
use serde_json::json;
use typst_ts_core::path::unix_slash;
use typst_ts_core::typst::prelude::EcoVec;

use crate::prelude::*;
use crate::syntax::module::*;
use crate::tests::*;

#[test]
fn test() {
snapshot_testing2("modules", &|ctx, _| {
snapshot_testing("modules", &|ctx, _| {
fn ids(ids: EcoVec<TypstFileId>) -> Vec<String> {
let mut ids: Vec<String> = ids
.into_iter()
Expand Down Expand Up @@ -66,14 +66,14 @@ mod lexical_hierarchy_tests {
use def_use::DefUseSnapshot;

use crate::analysis::def_use;
use crate::prelude::*;
// use crate::prelude::*;
use crate::syntax::lexical_hierarchy;
use crate::tests::*;

#[test]
fn scope() {
snapshot_testing("lexical_hierarchy", &|world, path| {
let source = get_suitable_source_in_workspace(world, &path).unwrap();
snapshot_testing("lexical_hierarchy", &|ctx, path| {
let source = ctx.source_by_path(&path).unwrap();

let result = lexical_hierarchy::get_lexical_hierarchy(
source,
Expand All @@ -87,7 +87,7 @@ mod lexical_hierarchy_tests {
#[test]
fn test_def_use() {
fn def_use(set: &str) {
snapshot_testing2(set, &|ctx, path| {
snapshot_testing(set, &|ctx, path| {
let source = ctx.source_by_path(&path).unwrap();

let result = ctx.def_use(source);
Expand Down
6 changes: 3 additions & 3 deletions crates/tinymist-query/src/analysis/def_use.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@ use std::{
};

use log::info;
use reflexo::path::unix_slash;
pub use reflexo::vector::ir::DefId;
use serde::Serialize;
use typst::syntax::FileId as TypstFileId;
use typst::syntax::Source;
use typst_ts_core::{path::unix_slash, TypstFileId};

use super::SearchCtx;
use crate::syntax::{
Expand All @@ -18,8 +20,6 @@ use crate::syntax::{
};
use crate::{adt::snapshot_map::SnapshotMap, syntax::LexicalModKind};

pub use typst_ts_core::vector::ir::DefId;

/// The type namespace of def-use relations
///
/// The symbols from different namespaces are not visible to each other.
Expand Down
49 changes: 35 additions & 14 deletions crates/tinymist-query/src/analysis/global.rs
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
use std::{
collections::{HashMap, HashSet},
path::Path,
path::{Path, PathBuf},
sync::Arc,
};

use once_cell::sync::OnceCell;
use reflexo::{cow_mut::CowMut, ImmutPath};
use typst::syntax::FileId as TypstFileId;
use typst::{
diag::{eco_format, FileError, FileResult},
syntax::{Source, VirtualPath},
World,
};
use typst_ts_compiler::{service::WorkspaceProvider, TypstSystemWorld};
use typst_ts_core::{cow_mut::CowMut, ImmutPath, TypstFileId};
use typst_ts_compiler::package::Registry;
use typst_ts_compiler::TypstSystemWorld;
// use typst_ts_compiler::TypstSystemWorld;
// use typst_ts_compiler::{service::WorkspaceProvider, TypstSystemWorld};
// use typst_ts_core::{cow_mut::CowMut, ImmutPath};

use super::{get_def_use_inner, DefUseInfo};
use crate::{
Expand Down Expand Up @@ -57,10 +62,11 @@ pub struct Analysis {
/// changes.
pub root: ImmutPath,
/// The position encoding for the workspace.
position_encoding: PositionEncoding,
pub position_encoding: PositionEncoding,
}

/// A cache for all level of analysis results of a module.
#[derive(Default)]
pub struct AnalysisCaches {
modules: HashMap<TypstFileId, ModuleAnalysisCache>,
root_files: OnceCell<Vec<TypstFileId>>,
Expand All @@ -78,18 +84,11 @@ pub struct AnalysisContext<'a> {

impl<'w> AnalysisContext<'w> {
/// Create a new analysis context.
pub fn new(world: &'w TypstSystemWorld, encoding: PositionEncoding) -> Self {
pub fn new(world: &'w TypstSystemWorld, a: Analysis) -> Self {
Self {
world,
analysis: CowMut::Owned(Analysis {
root: world.workspace_root(),
position_encoding: encoding,
}),
caches: AnalysisCaches {
modules: HashMap::new(),
root_files: OnceCell::new(),
module_deps: OnceCell::new(),
},
analysis: CowMut::Owned(a),
caches: AnalysisCaches::default(),
}
}

Expand Down Expand Up @@ -117,6 +116,24 @@ impl<'w> AnalysisContext<'w> {
}
}

/// Resolve the real path for a file id.
pub fn path_for_id(&self, id: TypstFileId) -> Result<PathBuf, FileError> {
if id.vpath().as_rootless_path() == Path::new("-") {
return Ok(PathBuf::from("-"));
}

// Determine the root path relative to which the file path
// will be resolved.
let root = match id.package() {
Some(spec) => self.world.registry.resolve(spec)?,
None => self.analysis.root.clone(),
};

// Join the path to the root. If it tries to escape, deny
// access. Note: It can still escape via symlinks.
id.vpath().resolve(&root).ok_or(FileError::AccessDenied)
}

/// Get the source of a file by file id.
pub fn source_by_id(&mut self, id: TypstFileId) -> FileResult<Source> {
self.get_mut(id);
Expand Down Expand Up @@ -173,6 +190,10 @@ impl<'w> AnalysisContext<'w> {
lsp_to_typst::range(position, self.analysis.position_encoding, src)
}

pub fn to_lsp_pos(&self, typst_offset: usize, src: &Source) -> LspPosition {
typst_to_lsp::offset_to_position(typst_offset, self.analysis.position_encoding, src)
}

pub fn to_lsp_range(&self, position: TypstRange, src: &Source) -> LspRange {
typst_to_lsp::range(position, src, self.analysis.position_encoding)
}
Expand Down
2 changes: 1 addition & 1 deletion crates/tinymist-query/src/analysis/track_values.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
//! Dynamic analysis of an expression or import statement.
use comemo::Track;
use ecow::*;
use typst::engine::{Engine, Route};
use typst::eval::{Tracer, Vm};
use typst::foundations::{Context, Label, Scopes, Styles, Value};
use typst::introspection::{Introspector, Locator};
use typst::model::{BibliographyElem, Document};
use typst::syntax::{ast, LinkedNode, Span, SyntaxKind};
use typst::World;
use typst_ts_core::typst::prelude::*;

/// Try to determine a set of possible values for an expression.
pub fn analyze_expr(world: &dyn World, node: &LinkedNode) -> EcoVec<(Value, Option<Styles>)> {
Expand Down
23 changes: 12 additions & 11 deletions crates/tinymist-query/src/completion.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::prelude::*;
use crate::{prelude::*, StatefulRequest};

#[derive(Debug, Clone)]
pub struct CompletionRequest {
Expand All @@ -7,16 +7,17 @@ pub struct CompletionRequest {
pub explicit: bool,
}

impl CompletionRequest {
pub fn request(
impl StatefulRequest for CompletionRequest {
type Response = CompletionResponse;

fn request(
self,
world: &TypstSystemWorld,
ctx: &mut AnalysisContext,
doc: Option<VersionedDocument>,
position_encoding: PositionEncoding,
) -> Option<CompletionResponse> {
) -> Option<Self::Response> {
let doc = doc.as_ref().map(|doc| doc.document.as_ref());
let source = get_suitable_source_in_workspace(world, &self.path).ok()?;
let cursor = lsp_to_typst::position(self.position, position_encoding, &source)?;
let source = ctx.source_by_path(&self.path).ok()?;
let cursor = ctx.to_typst_pos(self.position, &source)?;

// Please see <https://github.com/nvarner/typst-lsp/commit/2d66f26fb96ceb8e485f492e5b81e9db25c3e8ec>
//
Expand All @@ -33,10 +34,10 @@ impl CompletionRequest {
// assume that the completion is not explicit.
let explicit = false;

let (offset, completions) = typst_ide::autocomplete(world, doc, &source, cursor, explicit)?;
let (offset, completions) =
typst_ide::autocomplete(ctx.world, doc, &source, cursor, explicit)?;

let lsp_start_position =
typst_to_lsp::offset_to_position(offset, position_encoding, &source);
let lsp_start_position = ctx.to_lsp_pos(offset, &source);
let replace_range = LspRange::new(lsp_start_position, self.position);
Some(typst_to_lsp::completions(&completions, replace_range).into())
}
Expand Down
2 changes: 1 addition & 1 deletion crates/tinymist-query/src/diagnostics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ fn diagnostic_related_information(
Ok(tracepoints)
}

fn diagnostic_span_id(typst_diagnostic: &TypstDiagnostic) -> Option<(FileId, TypstSpan)> {
fn diagnostic_span_id(typst_diagnostic: &TypstDiagnostic) -> Option<(TypstFileId, TypstSpan)> {
iter::once(typst_diagnostic.span)
.chain(typst_diagnostic.trace.iter().map(|trace| trace.span))
.find_map(|span| Some((span.id()?, span)))
Expand Down
4 changes: 2 additions & 2 deletions crates/tinymist-query/src/document_symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,10 +57,10 @@ mod tests {

#[test]
fn test() {
snapshot_testing("document_symbols", &|world, path| {
snapshot_testing("document_symbols", &|ctx, path| {
let request = DocumentSymbolRequest { path: path.clone() };

let source = get_suitable_source_in_workspace(world, &path).unwrap();
let source = ctx.source_by_path(&path).unwrap();

let result = request.request(source, PositionEncoding::Utf16);
assert_snapshot!(JsonRepr::new_redacted(result.unwrap(), &REDACT_LOC));
Expand Down
2 changes: 1 addition & 1 deletion crates/tinymist-query/src/folding_range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ mod tests {
line_folding_only: true,
};

let source = get_suitable_source_in_workspace(world, &path).unwrap();
let source = world.source_by_path(&path).unwrap();

let result = request.request(source, PositionEncoding::Utf16);
assert_snapshot!(JsonRepr::new_pure(result.unwrap()));
Expand Down
2 changes: 1 addition & 1 deletion crates/tinymist-query/src/goto_declaration.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ impl SyntaxRequest for GotoDeclarationRequest {
let ref_id = source.id();
let ref_source = &source;

let span_path = ctx.world.path_for_id(ref_id).ok()?;
let span_path = ctx.path_for_id(ref_id).ok()?;
let range = ctx.to_lsp_range(ref_range, ref_source);

let uri = Url::from_file_path(span_path).ok()?;
Expand Down
6 changes: 3 additions & 3 deletions crates/tinymist-query/src/goto_definition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::ops::Range;

use log::debug;
use typst::foundations::Value;
use typst_ts_core::TypstFileId;
use typst::syntax::FileId as TypstFileId;

use crate::{
prelude::*,
Expand Down Expand Up @@ -53,7 +53,7 @@ impl SyntaxRequest for GotoDefinitionRequest {

let def = find_definition(ctx, source.clone(), deref_target)?;

let span_path = ctx.world.path_for_id(def.fid).ok()?;
let span_path = ctx.path_for_id(def.fid).ok()?;
let uri = Url::from_file_path(span_path).ok()?;

let span_source = ctx.source_by_id(def.fid).ok()?;
Expand Down Expand Up @@ -221,7 +221,7 @@ mod tests {

#[test]
fn test() {
snapshot_testing2("goto_definition", &|world, path| {
snapshot_testing("goto_definition", &|world, path| {
let source = world.source_by_path(&path).unwrap();

let request = GotoDefinitionRequest {
Expand Down
Loading

0 comments on commit cc1f418

Please sign in to comment.