Merge pull request #708 from tree-sitter/add-tagger-error-detection

Add ts_tags_buffer_found_parse_error capabilities for error detection during tagging.
This commit is contained in:
Patrick Thomson 2020-08-05 14:07:31 -04:00 committed by GitHub
commit d5576e306c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 57 additions and 6 deletions

View file

@ -53,7 +53,7 @@ pub fn generate_tags(
let source = fs::read(path)?;
let t0 = Instant::now();
for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))? {
for tag in context.generate_tags(tags_config, &source, Some(&cancellation_flag))?.0 {
let tag = tag?;
if !quiet {
write!(

View file

@ -102,6 +102,7 @@ fn test_tags_python() {
let tags = tag_context
.generate_tags(&tags_config, source, None)
.unwrap()
.0
.collect::<Result<Vec<_>, _>>()
.unwrap();
@ -153,6 +154,7 @@ fn test_tags_javascript() {
let tags = tag_context
.generate_tags(&tags_config, source, None)
.unwrap()
.0
.collect::<Result<Vec<_>, _>>()
.unwrap();
@ -189,6 +191,7 @@ fn test_tags_columns_measured_in_utf16_code_units() {
let tag = tag_context
.generate_tags(&tags_config, source, None)
.unwrap()
.0
.next()
.unwrap()
.unwrap();
@ -229,6 +232,7 @@ fn test_tags_ruby() {
let tags = tag_context
.generate_tags(&tags_config, source.as_bytes(), None)
.unwrap()
.0
.collect::<Result<Vec<_>, _>>()
.unwrap();
@ -271,7 +275,7 @@ fn test_tags_cancellation() {
.generate_tags(&tags_config, source.as_bytes(), Some(&cancellation_flag))
.unwrap();
for (i, tag) in tags.enumerate() {
for (i, tag) in tags.0.enumerate() {
if i == 150 {
cancellation_flag.store(1, Ordering::SeqCst);
}
@ -293,6 +297,39 @@ fn test_invalid_capture() {
assert_eq!(e, Error::InvalidCapture("method".to_string()));
}
#[test]
fn test_tags_with_parse_error() {
let language = get_language("python");
let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
let mut tag_context = TagsContext::new();
let source = br#"
class Fine: pass
class Bad
"#;
let (tags, failed) = tag_context
.generate_tags(&tags_config, source, None)
.unwrap();
let newtags = tags.collect::<Result<Vec<_>, _>>().unwrap();
assert!(failed, "syntax error should have been detected");
assert_eq!(
newtags.iter()
.map(|t| (
substr(source, &t.name_range),
tags_config.syntax_type_name(t.syntax_type_id)
))
.collect::<Vec<_>>(),
&[
("Fine", "class"),
]
);
}
#[test]
fn test_tags_via_c_api() {
allocations::record(|| {

View file

@ -88,6 +88,9 @@ uint32_t ts_tags_buffer_docs_len(const TSTagsBuffer *);
// Get the syntax kinds for a scope.
const char **ts_tagger_syntax_kinds_for_scope_name(const TSTagger *, const char *scope_name, uint32_t *len);
// Determine whether a parse error was encountered while tagging.
bool ts_tags_buffer_found_parse_error(const TSTagsBuffer*);
#ifdef __cplusplus
}
#endif

View file

@ -55,6 +55,7 @@ pub struct TSTagsBuffer {
context: TagsContext,
tags: Vec<TSTag>,
docs: Vec<u8>,
errors_present: bool,
}
#[no_mangle]
@ -129,7 +130,10 @@ pub extern "C" fn ts_tagger_tag(
.context
.generate_tags(config, source_code, cancellation_flag)
{
Ok(tags) => tags,
Ok((tags, found_error)) => {
buffer.errors_present = found_error;
tags
}
Err(e) => {
return match e {
Error::InvalidLanguage => TSTagsError::InvalidLanguage,
@ -188,6 +192,7 @@ pub extern "C" fn ts_tags_buffer_new() -> *mut TSTagsBuffer {
context: TagsContext::new(),
tags: Vec::with_capacity(BUFFER_TAGS_RESERVE_CAPACITY),
docs: Vec::with_capacity(BUFFER_DOCS_RESERVE_CAPACITY),
errors_present: false,
}))
}
@ -220,6 +225,12 @@ pub extern "C" fn ts_tags_buffer_docs_len(this: *const TSTagsBuffer) -> u32 {
buffer.docs.len() as u32
}
#[no_mangle]
pub extern "C" fn ts_tags_buffer_found_parse_error(this: *const TSTagsBuffer) -> bool {
let buffer = unwrap_ptr(this);
buffer.errors_present
}
#[no_mangle]
pub extern "C" fn ts_tagger_syntax_kinds_for_scope_name(
this: *mut TSTagger,

View file

@ -255,7 +255,7 @@ impl TagsContext {
config: &'a TagsConfiguration,
source: &'a [u8],
cancellation_flag: Option<&'a AtomicUsize>,
) -> Result<impl Iterator<Item = Result<Tag, Error>> + 'a, Error> {
) -> Result<(impl Iterator<Item = Result<Tag, Error>> + 'a, bool), Error> {
self.parser
.set_language(config.language)
.map_err(|_| Error::InvalidLanguage)?;
@ -271,7 +271,7 @@ impl TagsContext {
.matches(&config.query, tree_ref.root_node(), move |node| {
&source[node.byte_range()]
});
Ok(TagsIter {
Ok((TagsIter {
_tree: tree,
matches,
source,
@ -285,7 +285,7 @@ impl TagsContext {
inherits: false,
local_defs: Vec::new(),
}],
})
}, tree_ref.root_node().has_error()))
}
}