Skip to content

Commit

Permalink
Provide document links for imports
Browse files Browse the repository at this point in the history
  • Loading branch information
pfoerster committed Apr 16, 2020
1 parent 6facbe3 commit e316522
Show file tree
Hide file tree
Showing 4 changed files with 128 additions and 22 deletions.
8 changes: 8 additions & 0 deletions crates/texlab_syntax/src/latex/analysis.rs
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,14 @@ pub struct Import {
}

impl Import {
pub fn dir<'a>(&self, tree: &'a Tree) -> &'a Token {
tree.extract_word(self.parent, GroupKind::Group, 0).unwrap()
}

pub fn file<'a>(&self, tree: &'a Tree) -> &'a Token {
tree.extract_word(self.parent, GroupKind::Group, 1).unwrap()
}

fn parse(ctx: SymbolContext) -> Vec<Self> {
ctx.commands
.iter()
Expand Down
94 changes: 94 additions & 0 deletions src/link/latex_import.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
use futures_boxed::boxed;
use texlab_feature::{DocumentContent, FeatureProvider, FeatureRequest};
use texlab_protocol::{DocumentLink, DocumentLinkParams};
use texlab_syntax::{latex, SyntaxNode};

#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)]
pub struct LatexImportLinkProvider;

impl FeatureProvider for LatexImportLinkProvider {
type Params = DocumentLinkParams;
type Output = Vec<DocumentLink>;

#[boxed]
async fn execute<'a>(&'a self, req: &'a FeatureRequest<Self::Params>) -> Self::Output {
if let DocumentContent::Latex(table) = &req.current().content {
table
.imports
.iter()
.flat_map(|import| Self::resolve(req, table, import))
.collect()
} else {
Vec::new()
}
}
}

impl LatexImportLinkProvider {
fn resolve(
req: &FeatureRequest<DocumentLinkParams>,
table: &latex::SymbolTable,
import: &latex::Import,
) -> Vec<DocumentLink> {
let mut links = Vec::new();
let file = import.file(&table);
for target in &import.targets {
if let Some(link) = req.snapshot().find(target).map(|doc| DocumentLink {
range: file.range(),
target: doc.uri.clone().into(),
tooltip: None,
}) {
links.push(link);
break;
}
}
links
}
}

#[cfg(test)]
mod tests {
use super::*;
use texlab_feature::FeatureTester;
use texlab_protocol::{Range, RangeExt};

#[tokio::test]
async fn empty_latex_document_command() {
let actual_links = FeatureTester::new()
.file("main.tex", "")
.main("main.tex")
.test_link(LatexImportLinkProvider)
.await;

assert!(actual_links.is_empty());
}

#[tokio::test]
async fn empty_bibtex_document_command() {
let actual_links = FeatureTester::new()
.file("main.bib", "")
.main("main.bib")
.test_link(LatexImportLinkProvider)
.await;

assert!(actual_links.is_empty());
}

#[tokio::test]
async fn has_links() {
let actual_links = FeatureTester::new()
.file("foo.tex", r#"\import{bar/}{baz}"#)
.file("bar/baz.tex", r#""#)
.main("foo.tex")
.test_link(LatexImportLinkProvider)
.await;

let expected_links = vec![DocumentLink {
range: Range::new_simple(0, 14, 0, 17),
target: FeatureTester::uri("bar/baz.tex").into(),
tooltip: None,
}];

assert_eq!(actual_links, expected_links);
}
}
40 changes: 20 additions & 20 deletions src/link/latex_include.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,11 @@ impl FeatureProvider for LatexIncludeLinkProvider {
#[boxed]
async fn execute<'a>(&'a self, req: &'a FeatureRequest<Self::Params>) -> Self::Output {
if let DocumentContent::Latex(table) = &req.current().content {
return table
table
.includes
.iter()
.flat_map(|include| Self::resolve(req, table, include))
.collect();
.collect()
} else {
Vec::new()
}
Expand Down Expand Up @@ -55,42 +55,42 @@ mod tests {
use texlab_protocol::{Range, RangeExt};

#[tokio::test]
async fn has_links() {
async fn empty_latex_document_command() {
let actual_links = FeatureTester::new()
.file("foo.tex", r#"\input{bar.tex}"#)
.file("bar.tex", r#""#)
.main("foo.tex")
.file("main.tex", "")
.main("main.tex")
.test_link(LatexIncludeLinkProvider)
.await;

let expected_links = vec![DocumentLink {
range: Range::new_simple(0, 7, 0, 14),
target: FeatureTester::uri("bar.tex").into(),
tooltip: None,
}];

assert_eq!(actual_links, expected_links);
assert!(actual_links.is_empty());
}

#[tokio::test]
async fn no_links_latex() {
async fn empty_bibtex_document_command() {
let actual_links = FeatureTester::new()
.file("foo.tex", r#""#)
.main("foo.tex")
.file("main.bib", "")
.main("main.bib")
.test_link(LatexIncludeLinkProvider)
.await;

assert!(actual_links.is_empty());
}

#[tokio::test]
async fn no_links_bibtex() {
async fn has_links() {
let actual_links = FeatureTester::new()
.file("foo.bib", r#""#)
.main("foo.bib")
.file("foo.tex", r#"\input{bar.tex}"#)
.file("bar.tex", r#""#)
.main("foo.tex")
.test_link(LatexIncludeLinkProvider)
.await;

assert!(actual_links.is_empty());
let expected_links = vec![DocumentLink {
range: Range::new_simple(0, 7, 0, 14),
target: FeatureTester::uri("bar.tex").into(),
tooltip: None,
}];

assert_eq!(actual_links, expected_links);
}
}
8 changes: 6 additions & 2 deletions src/link/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod latex_import;
mod latex_include;

use self::latex_include::LatexIncludeLinkProvider;
use self::{latex_import::LatexImportLinkProvider, latex_include::LatexIncludeLinkProvider};
use futures_boxed::boxed;
use texlab_feature::{ConcatProvider, FeatureProvider, FeatureRequest};
use texlab_protocol::{DocumentLink, DocumentLinkParams};
Expand All @@ -12,7 +13,10 @@ pub struct LinkProvider {
impl LinkProvider {
pub fn new() -> Self {
Self {
provider: ConcatProvider::new(vec![Box::new(LatexIncludeLinkProvider)]),
provider: ConcatProvider::new(vec![
Box::new(LatexImportLinkProvider),
Box::new(LatexIncludeLinkProvider),
]),
}
}
}
Expand Down

0 comments on commit e316522

Please sign in to comment.