Return correct path and line in query errors from the CLI
This commit is contained in:
parent
297e2bcb28
commit
518916f221
5 changed files with 372 additions and 234 deletions
|
|
@ -5,12 +5,13 @@ use regex::{Regex, RegexBuilder};
|
|||
use serde_derive::Deserialize;
|
||||
use std::collections::HashMap;
|
||||
use std::io::BufReader;
|
||||
use std::ops::Range;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::Command;
|
||||
use std::sync::Mutex;
|
||||
use std::time::SystemTime;
|
||||
use std::{fs, mem};
|
||||
use tree_sitter::Language;
|
||||
use tree_sitter::{Language, QueryError};
|
||||
use tree_sitter_highlight::HighlightConfiguration;
|
||||
use tree_sitter_tags::TagsConfiguration;
|
||||
|
||||
|
|
@ -543,13 +544,32 @@ impl Loader {
|
|||
|
||||
impl<'a> LanguageConfiguration<'a> {
|
||||
pub fn highlight_config(&self, language: Language) -> Result<Option<&HighlightConfiguration>> {
|
||||
fn include_path_in_error<'a>(
|
||||
mut error: QueryError,
|
||||
ranges: &'a Vec<(String, Range<usize>)>,
|
||||
source: &str,
|
||||
start_offset: usize,
|
||||
) -> (&'a str, QueryError) {
|
||||
let offset = error.offset - start_offset;
|
||||
let (path, range) = ranges
|
||||
.iter()
|
||||
.find(|(_, range)| range.contains(&offset))
|
||||
.unwrap();
|
||||
error.row = source[range.start..offset]
|
||||
.chars()
|
||||
.filter(|c| *c == '\n')
|
||||
.count();
|
||||
(path.as_ref(), error)
|
||||
}
|
||||
|
||||
self.highlight_config
|
||||
.get_or_try_init(|| {
|
||||
let highlights_query =
|
||||
let (highlights_query, highlight_ranges) =
|
||||
self.read_queries(&self.highlights_filenames, "highlights.scm")?;
|
||||
let injections_query =
|
||||
let (injections_query, injection_ranges) =
|
||||
self.read_queries(&self.injections_filenames, "injections.scm")?;
|
||||
let locals_query = self.read_queries(&self.locals_filenames, "locals.scm")?;
|
||||
let (locals_query, locals_ranges) =
|
||||
self.read_queries(&self.locals_filenames, "locals.scm")?;
|
||||
|
||||
if highlights_query.is_empty() {
|
||||
Ok(None)
|
||||
|
|
@ -560,9 +580,25 @@ impl<'a> LanguageConfiguration<'a> {
|
|||
&injections_query,
|
||||
&locals_query,
|
||||
)
|
||||
.map_err(Error::wrap(|| {
|
||||
format!("Failed to load queries in {:?}", self.root_path)
|
||||
}))?;
|
||||
.map_err(|error| {
|
||||
if error.offset < injections_query.len() {
|
||||
include_path_in_error(error, &injection_ranges, &injections_query, 0)
|
||||
} else if error.offset < injections_query.len() + locals_query.len() {
|
||||
include_path_in_error(
|
||||
error,
|
||||
&locals_ranges,
|
||||
&locals_query,
|
||||
injections_query.len(),
|
||||
)
|
||||
} else {
|
||||
include_path_in_error(
|
||||
error,
|
||||
&highlight_ranges,
|
||||
&highlights_query,
|
||||
injections_query.len() + locals_query.len(),
|
||||
)
|
||||
}
|
||||
})?;
|
||||
let mut all_highlight_names = self.highlight_names.lock().unwrap();
|
||||
if self.use_all_highlight_names {
|
||||
for capture_name in result.query.capture_names() {
|
||||
|
|
@ -581,8 +617,8 @@ impl<'a> LanguageConfiguration<'a> {
|
|||
pub fn tags_config(&self, language: Language) -> Result<Option<&TagsConfiguration>> {
|
||||
self.tags_config
|
||||
.get_or_try_init(|| {
|
||||
let tags_query = self.read_queries(&self.tags_filenames, "tags.scm")?;
|
||||
let locals_query = self.read_queries(&self.locals_filenames, "locals.scm")?;
|
||||
let (tags_query, _) = self.read_queries(&self.tags_filenames, "tags.scm")?;
|
||||
let (locals_query, _) = self.read_queries(&self.locals_filenames, "locals.scm")?;
|
||||
if tags_query.is_empty() {
|
||||
Ok(None)
|
||||
} else {
|
||||
|
|
@ -596,27 +632,34 @@ impl<'a> LanguageConfiguration<'a> {
|
|||
.map(Option::as_ref)
|
||||
}
|
||||
|
||||
fn read_queries(&self, paths: &Option<Vec<String>>, default_path: &str) -> Result<String> {
|
||||
fn read_queries(
|
||||
&self,
|
||||
paths: &Option<Vec<String>>,
|
||||
default_path: &str,
|
||||
) -> Result<(String, Vec<(String, Range<usize>)>)> {
|
||||
let mut query = String::new();
|
||||
let mut path_ranges = Vec::new();
|
||||
if let Some(paths) = paths.as_ref() {
|
||||
let mut query = String::new();
|
||||
for path in paths {
|
||||
let path = self.root_path.join(path);
|
||||
query += &fs::read_to_string(&path).map_err(Error::wrap(|| {
|
||||
let abs_path = self.root_path.join(path);
|
||||
let prev_query_len = query.len();
|
||||
query += &fs::read_to_string(&abs_path).map_err(Error::wrap(|| {
|
||||
format!("Failed to read query file {:?}", path)
|
||||
}))?;
|
||||
path_ranges.push((path.clone(), prev_query_len..query.len()));
|
||||
}
|
||||
Ok(query)
|
||||
} else {
|
||||
let queries_path = self.root_path.join("queries");
|
||||
let path = queries_path.join(default_path);
|
||||
if path.exists() {
|
||||
fs::read_to_string(&path).map_err(Error::wrap(|| {
|
||||
query = fs::read_to_string(&path).map_err(Error::wrap(|| {
|
||||
format!("Failed to read query file {:?}", path)
|
||||
}))
|
||||
} else {
|
||||
Ok(String::new())
|
||||
}))?;
|
||||
path_ranges.push((default_path.to_string(), 0..query.len()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok((query, path_ranges))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue