Add unit test for tagging via C API. Fix docs handling
This commit is contained in:
parent
e3e1bdba75
commit
651fa38c93
4 changed files with 211 additions and 76 deletions
|
|
@ -1,30 +1,56 @@
|
|||
use super::helpers::allocations;
|
||||
use super::helpers::fixtures::get_language;
|
||||
use std::ffi::CString;
|
||||
use std::{ptr, slice, str};
|
||||
use tree_sitter_tags::c_lib as c;
|
||||
use tree_sitter_tags::{TagKind, TagsConfiguration, TagsContext};
|
||||
|
||||
const PYTHON_TAG_QUERY: &'static str = r#"
|
||||
((function_definition
|
||||
name: (identifier) @name
|
||||
body: (block . (expression_statement (string) @doc))) @function
|
||||
(strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)"))
|
||||
(function_definition
|
||||
name: (identifier) @name) @function
|
||||
((class_definition
|
||||
name: (identifier) @name
|
||||
body: (block . (expression_statement (string) @doc))) @class
|
||||
(strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)"))
|
||||
(class_definition
|
||||
name: (identifier) @name) @class
|
||||
(call
|
||||
function: (identifier) @name) @call
|
||||
"#;
|
||||
|
||||
const JS_TAG_QUERY: &'static str = r#"
|
||||
((*
|
||||
(comment)+ @doc .
|
||||
(class_declaration
|
||||
name: (identifier) @name) @class)
|
||||
(select-adjacent! @doc @class)
|
||||
(strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)"))
|
||||
|
||||
((*
|
||||
(comment)+ @doc .
|
||||
(method_definition
|
||||
name: (property_identifier) @name) @method)
|
||||
(select-adjacent! @doc @method)
|
||||
(strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)"))
|
||||
|
||||
((*
|
||||
(comment)+ @doc .
|
||||
(function_declaration
|
||||
name: (identifier) @name) @function)
|
||||
(select-adjacent! @doc @function)
|
||||
(strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)"))
|
||||
|
||||
(call_expression function: (identifier) @name) @call
|
||||
"#;
|
||||
|
||||
#[test]
|
||||
fn test_tags_python() {
|
||||
let language = get_language("python");
|
||||
let tags_config = TagsConfiguration::new(
|
||||
language,
|
||||
r#"
|
||||
((function_definition
|
||||
name: (identifier) @name
|
||||
body: (block . (expression_statement (string) @doc))) @function
|
||||
(strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)"))
|
||||
(function_definition
|
||||
name: (identifier) @name) @function
|
||||
((class_definition
|
||||
name: (identifier) @name
|
||||
body: (block . (expression_statement (string) @doc))) @class
|
||||
(strip! @doc "(^['\"\\s]*)|(['\"\\s]*$)"))
|
||||
(class_definition
|
||||
name: (identifier) @name) @class
|
||||
(call
|
||||
function: (identifier) @name) @call
|
||||
"#,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let tags_config = TagsConfiguration::new(language, PYTHON_TAG_QUERY, "").unwrap();
|
||||
|
||||
let source = br#"
|
||||
class Customer:
|
||||
|
|
@ -68,27 +94,7 @@ fn test_tags_python() {
|
|||
#[test]
|
||||
fn test_tags_javascript() {
|
||||
let language = get_language("javascript");
|
||||
let tags_config = TagsConfiguration::new(
|
||||
language,
|
||||
r#"
|
||||
((*
|
||||
(comment)+ @doc
|
||||
.
|
||||
(class_declaration
|
||||
name: (identifier) @name) @class)
|
||||
(select-adjacent! @doc @class)
|
||||
(strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)"))
|
||||
((*
|
||||
(comment)+ @doc
|
||||
.
|
||||
(method_definition
|
||||
name: (property_identifier) @name) @method)
|
||||
; (select-adjacent! @doc @method)
|
||||
(strip! @doc "(^[/\\*\\s]*)|([/\\*\\s]*$)"))
|
||||
"#,
|
||||
"",
|
||||
)
|
||||
.unwrap();
|
||||
let tags_config = TagsConfiguration::new(language, JS_TAG_QUERY, "").unwrap();
|
||||
|
||||
let mut tag_context = TagsContext::new();
|
||||
let source = br#"
|
||||
|
|
@ -132,6 +138,103 @@ fn test_tags_javascript() {
|
|||
assert_eq!(tags[2].docs, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_tags_via_c_api() {
|
||||
allocations::record(|| {
|
||||
let tagger = c::ts_tagger_new();
|
||||
let buffer = c::ts_tags_buffer_new();
|
||||
let scope_name = "source.js";
|
||||
let language = get_language("javascript");
|
||||
|
||||
let source_code = "
|
||||
var a = 1;
|
||||
|
||||
// one
|
||||
// two
|
||||
// three
|
||||
function b() {
|
||||
}
|
||||
|
||||
// four
|
||||
// five
|
||||
class C extends D {
|
||||
|
||||
}
|
||||
|
||||
b(a);"
|
||||
.lines()
|
||||
.skip(1)
|
||||
// remove extra indentation
|
||||
.map(|line| &line[line.len().min(12)..])
|
||||
.collect::<Vec<_>>()
|
||||
.join("\n");
|
||||
|
||||
let c_scope_name = CString::new(scope_name).unwrap();
|
||||
let result = c::ts_tagger_add_language(
|
||||
tagger,
|
||||
c_scope_name.as_ptr(),
|
||||
language,
|
||||
JS_TAG_QUERY.as_ptr(),
|
||||
ptr::null(),
|
||||
JS_TAG_QUERY.len() as u32,
|
||||
0,
|
||||
);
|
||||
assert_eq!(result, c::TSTagsError::Ok);
|
||||
|
||||
let result = c::ts_tagger_tag(
|
||||
tagger,
|
||||
c_scope_name.as_ptr(),
|
||||
source_code.as_ptr(),
|
||||
source_code.len() as u32,
|
||||
buffer,
|
||||
ptr::null(),
|
||||
);
|
||||
assert_eq!(result, c::TSTagsError::Ok);
|
||||
let tags = unsafe {
|
||||
slice::from_raw_parts(
|
||||
c::ts_tags_buffer_tags(buffer),
|
||||
c::ts_tags_buffer_tags_len(buffer) as usize,
|
||||
)
|
||||
};
|
||||
let docs = str::from_utf8(unsafe {
|
||||
slice::from_raw_parts(
|
||||
c::ts_tags_buffer_docs(buffer) as *const u8,
|
||||
c::ts_tags_buffer_docs_len(buffer) as usize,
|
||||
)
|
||||
})
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(
|
||||
tags.iter()
|
||||
.map(|tag| (
|
||||
tag.kind,
|
||||
&source_code[tag.name_start_byte as usize..tag.name_end_byte as usize],
|
||||
&source_code[tag.line_start_byte as usize..tag.line_end_byte as usize],
|
||||
&docs[tag.docs_start_byte as usize..tag.docs_end_byte as usize],
|
||||
))
|
||||
.collect::<Vec<_>>(),
|
||||
&[
|
||||
(
|
||||
c::TSTagKind::Function,
|
||||
"b",
|
||||
"function b() {",
|
||||
"one\ntwo\nthree"
|
||||
),
|
||||
(
|
||||
c::TSTagKind::Class,
|
||||
"C",
|
||||
"class C extends D {",
|
||||
"four\nfive"
|
||||
),
|
||||
(c::TSTagKind::Call, "b", "b(a);", "")
|
||||
]
|
||||
);
|
||||
|
||||
c::ts_tags_buffer_delete(buffer);
|
||||
c::ts_tagger_delete(tagger);
|
||||
});
|
||||
}
|
||||
|
||||
fn substr<'a>(source: &'a [u8], range: &std::ops::Range<usize>) -> &'a str {
|
||||
std::str::from_utf8(&source[range.clone()]).unwrap()
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue