Skip to main content

rust_code_analysis_code_split/
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 MozjsCode {
91    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
92        match Mozjs::from(node.kind_id()) {
93            Mozjs::String | Mozjs::String2 => {
94                // TODO: have a thought about template_strings:
95                // they may have children for replacement...
96                let (text, span) = Self::get_text_span(node, code, span, true);
97                AstNode::new(node.kind(), text, span, Vec::new())
98            }
99            _ => Self::get_default(node, code, span, children),
100        }
101    }
102}
103
104impl Alterator for JavascriptCode {
105    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
106        match Javascript::from(node.kind_id()) {
107            Javascript::String => {
108                let (text, span) = Self::get_text_span(node, code, span, true);
109                AstNode::new(node.kind(), text, span, Vec::new())
110            }
111            _ => Self::get_default(node, code, span, children),
112        }
113    }
114}
115
116impl Alterator for TypescriptCode {
117    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
118        match Typescript::from(node.kind_id()) {
119            Typescript::String => {
120                let (text, span) = Self::get_text_span(node, code, span, true);
121                AstNode::new(node.kind(), text, span, Vec::new())
122            }
123            _ => Self::get_default(node, code, span, children),
124        }
125    }
126}
127
128impl Alterator for TsxCode {
129    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
130        match Tsx::from(node.kind_id()) {
131            Tsx::String => {
132                let (text, span) = Self::get_text_span(node, code, span, true);
133                AstNode::new(node.kind(), text, span, Vec::new())
134            }
135            _ => Self::get_default(node, code, span, children),
136        }
137    }
138}
139
140impl Alterator for RustCode {
141    fn alterate(node: &Node, code: &[u8], span: bool, children: Vec<AstNode>) -> AstNode {
142        match Rust::from(node.kind_id()) {
143            Rust::StringLiteral | Rust::CharLiteral => {
144                let (text, span) = Self::get_text_span(node, code, span, true);
145                AstNode::new(node.kind(), text, span, Vec::new())
146            }
147            _ => Self::get_default(node, code, span, children),
148        }
149    }
150}