Skip to content

Commit

Permalink
Improve performance of workspace
Browse files Browse the repository at this point in the history
  • Loading branch information
pfoerster committed May 25, 2019
1 parent a6f859e commit d93db89
Show file tree
Hide file tree
Showing 13 changed files with 122 additions and 342 deletions.
4 changes: 2 additions & 2 deletions src/hover/latex_component.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ impl LatexComponentHoverProvider {
.includes
.iter()
.filter(|include| {
include.kind == LatexIncludeKind::Package
|| include.kind == LatexIncludeKind::Class
include.kind() == LatexIncludeKind::Package
|| include.kind() == LatexIncludeKind::Class
})
.find(|include| include.path().range().contains(request.params.position))
.map(|include| include.path().text())
Expand Down
2 changes: 1 addition & 1 deletion src/link/latex_include.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ impl LatexIncludeLinkProvider {
) -> Option<DocumentLink> {
request
.workspace
.resolve_document(&request.document.uri, include)
.find(include.target())
.map(|target| DocumentLink {
range: include.path().range(),
target: target.uri.clone(),
Expand Down
35 changes: 1 addition & 34 deletions src/syntax/latex/analysis/citation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl LatexCitation {
self.command.extract_word(0).unwrap()
}

pub fn parse(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
pub fn parse_all(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
let mut citations = Vec::new();
for command in commands {
if CITATION_COMMANDS.contains(&command.name.text()) && command.has_word(0) {
Expand Down Expand Up @@ -84,36 +84,3 @@ pub static CITATION_COMMANDS: &[&str] = &[
"\\Pnotecite",
"\\fnotecite",
];

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;

fn verify(text: &str, expected: Vec<&str>) {
let tree = LatexSyntaxTree::from(text);
let actual: Vec<&str> = tree
.citations
.iter()
.map(|citation| citation.key().text())
.collect();
assert_eq!(expected, actual);
}

#[test]
fn test_valid() {
verify("\\cite{foo}", vec!["foo"]);
verify("\\Cite{bar}", vec!["bar"]);
}

#[test]
fn test_invalid() {
verify("\\cite", vec![]);
verify("\\cite{}", vec![]);
}

#[test]
fn test_unrelated() {
verify("\\foo", vec![]);
verify("\\foo{bar}", vec![]);
}
}
25 changes: 5 additions & 20 deletions src/syntax/latex/analysis/command.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use crate::syntax::latex::ast::*;
use std::sync::Arc;

#[derive(Debug, PartialEq, Eq, Clone, Default)]
pub struct LatexCommandAnalyzer {
pub commands: Vec<Arc<LatexCommand>>,
}

impl LatexCommandAnalyzer {
pub fn new() -> Self {
LatexCommandAnalyzer {
commands: Vec::new(),
}
pub fn find(root: Arc<LatexRoot>) -> Vec<Arc<LatexCommand>> {
let mut analyzer = LatexCommandAnalyzer::default();
analyzer.visit_root(root);
analyzer.commands
}
}

Expand All @@ -29,19 +30,3 @@ impl LatexVisitor for LatexCommandAnalyzer {

fn visit_text(&mut self, _text: Arc<LatexText>) {}
}

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;

#[test]
fn test() {
let tree = LatexSyntaxTree::from("\\a[\\b]{\\c}{d}");
let commands: Vec<&str> = tree
.commands
.iter()
.map(|command| command.name.text())
.collect();
assert_eq!(vec!["\\a", "\\b", "\\c"], commands);
}
}
33 changes: 1 addition & 32 deletions src/syntax/latex/analysis/environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ impl LatexEnvironment {
}
}

pub fn parse(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
pub fn parse_all(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
let mut stack = Vec::new();
let mut environments = Vec::new();
for command in commands {
Expand All @@ -62,34 +62,3 @@ impl LatexEnvironment {
}

pub static ENVIRONMENT_COMMANDS: &[&str] = &["\\begin", "\\end"];

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;

#[test]
fn test_nested() {
let tree = LatexSyntaxTree::from("\\begin{foo}\\begin{bar}\\end{baz}\\end{qux}");
let environments = tree.environments;
assert_eq!(2, environments.len());
assert_eq!("bar", environments[0].left.name().unwrap().text());
assert_eq!("baz", environments[0].right.name().unwrap().text());
assert_eq!("foo", environments[1].left.name().unwrap().text());
assert_eq!("qux", environments[1].right.name().unwrap().text());
}

#[test]
fn test_empty_name() {
let tree = LatexSyntaxTree::from("\\begin{}\\end{}");
let environments = tree.environments;
assert_eq!(1, environments.len());
assert_eq!(None, environments[0].left.name());
assert_eq!(None, environments[0].right.name());
}

#[test]
fn test_ummatched() {
let tree = LatexSyntaxTree::from("\\end{foo} \\begin{bar}");
assert_eq!(tree.environments, Vec::new());
}
}
24 changes: 1 addition & 23 deletions src/syntax/latex/analysis/equation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ impl LatexEquation {
LatexEquation { left, right }
}

pub fn parse(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
pub fn parse_all(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
let mut equations = Vec::new();
let mut left = None;
for command in commands {
Expand All @@ -28,25 +28,3 @@ impl LatexEquation {
}

pub static EQUATION_COMMANDS: &[&str] = &["\\[", "\\]"];

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;
use crate::syntax::text::SyntaxNode;
use lsp_types::Range;

#[test]
fn test_matched() {
let tree = LatexSyntaxTree::from("\\[ foo \\]");
let equations = tree.equations;
assert_eq!(1, equations.len());
assert_eq!(Range::new_simple(0, 0, 0, 2), equations[0].left.range());
assert_eq!(Range::new_simple(0, 7, 0, 9), equations[0].right.range());
}

#[test]
fn test_unmatched() {
let tree = LatexSyntaxTree::from("\\] \\[");
assert_eq!(tree.equations, Vec::new());
}
}
127 changes: 60 additions & 67 deletions src/syntax/latex/analysis/include.rs
Original file line number Diff line number Diff line change
@@ -1,102 +1,95 @@
use crate::syntax::latex::ast::*;
use lsp_types::Uri;
use path_clean::PathClean;
use std::sync::Arc;

#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum LatexIncludeKind {
Package,
Class,
TexFile,
BibFile,
Package,
Class,
}

#[derive(Debug, PartialEq, Eq, Clone)]
pub struct LatexInclude {
pub command: Arc<LatexCommand>,
pub kind: LatexIncludeKind,
target: Option<Uri>,
}

impl LatexInclude {
pub fn path(&self) -> &LatexToken {
self.command.extract_word(0).unwrap()
}
fn parse(uri: &Uri, command: Arc<LatexCommand>) -> Option<Self> {
let mut include = LatexInclude {
command,
target: None,
};

pub fn new(command: Arc<LatexCommand>, kind: LatexIncludeKind) -> Self {
LatexInclude { command, kind }
let mut path = uri.to_file_path().ok()?;
path.pop();
path.push(include.path().text());
path = path.clean();
let has_extension = path.extension().is_some();
let mut path = path.to_str()?.to_owned();
if !has_extension {
path = format!("{}{}", path, include.extension());
}
include.target = Some(Uri::from_file_path(path).ok()?);
Some(include)
}

pub fn parse(commands: &[Arc<LatexCommand>]) -> (Vec<Self>, Vec<String>) {
pub fn parse_all(uri: &Uri, commands: &[Arc<LatexCommand>]) -> Vec<Self> {
let mut includes = Vec::new();
let mut components = Vec::new();
for command in commands {
let kind = match command.name.text() {
"\\include" | "\\input" => Some(LatexIncludeKind::TexFile),
"\\bibliography" | "\\addbibresource" => Some(LatexIncludeKind::BibFile),
"\\usepackage" => Some(LatexIncludeKind::Package),
"\\documentclass" => Some(LatexIncludeKind::Class),
_ => None,
};

if let Some(kind) = kind {
if command.has_word(0) {
let include = LatexInclude::new(Arc::clone(&command), kind);
match include.kind {
LatexIncludeKind::Package => {
components.push(format!("{}.sty", include.path().text()));
}
LatexIncludeKind::Class => {
components.push(format!("{}.cls", include.path().text()));
}
LatexIncludeKind::TexFile | LatexIncludeKind::BibFile => {}
}
if INCLUDE_COMMANDS.contains(&command.name.text()) && command.has_word(0) {
if let Some(include) = LatexInclude::parse(uri, Arc::clone(&command)) {
includes.push(include);
}
}
}
(includes, components)
includes
}
}

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;
pub fn target(&self) -> &Uri {
self.target.as_ref().unwrap()
}

fn verify(text: &str, includes: Vec<&str>, components: Vec<&str>) {
let tree = LatexSyntaxTree::from(text);
let actual_includes: Vec<&str> = tree
.includes
.iter()
.map(|include| include.path().text())
.collect();
assert_eq!(includes, actual_includes);
assert_eq!(components, tree.components);
pub fn path(&self) -> &LatexToken {
self.command.extract_word(0).unwrap()
}

#[test]
fn test_valid() {
verify("\\include{foo}", vec!["foo"], vec![]);
verify("\\bibliography{foo}", vec!["foo"], vec![]);
verify(
"\\usepackage{amsmath}",
vec!["amsmath"],
vec!["amsmath.sty"],
);
verify(
"\\documentclass{article}",
vec!["article"],
vec!["article.cls"],
);
pub fn kind(&self) -> LatexIncludeKind {
match self.command.name.text() {
"\\include" | "\\input" => LatexIncludeKind::TexFile,
"\\bibliography" | "\\addbibresource" => LatexIncludeKind::BibFile,
"\\usepackage" => LatexIncludeKind::Package,
"\\documentclass" => LatexIncludeKind::Class,
_ => unreachable!(),
}
}

#[test]
fn test_invalid() {
verify("\\include", vec![], vec![]);
verify("\\include{}", vec![], vec![]);
verify("\\include{foo bar}", vec![], vec![]);
pub fn name(&self) -> Option<String> {
match self.kind() {
LatexIncludeKind::TexFile | LatexIncludeKind::BibFile => None,
LatexIncludeKind::Package => Some(format!("{}.sty", self.path().text())),
LatexIncludeKind::Class => Some(format!("{}.cls", self.path().text())),
}
}

#[test]
fn test_unrelated() {
verify("\\foo", vec![], vec![]);
verify("\\foo{bar}", vec![], vec![]);
pub fn extension(&self) -> &'static str {
match self.kind() {
LatexIncludeKind::TexFile => ".tex",
LatexIncludeKind::BibFile => ".bib",
LatexIncludeKind::Package => ".sty",
LatexIncludeKind::Class => ".cls",
}
}
}

pub static INCLUDE_COMMANDS: &[&str] = &[
"\\include",
"\\input",
"\\bibliography",
"\\addbibresource",
"\\usepackage",
"\\documentclass",
];
35 changes: 1 addition & 34 deletions src/syntax/latex/analysis/label.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ impl LatexLabel {
}
}

pub fn parse(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
pub fn parse_all(commands: &[Arc<LatexCommand>]) -> Vec<Self> {
let mut labels = Vec::new();
for command in commands {
if command.has_word(0)
Expand All @@ -46,36 +46,3 @@ impl LatexLabel {
pub static LABEL_DEFINITION_COMMANDS: &[&str] = &["\\label"];

pub static LABEL_REFERENCE_COMMANDS: &[&str] = &["\\ref", "\\autoref", "\\eqref"];

#[cfg(test)]
mod tests {
use crate::syntax::latex::LatexSyntaxTree;

fn verify(text: &str, expected: Vec<&str>) {
let tree = LatexSyntaxTree::from(text);
let actual: Vec<&str> = tree
.labels
.iter()
.map(|label| label.name().text())
.collect();
assert_eq!(expected, actual);
}

#[test]
fn test_valid() {
verify("\\label{foo}", vec!["foo"]);
verify("\\ref{bar}", vec!["bar"]);
}

#[test]
fn test_invalid() {
verify("\\label", vec![]);
verify("\\label{}", vec![]);
}

#[test]
fn test_unrelated() {
verify("\\foo", vec![]);
verify("\\foo{bar}", vec![]);
}
}
Loading

0 comments on commit d93db89

Please sign in to comment.