mirror of
https://github.com/Myriad-Dreamin/tinymist.git
synced 2025-08-04 02:08:17 +00:00
feat: show rendered bibliography in bib hover and improve label hover (#1611)
* feat: show rendered bibliography in citation details * adjust code and revert changes to completions * refactor: refactor a bit * refactor: refactor two bit * feat: improve hover docs a bit * test: add hover tests for label and ref * test: add html tests --------- Co-authored-by: Myriad-Dreamin <camiyoru@gmail.com>
This commit is contained in:
parent
4265bc25bc
commit
a7a22c0d70
26 changed files with 312 additions and 50 deletions
|
@ -21,6 +21,7 @@ dashmap.workspace = true
|
|||
dirs.workspace = true
|
||||
ena.workspace = true
|
||||
ecow.workspace = true
|
||||
hayagriva.workspace = true
|
||||
if_chain.workspace = true
|
||||
itertools.workspace = true
|
||||
indexmap.workspace = true
|
||||
|
@ -55,7 +56,6 @@ unscanny.workspace = true
|
|||
walkdir.workspace = true
|
||||
yaml-rust2.workspace = true
|
||||
|
||||
|
||||
[dev-dependencies]
|
||||
insta.workspace = true
|
||||
serde.workspace = true
|
||||
|
|
|
@ -1,29 +1,38 @@
|
|||
use typst::foundations::Bytes;
|
||||
use indexmap::IndexMap;
|
||||
use typst::{foundations::Bytes, model::CslStyle};
|
||||
use yaml_rust2::{parser::Event, parser::MarkedEventReceiver, scanner::Marker};
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
pub(crate) fn bib_info(files: EcoVec<(TypstFileId, Bytes)>) -> Option<Arc<BibInfo>> {
|
||||
pub(crate) fn bib_info(
|
||||
csl_style: CslStyle,
|
||||
files: impl Iterator<Item = (TypstFileId, Bytes)>,
|
||||
) -> Option<Arc<BibInfo>> {
|
||||
let mut worker = BibWorker {
|
||||
info: BibInfo::default(),
|
||||
info: BibInfo {
|
||||
csl_style,
|
||||
entries: IndexMap::new(),
|
||||
},
|
||||
};
|
||||
|
||||
// We might have multiple bib/yaml files
|
||||
for (file_id, content) in files.clone() {
|
||||
for (file_id, content) in files {
|
||||
worker.analyze_path(file_id, content);
|
||||
}
|
||||
|
||||
let info = Arc::new(worker.info);
|
||||
|
||||
crate::log_debug_ct!("bib analysis: {files:?} -> {info:?}");
|
||||
crate::log_debug_ct!("bib analysis: {info:?}");
|
||||
Some(info)
|
||||
}
|
||||
|
||||
/// The bibliography information.
|
||||
#[derive(Debug, Default)]
|
||||
#[derive(Debug)]
|
||||
pub struct BibInfo {
|
||||
/// The using CSL style.
|
||||
pub csl_style: CslStyle,
|
||||
/// The bibliography entries.
|
||||
pub entries: indexmap::IndexMap<String, BibEntry>,
|
||||
pub entries: IndexMap<String, BibEntry>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -31,6 +40,7 @@ pub struct BibEntry {
|
|||
pub file_id: TypstFileId,
|
||||
pub name_range: Range<usize>,
|
||||
pub range: Range<usize>,
|
||||
pub raw_entry: Option<hayagriva::Entry>,
|
||||
}
|
||||
|
||||
struct BibWorker {
|
||||
|
@ -42,15 +52,28 @@ impl BibWorker {
|
|||
let file_extension = file_id.vpath().as_rooted_path().extension()?.to_str()?;
|
||||
let content = std::str::from_utf8(&content).ok()?;
|
||||
|
||||
match file_extension.to_lowercase().as_str() {
|
||||
"yml" | "yaml" => self.yaml_bib(file_id, content),
|
||||
// Reparse the content to get all entries
|
||||
let bib = match file_extension.to_lowercase().as_str() {
|
||||
"yml" | "yaml" => {
|
||||
self.yaml_bib(file_id, content);
|
||||
|
||||
hayagriva::io::from_yaml_str(content).ok()?
|
||||
}
|
||||
"bib" => {
|
||||
let bibliography = biblatex::RawBibliography::parse(content).ok()?;
|
||||
self.tex_bib(file_id, bibliography)
|
||||
self.tex_bib(file_id, bibliography);
|
||||
|
||||
hayagriva::io::from_biblatex_str(content).ok()?
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
for entry in bib {
|
||||
if let Some(stored_entry) = self.info.entries.get_mut(entry.key()) {
|
||||
stored_entry.raw_entry = Some(entry);
|
||||
}
|
||||
}
|
||||
|
||||
Some(())
|
||||
}
|
||||
|
||||
|
@ -66,6 +89,7 @@ impl BibWorker {
|
|||
file_id,
|
||||
name_range: name.span,
|
||||
range: entry.span,
|
||||
raw_entry: None,
|
||||
};
|
||||
self.info.entries.insert(name.v.to_owned(), entry);
|
||||
}
|
||||
|
@ -172,6 +196,7 @@ impl YamlBib {
|
|||
file_id,
|
||||
name_range,
|
||||
range,
|
||||
raw_entry: None,
|
||||
};
|
||||
Some((name.value, entry))
|
||||
};
|
||||
|
@ -209,8 +234,8 @@ Euclid2:
|
|||
FileId::new_fake(VirtualPath::new(Path::new("test.yml"))),
|
||||
);
|
||||
assert_eq!(bib.entries.len(), 2);
|
||||
insta::assert_snapshot!(bib_snap(&bib.entries[0]), @r###"("Euclid", BibEntry { file_id: /test.yml, name_range: 1..7, range: 1..63 })"###);
|
||||
insta::assert_snapshot!(bib_snap(&bib.entries[1]), @r###"("Euclid2", BibEntry { file_id: /test.yml, name_range: 63..70, range: 63..126 })"###);
|
||||
insta::assert_snapshot!(bib_snap(&bib.entries[0]), @r###"("Euclid", BibEntry { file_id: /test.yml, name_range: 1..7, range: 1..63, raw_entry: None })"###);
|
||||
insta::assert_snapshot!(bib_snap(&bib.entries[1]), @r###"("Euclid2", BibEntry { file_id: /test.yml, name_range: 63..70, range: 63..126, raw_entry: None })"###);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -1,9 +1,8 @@
|
|||
//! Linked definition analysis
|
||||
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use typst::foundations::{IntoValue, Label, Selector, Type};
|
||||
use typst::foundations::{Label, Selector, Type};
|
||||
use typst::introspection::Introspector;
|
||||
use typst::model::BibliographyElem;
|
||||
|
||||
use super::{prelude::*, InsTy, SharedContext};
|
||||
use crate::syntax::{Decl, DeclExpr, Expr, ExprInfo, SyntaxClass, VarClass};
|
||||
|
@ -169,13 +168,7 @@ fn bib_definition(
|
|||
introspector: &Introspector,
|
||||
key: &str,
|
||||
) -> Option<Definition> {
|
||||
let bib_elem = BibliographyElem::find(introspector.track()).ok()?;
|
||||
let Value::Array(paths) = bib_elem.sources.clone().into_value() else {
|
||||
return None;
|
||||
};
|
||||
|
||||
let bib_paths = paths.into_iter().flat_map(|path| path.cast().ok());
|
||||
let bib_info = ctx.analyze_bib(bib_elem.span(), bib_paths)?;
|
||||
let bib_info = ctx.analyze_bib(introspector)?;
|
||||
|
||||
let entry = bib_info.entries.get(key)?;
|
||||
crate::log_debug_ct!("find_bib_definition: {key} => {entry:?}");
|
||||
|
|
|
@ -15,11 +15,13 @@ use tinymist_project::{LspComputeGraph, LspWorld};
|
|||
use tinymist_std::hash::{hash128, FxDashMap};
|
||||
use tinymist_std::typst::TypstDocument;
|
||||
use tinymist_world::debug_loc::DataSource;
|
||||
use tinymist_world::vfs::{FileId, PathResolution, WorkspaceResolver};
|
||||
use tinymist_world::vfs::{PathResolution, WorkspaceResolver};
|
||||
use tinymist_world::{EntryReader, DETACHED_ENTRY};
|
||||
use typst::diag::{eco_format, At, FileError, FileResult, SourceResult, StrResult};
|
||||
use typst::foundations::{Bytes, Module, Styles};
|
||||
use typst::foundations::{Bytes, IntoValue, Module, StyleChain, Styles};
|
||||
use typst::introspection::Introspector;
|
||||
use typst::layout::Position;
|
||||
use typst::model::BibliographyElem;
|
||||
use typst::syntax::package::{PackageManifest, PackageSpec};
|
||||
use typst::syntax::{Span, VirtualPath};
|
||||
use typst_shim::eval::{eval_compat, Eval};
|
||||
|
@ -884,17 +886,11 @@ impl SharedContext {
|
|||
}
|
||||
|
||||
/// Get bib info of a source file.
|
||||
pub fn analyze_bib(
|
||||
&self,
|
||||
span: Span,
|
||||
bib_paths: impl Iterator<Item = EcoString>,
|
||||
) -> Option<Arc<BibInfo>> {
|
||||
use comemo::Track;
|
||||
let w = &self.world;
|
||||
let w = (w as &dyn World).track();
|
||||
pub fn analyze_bib(&self, introspector: &Introspector) -> Option<Arc<BibInfo>> {
|
||||
let world = &self.world;
|
||||
let world = (world as &dyn World).track();
|
||||
|
||||
let fid = span.id()?;
|
||||
analyze_bib(w, bib_paths.collect(), fid)
|
||||
analyze_bib(world, introspector.track())
|
||||
}
|
||||
|
||||
/// Describe the item under the cursor.
|
||||
|
@ -1278,17 +1274,27 @@ fn ceil_char_boundary(text: &str, mut cursor: usize) -> usize {
|
|||
#[comemo::memoize]
|
||||
fn analyze_bib(
|
||||
world: Tracked<dyn World + '_>,
|
||||
bib_paths: EcoVec<EcoString>,
|
||||
elem_fid: FileId,
|
||||
introspector: Tracked<Introspector>,
|
||||
) -> Option<Arc<BibInfo>> {
|
||||
let files = bib_paths
|
||||
.iter()
|
||||
.flat_map(|bib_path| {
|
||||
let bib_fid = resolve_id_by_path(world.deref(), elem_fid, bib_path)?;
|
||||
let bib_elem = BibliographyElem::find(introspector).ok()?;
|
||||
|
||||
// todo: it doesn't respect the style chain which can be get from
|
||||
// `analyze_expr`
|
||||
let csl_style = bib_elem.style(StyleChain::default()).derived;
|
||||
|
||||
let Value::Array(paths) = bib_elem.sources.clone().into_value() else {
|
||||
return None;
|
||||
};
|
||||
let elem_fid = bib_elem.span().id()?;
|
||||
let files = paths
|
||||
.into_iter()
|
||||
.flat_map(|path| path.cast().ok())
|
||||
.flat_map(|bib_path: EcoString| {
|
||||
let bib_fid = resolve_id_by_path(world.deref(), elem_fid, &bib_path)?;
|
||||
Some((bib_fid, world.file(bib_fid).ok()?))
|
||||
})
|
||||
.collect::<EcoVec<_>>();
|
||||
bib_info(files)
|
||||
});
|
||||
|
||||
bib_info(csl_style, files)
|
||||
}
|
||||
|
||||
#[comemo::memoize]
|
||||
|
|
|
@ -4,7 +4,6 @@ pub use std::ops::Range;
|
|||
pub use std::path::Path;
|
||||
pub use std::sync::{Arc, LazyLock};
|
||||
|
||||
pub use comemo::Track;
|
||||
pub use ecow::*;
|
||||
pub use typst::foundations::{Func, Value};
|
||||
pub use typst::syntax::ast::{self, AstNode};
|
||||
|
|
56
crates/tinymist-query/src/bib.rs
Normal file
56
crates/tinymist-query/src/bib.rs
Normal file
|
@ -0,0 +1,56 @@
|
|||
use hayagriva::{
|
||||
BibliographyDriver, BibliographyRequest, BufWriteFormat, CitationItem, CitationRequest,
|
||||
ElemChildren,
|
||||
};
|
||||
|
||||
use crate::analysis::BibInfo;
|
||||
|
||||
pub(crate) struct RenderedBibCitation {
|
||||
pub citation: String,
|
||||
pub bib_item: String,
|
||||
}
|
||||
|
||||
/// Render the citation string in the bib with given CSL style.
|
||||
pub(crate) fn render_citation_string(
|
||||
bib_info: &BibInfo,
|
||||
key: &str,
|
||||
support_html: bool,
|
||||
) -> Option<RenderedBibCitation> {
|
||||
let entry = bib_info.entries.get(key)?;
|
||||
let raw_entry = entry.raw_entry.as_ref()?;
|
||||
|
||||
let mut driver = BibliographyDriver::new();
|
||||
|
||||
let locales = &[];
|
||||
driver.citation(CitationRequest::from_items(
|
||||
vec![CitationItem::with_entry(raw_entry)],
|
||||
bib_info.csl_style.get(),
|
||||
locales,
|
||||
));
|
||||
|
||||
let result = driver.finish(BibliographyRequest {
|
||||
style: bib_info.csl_style.get(),
|
||||
locale: None, // todo: get locale from CiteElem
|
||||
locale_files: locales,
|
||||
});
|
||||
let rendered_bib = result.bibliography?;
|
||||
|
||||
let format_elem = |elem: &ElemChildren| {
|
||||
let mut buf = String::new();
|
||||
elem.write_buf(
|
||||
&mut buf,
|
||||
if support_html {
|
||||
BufWriteFormat::Html
|
||||
} else {
|
||||
BufWriteFormat::Plain
|
||||
},
|
||||
)
|
||||
.ok()?;
|
||||
Some(buf)
|
||||
};
|
||||
|
||||
Some(RenderedBibCitation {
|
||||
citation: format_elem(&result.citations.first()?.citation)?,
|
||||
bib_item: format_elem(&rendered_bib.items.first()?.content)?,
|
||||
})
|
||||
}
|
15
crates/tinymist-query/src/fixtures/hover/label_bib.typ
Normal file
15
crates/tinymist-query/src/fixtures/hover/label_bib.typ
Normal file
|
@ -0,0 +1,15 @@
|
|||
/// path: references.bib
|
||||
@article{Russell:1908,
|
||||
Author = {Bertand Russell},
|
||||
Journal = {American Journal of Mathematics},
|
||||
Pages = {222--262},
|
||||
Title = {Mathematical logic based on the theory of types},
|
||||
Volume = 30,
|
||||
Year = 1908}
|
||||
|
||||
-----
|
||||
/// compile: true
|
||||
|
||||
#ref(/* position after */ <Russell:1908>)
|
||||
|
||||
#bibliography("references.bib")
|
|
@ -0,0 +1,16 @@
|
|||
/// path: references.bib
|
||||
@article{Russell:1908,
|
||||
Author = {Bertand Russell},
|
||||
Journal = {American Journal of Mathematics},
|
||||
Pages = {222--262},
|
||||
Title = {Mathematical logic based on the theory of types},
|
||||
Volume = 30,
|
||||
Year = 1908}
|
||||
|
||||
-----
|
||||
/// compile: true
|
||||
/// html: false
|
||||
|
||||
#ref(/* position after */ <Russell:1908>)
|
||||
|
||||
#bibliography("references.bib")
|
|
@ -0,0 +1,4 @@
|
|||
/// compile: true
|
||||
|
||||
#let test1(body) = figure(body)
|
||||
#test1([Test1]) /* position after */ <fig:test1>
|
|
@ -0,0 +1,5 @@
|
|||
/// compile: true
|
||||
|
||||
#set heading(numbering: "1.1")
|
||||
= H /* position after */ <head>
|
||||
@head
|
15
crates/tinymist-query/src/fixtures/hover/ref_bib.typ
Normal file
15
crates/tinymist-query/src/fixtures/hover/ref_bib.typ
Normal file
|
@ -0,0 +1,15 @@
|
|||
/// path: references.bib
|
||||
@article{Russell:1908,
|
||||
Author = {Bertand Russell},
|
||||
Journal = {American Journal of Mathematics},
|
||||
Pages = {222--262},
|
||||
Title = {Mathematical logic based on the theory of types},
|
||||
Volume = 30,
|
||||
Year = 1908}
|
||||
|
||||
-----
|
||||
/// compile: true
|
||||
|
||||
/* position after */ @Russell:1908
|
||||
|
||||
#bibliography("references.bib")
|
16
crates/tinymist-query/src/fixtures/hover/ref_bib_no_html.typ
Normal file
16
crates/tinymist-query/src/fixtures/hover/ref_bib_no_html.typ
Normal file
|
@ -0,0 +1,16 @@
|
|||
/// path: references.bib
|
||||
@article{Russell:1908,
|
||||
Author = {Bertand Russell},
|
||||
Journal = {American Journal of Mathematics},
|
||||
Pages = {222--262},
|
||||
Title = {Mathematical logic based on the theory of types},
|
||||
Volume = 30,
|
||||
Year = 1908}
|
||||
|
||||
-----
|
||||
/// compile: true
|
||||
/// html: false
|
||||
|
||||
/* position after */ @Russell:1908
|
||||
|
||||
#bibliography("references.bib")
|
5
crates/tinymist-query/src/fixtures/hover/ref_figure.typ
Normal file
5
crates/tinymist-query/src/fixtures/hover/ref_figure.typ
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// compile: true
|
||||
|
||||
#let test1(body) = figure(body)
|
||||
#test1([Test1]) <fig:test1>
|
||||
/* position after */ @fig:test1
|
5
crates/tinymist-query/src/fixtures/hover/ref_heading.typ
Normal file
5
crates/tinymist-query/src/fixtures/hover/ref_heading.typ
Normal file
|
@ -0,0 +1,5 @@
|
|||
/// compile: true
|
||||
|
||||
#set heading(numbering: "1.1")
|
||||
= H /* position after */ <head>
|
||||
@head
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/label_bib.typ
|
||||
---
|
||||
{
|
||||
"contents": "Bibliography: `Russell:1908` [1]\n\n---\n\nB. Russell, Mathematical logic based on the theory of types, <span style=\"font-style: italic;\">American Journal of Mathematics</span>, 30, 222–262, 1908.",
|
||||
"range": "2:26:2:40"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/label_bib_no_html.typ
|
||||
---
|
||||
{
|
||||
"contents": "Bibliography: `Russell:1908` [1]\n\n---\n\nB. Russell, Mathematical logic based on the theory of types, American Journal of Mathematics, 30, 222–262, 1908.",
|
||||
"range": "3:26:3:40"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/label_figure.typ
|
||||
---
|
||||
{
|
||||
"contents": "Label: `fig:test1`\n",
|
||||
"range": "3:37:3:48"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/label_heading.typ
|
||||
---
|
||||
{
|
||||
"contents": "Label: `head`\n",
|
||||
"range": "3:25:3:31"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/ref_bib.typ
|
||||
---
|
||||
{
|
||||
"contents": "Bibliography: `Russell:1908` [1]\n\n---\n\nB. Russell, Mathematical logic based on the theory of types, <span style=\"font-style: italic;\">American Journal of Mathematics</span>, 30, 222–262, 1908.",
|
||||
"range": "2:21:2:34"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/ref_bib_no_html.typ
|
||||
---
|
||||
{
|
||||
"contents": "Bibliography: `Russell:1908` [1]\n\n---\n\nB. Russell, Mathematical logic based on the theory of types, American Journal of Mathematics, 30, 222–262, 1908.",
|
||||
"range": "3:21:3:34"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/ref_figure.typ
|
||||
---
|
||||
{
|
||||
"contents": "Ref: `fig:test1`\n\n\n---\n\n```typc\nfigure(\n body: [Test1],\n placement: none,\n scope: \"column\",\n caption: none,\n kind: image,\n supplement: [Figure],\n numbering: \"1\",\n gap: 0.65em,\n outlined: true,\n counter: counter(figure.where(kind: image)),\n)\n```",
|
||||
"range": "4:21:4:31"
|
||||
}
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
source: crates/tinymist-query/src/hover.rs
|
||||
expression: "JsonRepr::new_redacted(result, &REDACT_LOC)"
|
||||
input_file: crates/tinymist-query/src/fixtures/hover/ref_heading.typ
|
||||
---
|
||||
{
|
||||
"contents": "Label: `head`\n",
|
||||
"range": "3:25:3:31"
|
||||
}
|
|
@ -5,6 +5,7 @@ use typst::foundations::repr::separated_list;
|
|||
use typst_shim::syntax::LinkedNodeExt;
|
||||
|
||||
use crate::analysis::get_link_exprs_in;
|
||||
use crate::bib::{render_citation_string, RenderedBibCitation};
|
||||
use crate::jump_from_cursor;
|
||||
use crate::prelude::*;
|
||||
use crate::upstream::{route_of_value, truncated_repr, Tooltip};
|
||||
|
@ -125,14 +126,26 @@ impl HoverWorker<'_> {
|
|||
use Decl::*;
|
||||
match def.decl.as_ref() {
|
||||
Label(..) => {
|
||||
self.def.push(format!("Label: {}\n", def.name()));
|
||||
// todo: type repr
|
||||
if let Some(val) = def.term.as_ref().and_then(|v| v.value()) {
|
||||
self.def.push(truncated_repr(&val).into());
|
||||
self.def.push(format!("Ref: `{}`\n", def.name()));
|
||||
self.def
|
||||
.push(format!("```typc\n{}\n```", truncated_repr(&val)));
|
||||
} else {
|
||||
self.def.push(format!("Label: `{}`\n", def.name()));
|
||||
}
|
||||
}
|
||||
BibEntry(..) => {
|
||||
self.def.push(format!("Bibliography: @{}", def.name()));
|
||||
if let Some(details) = try_get_bib_details(&self.doc, self.ctx, def.name()) {
|
||||
self.def.push(format!(
|
||||
"Bibliography: `{}` {}",
|
||||
def.name(),
|
||||
details.citation
|
||||
));
|
||||
self.def.push(details.bib_item);
|
||||
} else {
|
||||
// fallback: no additional information
|
||||
self.def.push(format!("Bibliography: `{}`", def.name()));
|
||||
}
|
||||
}
|
||||
_ => {
|
||||
let sym_docs = self.ctx.def_docs(&def);
|
||||
|
@ -283,6 +296,17 @@ impl HoverWorker<'_> {
|
|||
}
|
||||
}
|
||||
|
||||
fn try_get_bib_details(
|
||||
doc: &Option<TypstDocument>,
|
||||
ctx: &LocalContext,
|
||||
name: &str,
|
||||
) -> Option<RenderedBibCitation> {
|
||||
let doc = doc.as_ref()?;
|
||||
let support_html = !ctx.shared.analysis.remove_html;
|
||||
let bib_info = ctx.analyze_bib(doc.introspector())?;
|
||||
render_citation_string(&bib_info, name, support_html)
|
||||
}
|
||||
|
||||
fn push_result_ty(
|
||||
name: &str,
|
||||
ty_repr: Option<&(EcoString, EcoString, EcoString)>,
|
||||
|
@ -396,13 +420,16 @@ mod tests {
|
|||
snapshot_testing("hover", &|ctx, path| {
|
||||
let source = ctx.source_by_path(&path).unwrap();
|
||||
|
||||
let docs = find_module_level_docs(&source).unwrap_or_default();
|
||||
let properties = get_test_properties(&docs);
|
||||
let graph = compile_doc_for_test(ctx, &properties);
|
||||
|
||||
let request = HoverRequest {
|
||||
path: path.clone(),
|
||||
position: find_test_position(&source),
|
||||
};
|
||||
|
||||
let snap = WorldComputeGraph::from_world(ctx.world.clone());
|
||||
let result = request.request(ctx, snap);
|
||||
let result = request.request(ctx, graph);
|
||||
assert_snapshot!(JsonRepr::new_redacted(result, &REDACT_LOC));
|
||||
});
|
||||
}
|
||||
|
|
|
@ -56,6 +56,7 @@ mod adt;
|
|||
mod lsp_typst_boundary;
|
||||
mod prelude;
|
||||
|
||||
mod bib;
|
||||
mod check;
|
||||
mod code_action;
|
||||
mod code_context;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue