diff options
Diffstat (limited to 'support/texlab/src/features/link.rs')
-rw-r--r-- | support/texlab/src/features/link.rs | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/support/texlab/src/features/link.rs b/support/texlab/src/features/link.rs new file mode 100644 index 0000000000..a6016c9f76 --- /dev/null +++ b/support/texlab/src/features/link.rs @@ -0,0 +1,115 @@ +use cancellation::CancellationToken; +use lsp_types::{DocumentLink, DocumentLinkParams}; + +use crate::LineIndexExt; + +use super::FeatureRequest; + +pub fn find_document_links( + request: FeatureRequest<DocumentLinkParams>, + cancellation_token: &CancellationToken, +) -> Vec<DocumentLink> { + let mut links = Vec::new(); + let main_document = request.main_document(); + if let Some(data) = main_document.data.as_latex() { + for include in &data.extras.explicit_links { + for target in &include.targets { + if cancellation_token.is_canceled() { + return links; + } + + if request + .subset + .documents + .iter() + .any(|document| document.uri.as_ref() == target.as_ref()) + { + links.push(DocumentLink { + range: main_document + .line_index + .line_col_lsp_range(include.stem_range), + target: Some(target.as_ref().clone().into()), + tooltip: None, + data: None, + }); + break; + } + } + } + } + links +} + +#[cfg(test)] +mod tests { + use super::*; + + use lsp_types::Range; + + use crate::{features::testing::FeatureTester, RangeExt}; + + #[test] + fn test_empty_latex_document() { + let request = FeatureTester::builder() + .files(vec![("main.tex", "")]) + .main("main.tex") + .build() + .link(); + + let items = find_document_links(request, CancellationToken::none()); + assert!(items.is_empty()); + } + + #[test] + fn test_empty_bibtex_document() { + let request = FeatureTester::builder() + .files(vec![("main.bib", "")]) + .main("main.bib") + .build() + .link(); + + let items = find_document_links(request, CancellationToken::none()); + assert!(items.is_empty()); + } + + #[test] + fn test_includes() { + let tester = FeatureTester::builder() + .files(vec![("foo.tex", r#"\input{bar.tex}"#), ("bar.tex", r#""#)]) + .main("foo.tex") + .build(); + let target = tester.uri("bar.tex"); + + let actual_items = find_document_links(tester.link(), CancellationToken::none()); + + let expected_items = vec![DocumentLink { + range: Range::new_simple(0, 7, 0, 14), + target: Some(target.as_ref().clone().into()), + tooltip: None, + data: None, + }]; + assert_eq!(actual_items, expected_items); + } + + #[test] + fn test_imports() { + let tester = FeatureTester::builder() + .files(vec![ + ("foo.tex", r#"\import{bar/}{baz}"#), + ("bar/baz.tex", r#""#), + ]) + .main("foo.tex") + .build(); + let target = tester.uri("bar/baz.tex"); + + let actual_items = find_document_links(tester.link(), CancellationToken::none()); + + let expected_items = vec![DocumentLink { + range: Range::new_simple(0, 14, 0, 17), + target: Some(target.as_ref().clone().into()), + tooltip: None, + data: None, + }]; + assert_eq!(actual_items, expected_items); + } +} |