This commit is contained in:
Max Brunsfeld 2020-03-06 13:24:03 -08:00
parent a3f0087b11
commit 680a9e0531
2 changed files with 104 additions and 38 deletions

View file

@ -9,10 +9,8 @@ fn test_tags_javascript() {
r#"
((function_definition
name: (identifier) @name
body: (block
. (string) @doc)) @function
body: (block . (string) @doc)) @function
(set! replace @doc "(^['\s]*)|(['\s]*$)"))
(function_definition
name: (identifier) @name) @function
(class_definition

View file

@ -1,12 +1,19 @@
use serde::{Serialize, Serializer};
use tree_sitter::{Language, Parser, Query, QueryCursor, QueryError};
use std::{ops, str};
use tree_sitter::{Language, Node, Parser, Point, Query, QueryCursor, QueryError};
/// Contains the data neeeded to compute tags for code written in a
/// particular language.
pub struct TagsConfiguration {
pub language: Language,
pub query: Query,
call_capture_index: Option<u32>,
class_capture_index: Option<u32>,
doc_capture_index: Option<u32>,
function_capture_index: Option<u32>,
locals_pattern_index: usize,
module_capture_index: Option<u32>,
name_capture_index: Option<u32>,
}
pub struct TagsContext {
@ -14,22 +21,10 @@ pub struct TagsContext {
cursor: QueryCursor,
}
#[derive(Debug, Serialize)]
pub struct Range {
pub start: i64,
pub end: i64,
}
#[derive(Debug, Serialize)]
pub struct Loc {
pub byte_range: Range,
pub span: Span,
}
#[derive(Debug, Serialize)]
pub struct Span {
pub start: Pos,
pub end: Pos,
pub byte_range: ops::Range<usize>,
pub span: ops::Range<Pos>,
}
#[derive(Debug, Serialize)]
@ -56,22 +51,6 @@ pub struct Tag<'a> {
pub docs: Option<&'a str>,
}
impl Serialize for TagKind {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
TagKind::Call => "Call",
TagKind::Module => "Module",
TagKind::Class => "Class",
TagKind::Method => "Method",
TagKind::Function => "Function",
}
.serialize(s)
}
}
impl TagsConfiguration {
pub fn new(
language: Language,
@ -89,10 +68,35 @@ impl TagsConfiguration {
}
}
let mut call_capture_index = None;
let mut class_capture_index = None;
let mut doc_capture_index = None;
let mut function_capture_index = None;
let mut module_capture_index = None;
let mut name_capture_index = None;
for (i, name) in query.capture_names().iter().enumerate() {
let index = match name.as_str() {
"call" => &mut call_capture_index,
"class" => &mut class_capture_index,
"doc" => &mut doc_capture_index,
"function" => &mut function_capture_index,
"module" => &mut module_capture_index,
"name" => &mut name_capture_index,
_ => continue,
};
*index = Some(i as u32);
}
Ok(TagsConfiguration {
language,
query,
locals_pattern_index,
function_capture_index,
class_capture_index,
module_capture_index,
doc_capture_index,
call_capture_index,
name_capture_index,
})
}
}
@ -105,7 +109,11 @@ impl TagsContext {
}
}
pub fn generate_tags(&mut self, config: &TagsConfiguration, source: &[u8]) -> Vec<Tag> {
pub fn generate_tags<'a>(
&mut self,
config: &TagsConfiguration,
source: &'a [u8],
) -> Vec<Tag<'a>> {
self.parser
.set_language(config.language)
.expect("Incompatible language");
@ -119,10 +127,70 @@ impl TagsContext {
&source[node.byte_range()]
});
matches
.map(|mat| {
for capture in mat.captures {}
unimplemented!();
.filter_map(|mat| {
let mut call_node = None;
let mut doc_node = None;
let mut class_node = None;
let mut function_node = None;
let mut module_node = None;
let mut name_node = None;
for capture in mat.captures {
let index = Some(capture.index);
let node = Some(capture.node);
if index == config.call_capture_index {
call_node = node;
} else if index == config.class_capture_index {
class_node = node;
} else if index == config.doc_capture_index {
doc_node = node;
} else if index == config.function_capture_index {
function_node = node;
} else if index == config.module_capture_index {
module_node = node;
} else if index == config.name_capture_index {
name_node = node;
}
}
if let (Some(function), Some(name)) = (function_node, name_node) {
if let Ok(name) = str::from_utf8(&source[name.byte_range()]) {
return Some(Tag {
name,
line: "",
loc: loc_for_node(function),
kind: TagKind::Function,
docs: doc_node
.and_then(|n| str::from_utf8(&source[n.byte_range()]).ok()),
});
}
}
None
})
.collect()
}
}
impl Serialize for TagKind {
fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
match self {
TagKind::Call => "Call",
TagKind::Module => "Module",
TagKind::Class => "Class",
TagKind::Method => "Method",
TagKind::Function => "Function",
}
.serialize(s)
}
}
fn loc_for_node(node: Node) -> Loc {
Loc {
byte_range: node.byte_range(),
span: node.start_position()..node.start_position(),
}
}