mirror of
https://github.com/latex-lsp/texlab.git
synced 2025-12-23 09:19:21 +00:00
Improve performance of TeX file resolver
This commit is contained in:
parent
d99672c5bc
commit
f67e134088
3 changed files with 44 additions and 47 deletions
|
|
@ -13,7 +13,7 @@ const FNDB_TABLE_POINTER_OFFSET: usize = 4 * FNDB_WORD_SIZE;
|
|||
const FNDB_TABLE_SIZE_OFFSET: usize = 6 * FNDB_WORD_SIZE;
|
||||
const FNDB_ENTRY_SIZE: usize = 4 * FNDB_WORD_SIZE;
|
||||
|
||||
pub fn read_database(directory: &Path, root_directories: &[PathBuf]) -> Result<Vec<PathBuf>> {
|
||||
pub fn read_database(directory: &Path) -> Result<Vec<PathBuf>> {
|
||||
let database_directory = directory.join(DATABASE_PATH);
|
||||
if !database_directory.exists() {
|
||||
return Ok(Vec::new());
|
||||
|
|
@ -27,15 +27,13 @@ pub fn read_database(directory: &Path, root_directories: &[PathBuf]) -> Result<V
|
|||
|
||||
for file in files {
|
||||
let bytes = fs::read(file.path()).expect("Could not read fndb file");
|
||||
database.extend(
|
||||
parse_database(root_directories, &bytes).map_err(|_| Error::CorruptFileDatabase)?,
|
||||
);
|
||||
database.extend(parse_database(&bytes).map_err(|_| Error::CorruptFileDatabase)?);
|
||||
}
|
||||
|
||||
Ok(database)
|
||||
}
|
||||
|
||||
fn parse_database(root_directories: &[PathBuf], bytes: &[u8]) -> io::Result<Vec<PathBuf>> {
|
||||
fn parse_database(bytes: &[u8]) -> io::Result<Vec<PathBuf>> {
|
||||
let mut reader = Cursor::new(bytes);
|
||||
if reader.read_u32::<LittleEndian>()? != FNDB_SIGNATURE {
|
||||
return Err(io::Error::from(io::ErrorKind::InvalidData));
|
||||
|
|
@ -56,12 +54,8 @@ fn parse_database(root_directories: &[PathBuf], bytes: &[u8]) -> io::Result<Vec<
|
|||
let file_name = read_string(bytes, file_name_offset)?;
|
||||
let directory = read_string(bytes, directory_offset)?;
|
||||
|
||||
for root_directory in root_directories {
|
||||
let file = root_directory.join(directory).join(file_name);
|
||||
if file.is_file() {
|
||||
files.push(file.canonicalize().unwrap());
|
||||
}
|
||||
}
|
||||
let file = PathBuf::from(directory).join(file_name);
|
||||
files.push(file);
|
||||
}
|
||||
|
||||
Ok(files)
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
use crate::syntax::Language;
|
||||
use lazy_static::lazy_static;
|
||||
use std::collections::HashMap;
|
||||
use std::env;
|
||||
use std::ffi::OsString;
|
||||
use std::ffi::{OsStr, OsString};
|
||||
use std::path::PathBuf;
|
||||
use std::process::Command;
|
||||
use std::sync::Arc;
|
||||
|
|
@ -35,9 +36,34 @@ pub struct TexResolver {
|
|||
|
||||
impl TexResolver {
|
||||
fn load() -> Result<Self> {
|
||||
let directories = Self::find_root_directories()?;
|
||||
let kind = Self::detect_distribution(&directories)?;
|
||||
let files_by_name = Self::read_database(&directories, kind)?;
|
||||
let root_directories = Self::find_root_directories()?;
|
||||
let kind = Self::detect_distribution(&root_directories)?;
|
||||
let reader = match kind {
|
||||
TexDistributionKind::Texlive => texlive::read_database,
|
||||
TexDistributionKind::Miktex => miktex::read_database,
|
||||
};
|
||||
|
||||
let mut files_by_name = HashMap::new();
|
||||
for directory in &root_directories {
|
||||
let database = reader(directory)?
|
||||
.into_iter()
|
||||
.filter(|path| {
|
||||
path.extension()
|
||||
.and_then(OsStr::to_str)
|
||||
.and_then(Language::by_extension)
|
||||
.is_some()
|
||||
})
|
||||
.filter_map(|path| {
|
||||
root_directories
|
||||
.iter()
|
||||
.rev()
|
||||
.find_map(move |dir| dir.join(&path).canonicalize().ok())
|
||||
})
|
||||
.map(|path| (path.file_name().unwrap().to_owned(), path));
|
||||
|
||||
files_by_name.extend(database);
|
||||
}
|
||||
|
||||
Ok(Self { files_by_name })
|
||||
}
|
||||
|
||||
|
|
@ -58,7 +84,7 @@ impl TexResolver {
|
|||
Ok(String::from_utf8(output.stdout)
|
||||
.expect("Could not decode output from kpsewhich")
|
||||
.lines()
|
||||
.nth(0)
|
||||
.next()
|
||||
.expect("Invalid output from kpsewhich")
|
||||
.to_owned())
|
||||
}
|
||||
|
|
@ -74,24 +100,4 @@ impl TexResolver {
|
|||
|
||||
Err(Error::UnsupportedTexDistribution)
|
||||
}
|
||||
|
||||
fn read_database(
|
||||
root_directories: &[PathBuf],
|
||||
kind: TexDistributionKind,
|
||||
) -> Result<HashMap<OsString, PathBuf>> {
|
||||
let mut files_by_name = HashMap::new();
|
||||
for directory in root_directories {
|
||||
let database = match kind {
|
||||
TexDistributionKind::Texlive => texlive::read_database(&directory),
|
||||
TexDistributionKind::Miktex => miktex::read_database(&directory, root_directories),
|
||||
}?;
|
||||
|
||||
for file in database {
|
||||
let name = file.file_name().unwrap().to_owned();
|
||||
files_by_name.insert(name, file);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(files_by_name)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,24 +13,21 @@ pub fn read_database(directory: &Path) -> Result<Vec<PathBuf>> {
|
|||
}
|
||||
|
||||
let text = fs::read_to_string(file).expect("Could not read ls-R file");
|
||||
parse_database(&directory, text.lines()).map_err(|_| Error::CorruptFileDatabase)
|
||||
parse_database(text.lines()).map_err(|_| Error::CorruptFileDatabase)
|
||||
}
|
||||
|
||||
fn parse_database(root_directory: &Path, lines: Lines) -> io::Result<Vec<PathBuf>> {
|
||||
let mut files = Vec::new();
|
||||
let mut directory = PathBuf::new();
|
||||
fn parse_database(lines: Lines) -> io::Result<Vec<PathBuf>> {
|
||||
let mut paths = Vec::new();
|
||||
let mut directory = "";
|
||||
|
||||
for line in lines.filter(|x| !x.trim().is_empty() && !x.starts_with('%')) {
|
||||
if line.ends_with(':') {
|
||||
let path = &line[..line.len() - 1];
|
||||
directory = root_directory.join(path);
|
||||
directory = &line[..line.len() - 1];
|
||||
} else {
|
||||
let file = directory.join(line).canonicalize()?;
|
||||
if file.is_file() {
|
||||
files.push(file);
|
||||
}
|
||||
let path = PathBuf::from(directory).join(line);
|
||||
paths.push(path);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(files)
|
||||
Ok(paths)
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue