Skip to main content

codelore_rca/
alterator.rs

1use crate::*;
2
3/// A trait to create a richer `AST` node for a programming language, mainly
4/// thought to be sent on the network.
5pub trait Alterator
6where
7    Self: Checker,
8{
9    /// Creates a new `AST` node containing the code associated to the node,
10    /// its span, and its children.
11    ///
12    /// This function can be overloaded according to the needs of each
13    /// programming language.
14    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
15        Self::get_default(node, code, span, children)
16    }
17
18    /// Gets the code as text and the span associated to a node.
19    fn get_text_span(node: &Node, code: &[u8], span: bool, text: bool) -> (String, Span) {
20        let text = if text {
21            String::from_utf8(code[node.start_byte()..node.end_byte()].to_vec()).unwrap()
22        } else {
23            "".to_string()
24        };
25        if span {
26            let (spos_row, spos_column) = node.start_position();
27            let (epos_row, epos_column) = node.end_position();
28            (
29                text,
30                Some((spos_row + 1, spos_column + 1, epos_row + 1, epos_column + 1)),
31            )
32        } else {
33            (text, None)
34        }
35    }
36
37    /// Gets a default `AST` node containing the code associated to the node,
38    /// its span, and its children.
39    fn get_default(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
40        let (text, span) = Self::get_text_span(node, code, span, node.child_count() == 0);
41        AstNode::new(node.kind(), text, span, children)
42    }
43
44    /// Gets a new `AST` node if and only if the code is not a comment,
45    /// otherwise [`None`] is returned.
46    fn get_ast_node(
47        node: &Node,
48        code: &[u8],
49        children: Vec<AstNode>,
50        span: bool,
51        comment: bool,
52    ) -> Option<AstNode> {
53        if comment && Self::is_comment(node) {
54            None
55        } else {
56            Some(Self::alterate(node, code, span, children))
57        }
58    }
59}
60
61impl Alterator for PreprocCode {}
62
63impl Alterator for CcommentCode {}
64
65impl Alterator for CppCode {
66    fn alterate(node: &Node, code: &[u8], span: bool, mut children: Vec<AstNode>) -> AstNode {
67        match Cpp::from(node.kind_id()) {
68            Cpp::StringLiteral | Cpp::CharLiteral => {
69                let (text, span) = Self::get_text_span(node, code, span, true);
70                AstNode::new(node.kind(), text, span, Vec::new())
71            }
72            Cpp::PreprocDef | Cpp::PreprocFunctionDef | Cpp::PreprocCall => {
73                if let Some(last) = children.last()
74                    && last.r#type == "\n"
75                {
76                    children.pop();
77                }
78                Self::get_default(node, code, span, children)
79            }
80            _ => Self::get_default(node, code, span, children),
81        }
82    }
83}
84
85impl Alterator for PythonCode {}
86
87impl Alterator for JavaCode {}
88impl Alterator for KotlinCode {}
89
90impl Alterator for JavascriptCode {
91    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
92        match Javascript::from(node.kind_id()) {
93            Javascript::String => {
94                let (text, span) = Self::get_text_span(node, code, span, true);
95                AstNode::new(node.kind(), text, span, Vec::new())
96            }
97            _ => Self::get_default(node, code, span, children),
98        }
99    }
100}
101
102impl Alterator for TypescriptCode {
103    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
104        match Typescript::from(node.kind_id()) {
105            Typescript::String => {
106                let (text, span) = Self::get_text_span(node, code, span, true);
107                AstNode::new(node.kind(), text, span, Vec::new())
108            }
109            _ => Self::get_default(node, code, span, children),
110        }
111    }
112}
113
114impl Alterator for TsxCode {
115    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
116        match Tsx::from(node.kind_id()) {
117            Tsx::String => {
118                let (text, span) = Self::get_text_span(node, code, span, true);
119                AstNode::new(node.kind(), text, span, Vec::new())
120            }
121            _ => Self::get_default(node, code, span, children),
122        }
123    }
124}
125
126impl Alterator for RustCode {
127    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
128        match Rust::from(node.kind_id()) {
129            Rust::StringLiteral | Rust::CharLiteral => {
130                let (text, span) = Self::get_text_span(node, code, span, true);
131                AstNode::new(node.kind(), text, span, Vec::new())
132            }
133            _ => Self::get_default(node, code, span, children),
134        }
135    }
136}