Skip to main content

jinja_lsp_queries/search/
python_identifiers.rs

1use std::collections::HashMap;
2
3use tree_sitter::{Point, Query, QueryCursor, StreamingIterator, Tree};
4
5pub struct PythonAttributes {
6    pub attributes: HashMap<Point, Vec<PythonIdentifier>>,
7}
8
9impl PythonAttributes {
10    pub fn merge(&self, line: u32) -> Vec<PythonIdentifier> {
11        let mut identifiers = vec![];
12        for i in &self.attributes {
13            let mut start = i.0.to_owned();
14            start.row += line as usize;
15            let mut end = i.0;
16            let mut name = String::new();
17            let len = i.1.len();
18            for (index, identifier) in i.1.iter().enumerate() {
19                name.push_str(&identifier.field);
20                end = &identifier.end;
21                if index != len - 1 {
22                    name.push('.');
23                }
24            }
25            let mut end = end.to_owned();
26            end.row += line as usize;
27            let identifier = PythonIdentifier {
28                id: 0,
29                start,
30                end,
31                field: name,
32            };
33            identifiers.push(identifier);
34        }
35        identifiers
36    }
37}
38
39#[derive(Default, Debug, Clone, PartialEq, PartialOrd, Ord, Eq)]
40pub struct PythonIdentifier {
41    pub id: usize,
42    pub start: Point,
43    pub end: Point,
44    pub field: String,
45}
46
47pub fn python_identifiers(
48    query: &Query,
49    tree: &Tree,
50    mut _trigger_point: Point,
51    text: &str,
52    line: u32,
53) -> Vec<PythonIdentifier> {
54    let closest_node = tree.root_node();
55    let mut cursor_qry = QueryCursor::new();
56    let _capture_names = query.capture_names();
57    let mut attributes = PythonAttributes {
58        attributes: HashMap::new(),
59    };
60    let mut matches = cursor_qry.matches(query, closest_node, text.as_bytes());
61    while let Some(i) = matches.next() {
62        for capture in i.captures {
63            if let Some(parent) = capture.node.parent() {
64                let attribute = attributes
65                    .attributes
66                    .entry(parent.start_position())
67                    .or_default();
68                let field = capture.node.utf8_text(text.as_bytes()).unwrap_or_default();
69                let identifier = PythonIdentifier {
70                    id: capture.node.id(),
71                    start: capture.node.start_position(),
72                    end: capture.node.end_position(),
73                    field: field.to_string(),
74                };
75                attribute.push(identifier);
76            }
77        }
78    }
79
80    attributes.merge(line)
81}