diff --git a/src/alterator.rs b/src/alterator.rs index 9a8d80e9b..bc851eb5d 100644 --- a/src/alterator.rs +++ b/src/alterator.rs @@ -1,5 +1,3 @@ -use tree_sitter::Node; - use crate::*; pub trait Alterator @@ -12,13 +10,14 @@ where fn get_text_span(node: &Node, code: &[u8], span: bool, text: bool) -> (String, Span) { let text = if text { - String::from_utf8(code[node.start_byte()..node.end_byte()].to_vec()).unwrap() + String::from_utf8(code[node.object().start_byte()..node.object().end_byte()].to_vec()) + .unwrap() } else { "".to_string() }; if span { - let spos = node.start_position(); - let epos = node.end_position(); + let spos = node.object().start_position(); + let epos = node.object().end_position(); ( text, Some((spos.row + 1, spos.column + 1, epos.row + 1, epos.column + 1)), @@ -29,8 +28,8 @@ where } fn get_default(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - let (text, span) = Self::get_text_span(node, code, span, node.child_count() == 0); - AstNode::new(node.kind(), text, span, children) + let (text, span) = Self::get_text_span(node, code, span, node.object().child_count() == 0); + AstNode::new(node.object().kind(), text, span, children) } fn get_ast_node( @@ -54,10 +53,10 @@ impl Alterator for CcommentCode {} impl Alterator for CppCode { fn alterate(node: &Node, code: &[u8], span: bool, mut children: Vec) -> AstNode { - match Cpp::from(node.kind_id()) { + match Cpp::from(node.object().kind_id()) { Cpp::StringLiteral | Cpp::CharLiteral => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } Cpp::PreprocDef | Cpp::PreprocFunctionDef | Cpp::PreprocCall => { if let Some(last) = children.last() { @@ -80,12 +79,12 @@ impl Alterator for JavaCode {} impl Alterator for MozjsCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Mozjs::from(node.kind_id()) { + match Mozjs::from(node.object().kind_id()) { Mozjs::String => { // TODO: have a thought about template_strings: // they may have children for replacement... let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } @@ -94,10 +93,10 @@ impl Alterator for MozjsCode { impl Alterator for JavascriptCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Javascript::from(node.kind_id()) { + match Javascript::from(node.object().kind_id()) { Javascript::String => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } @@ -106,10 +105,10 @@ impl Alterator for JavascriptCode { impl Alterator for TypescriptCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Typescript::from(node.kind_id()) { + match Typescript::from(node.object().kind_id()) { Typescript::String => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } @@ -118,10 +117,10 @@ impl Alterator for TypescriptCode { impl Alterator for TsxCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Tsx::from(node.kind_id()) { + match Tsx::from(node.object().kind_id()) { Tsx::String => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } @@ -130,10 +129,10 @@ impl Alterator for TsxCode { impl Alterator for GoCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Go::from(node.kind_id()) { + match Go::from(node.object().kind_id()) { Go::InterpretedStringLiteral => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } @@ -144,7 +143,7 @@ impl Alterator for CssCode {} impl Alterator for HtmlCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Html::from(node.kind_id()) { + match Html::from(node.object().kind_id()) { Html::QuotedAttributeValue => { if let [q1, attr, q2] = &children[..] { let span = if span { @@ -167,10 +166,10 @@ impl Alterator for HtmlCode { impl Alterator for RustCode { fn alterate(node: &Node, code: &[u8], span: bool, children: Vec) -> AstNode { - match Rust::from(node.kind_id()) { + match Rust::from(node.object().kind_id()) { Rust::StringLiteral | Rust::CharLiteral => { let (text, span) = Self::get_text_span(node, code, span, true); - AstNode::new(node.kind(), text, span, Vec::new()) + AstNode::new(node.object().kind(), text, span, Vec::new()) } _ => Self::get_default(node, code, span, children), } diff --git a/src/ast.rs b/src/ast.rs index 2666b149e..ce343a6b5 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -80,7 +80,7 @@ impl AstNode { fn build(parser: &T, span: bool, comment: bool) -> Option { let code = parser.get_code(); let root = parser.get_root(); - let mut cursor = root.walk(); + let mut cursor = root.object().walk(); let mut node_stack = Vec::new(); let mut child_stack = Vec::new(); @@ -92,11 +92,11 @@ fn build(parser: &T, span: bool, comment: bool) -> Option(parser: &T, span: bool, comment: bool) -> Option(node: &'a Node<'a>, level: usize) -> Option> { let mut level = level; let mut node = *node; while level != 0 { - if let Some(parent) = node.parent() { - node = parent; + if let Some(parent) = node.object().parent() { + node = Node::new(parent); } else { return None; } @@ -24,10 +24,10 @@ macro_rules! has_ancestors { loop { let mut node = *$node; $( - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { $typ => { - node = parent; + node = Node::new(parent); }, _ => { break; @@ -37,7 +37,7 @@ macro_rules! has_ancestors { break; } )* - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { $( $typs )|+ => { res = true; diff --git a/src/checker.rs b/src/checker.rs index 21456196d..701a66584 100644 --- a/src/checker.rs +++ b/src/checker.rs @@ -1,6 +1,5 @@ use aho_corasick::AhoCorasick; use regex::bytes::Regex; -use tree_sitter::Node; use crate::*; @@ -19,7 +18,7 @@ pub trait Checker { fn is_non_arg(node: &Node) -> bool; fn is_error(node: &Node) -> bool { - node.is_error() + node.object().is_error() } } @@ -44,7 +43,7 @@ impl Checker for CcommentCode { lazy_static! { static ref AC: AhoCorasick = AhoCorasick::new(vec![b"
bool { - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { if parent.kind_id() == Rust::TokenTree { // A comment could be a macro token return true; } } - let code = &code[node.start_byte()..node.end_byte()]; + let code = &code[node.object().start_byte()..node.object().end_byte()]; code.starts_with(b"/// cbindgen:") } diff --git a/src/comment_rm.rs b/src/comment_rm.rs index 3735f5286..a5c45afd6 100644 --- a/src/comment_rm.rs +++ b/src/comment_rm.rs @@ -2,6 +2,8 @@ use std::io::{self, Write}; use std::path::PathBuf; use crate::checker::Checker; +use crate::node::Node; + use crate::tools::*; use crate::traits::*; @@ -11,7 +13,7 @@ const CR: [u8; 8192] = [b'\n'; 8192]; pub fn rm_comments(parser: &T) -> Option> { let node = parser.get_root(); let mut stack = Vec::new(); - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); let mut spans = Vec::new(); stack.push(node); @@ -19,13 +21,13 @@ pub fn rm_comments(parser: &T) -> Option> { while let Some(node) = stack.pop() { if T::Checker::is_comment(&node) && !T::Checker::is_useful_comment(&node, parser.get_code()) { - let lines = node.end_position().row - node.start_position().row; - spans.push((node.start_byte(), node.end_byte(), lines)); + let lines = node.object().end_position().row - node.object().start_position().row; + spans.push((node.object().start_byte(), node.object().end_byte(), lines)); } else { - cursor.reset(node); + cursor.reset(node.object()); if cursor.goto_first_child() { loop { - stack.push(cursor.node()); + stack.push(Node::new(cursor.node())); if !cursor.goto_next_sibling() { break; } diff --git a/src/count.rs b/src/count.rs index 8522b630f..3f9e0bd80 100644 --- a/src/count.rs +++ b/src/count.rs @@ -4,6 +4,7 @@ use num_format::{Locale, ToFormattedString}; use std::fmt; use std::sync::{Arc, Mutex}; +use crate::node::Node; use crate::traits::*; /// Counts the types of nodes specified in the input slice @@ -11,7 +12,7 @@ use crate::traits::*; pub fn count<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> (usize, usize) { let filters = parser.get_filters(filters); let node = parser.get_root(); - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); let mut stack = Vec::new(); let mut good = 0; let mut total = 0; @@ -23,10 +24,10 @@ pub fn count<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> (usize, u if filters.any(&node) { good += 1; } - cursor.reset(node); + cursor.reset(node.object()); if cursor.goto_first_child() { loop { - stack.push(cursor.node()); + stack.push(Node::new(cursor.node())); if !cursor.goto_next_sibling() { break; } diff --git a/src/find.rs b/src/find.rs index 41b0dc5c6..57fe031dc 100644 --- a/src/find.rs +++ b/src/find.rs @@ -1,5 +1,6 @@ use std::path::PathBuf; -use tree_sitter::Node; + +use crate::node::Node; use crate::dump::*; use crate::traits::*; @@ -8,7 +9,7 @@ use crate::traits::*; pub fn find<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> Option>> { let filters = parser.get_filters(filters); let node = parser.get_root(); - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); let mut stack = Vec::new(); let mut good = Vec::new(); let mut children = Vec::new(); @@ -19,10 +20,10 @@ pub fn find<'a, T: ParserTrait>(parser: &'a T, filters: &[String]) -> Option(parser: &T) -> Vec { let mut spans = Vec::new(); root.act_on_node(&mut |n| { if T::Checker::is_func(n) { - let start_line = n.start_position().row + 1; - let end_line = n.end_position().row + 1; + let start_line = n.object().start_position().row + 1; + let end_line = n.object().end_position().row + 1; if let Some(name) = T::Getter::get_func_name(n, code) { spans.push(FunctionSpan { name: name.to_string(), diff --git a/src/getter.rs b/src/getter.rs index 7baeaf18f..646e9b7e2 100644 --- a/src/getter.rs +++ b/src/getter.rs @@ -1,6 +1,5 @@ -use tree_sitter::Node; - use crate::metrics::halstead::HalsteadType; + use crate::spaces::SpaceKind; use crate::traits::Search; @@ -13,7 +12,7 @@ pub trait Getter { fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { // we're in a function or in a class - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() } else { @@ -32,7 +31,7 @@ pub trait Getter { impl Getter for PythonCode { fn get_space_kind(node: &Node) -> SpaceKind { - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Python::FunctionDefinition => SpaceKind::Function, Python::ClassDefinition => SpaceKind::Class, @@ -44,7 +43,7 @@ impl Getter for PythonCode { fn get_op_type(node: &Node) -> HalsteadType { use Python::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { Import | DOT | From | LPAREN | COMMA | As | STAR | GTGT | Assert | COLONEQ | Return | Del | Raise | Pass | Break | Continue | If | Elif | Else | Async | For | In @@ -58,7 +57,7 @@ impl Getter for PythonCode { String => { let mut operator = HalsteadType::Unknown; // check if we've a documentation string or a multiline comment - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { if parent.kind_id() != ExpressionStatement || parent.child_count() != 1 { operator = HalsteadType::Operand; }; @@ -74,7 +73,7 @@ impl Getter for MozjsCode { fn get_space_kind(node: &Node) -> SpaceKind { use Mozjs::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Function | MethodDefinition @@ -89,13 +88,13 @@ impl Getter for MozjsCode { } fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() } else { // We can be in a pair: foo: function() {} // Or in a variable declaration: var aFun = function() {} - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { Mozjs::Pair => { if let Some(name) = parent.child_by_field_name("key") { @@ -119,7 +118,7 @@ impl Getter for MozjsCode { fn get_op_type(node: &Node) -> HalsteadType { use Mozjs::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else @@ -142,7 +141,7 @@ impl Getter for JavascriptCode { fn get_space_kind(node: &Node) -> SpaceKind { use Javascript::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Function | MethodDefinition @@ -157,13 +156,13 @@ impl Getter for JavascriptCode { } fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() } else { // We can be in a pair: foo: function() {} // Or in a variable declaration: var aFun = function() {} - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { Mozjs::Pair => { if let Some(name) = parent.child_by_field_name("key") { @@ -187,7 +186,7 @@ impl Getter for JavascriptCode { fn get_op_type(node: &Node) -> HalsteadType { use Javascript::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else @@ -210,7 +209,7 @@ impl Getter for TypescriptCode { fn get_space_kind(node: &Node) -> SpaceKind { use Typescript::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Function | MethodDefinition @@ -225,13 +224,13 @@ impl Getter for TypescriptCode { } fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() } else { // We can be in a pair: foo: function() {} // Or in a variable declaration: var aFun = function() {} - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { Mozjs::Pair => { if let Some(name) = parent.child_by_field_name("key") { @@ -255,7 +254,7 @@ impl Getter for TypescriptCode { fn get_op_type(node: &Node) -> HalsteadType { use Typescript::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else @@ -278,7 +277,7 @@ impl Getter for TsxCode { fn get_space_kind(node: &Node) -> SpaceKind { use Tsx::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Function | MethodDefinition @@ -293,13 +292,13 @@ impl Getter for TsxCode { } fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() } else { // We can be in a pair: foo: function() {} // Or in a variable declaration: var aFun = function() {} - if let Some(parent) = node.parent() { + if let Some(parent) = node.object().parent() { match parent.kind_id().into() { Mozjs::Pair => { if let Some(name) = parent.child_by_field_name("key") { @@ -323,7 +322,7 @@ impl Getter for TsxCode { fn get_op_type(node: &Node) -> HalsteadType { use Tsx::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR | GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If | Else @@ -347,8 +346,9 @@ impl Getter for RustCode { // we're in a function or in a class or an impl // for an impl: we've 'impl ... type {...' if let Some(name) = node + .object() .child_by_field_name("name") - .or(node.child_by_field_name("type")) + .or(node.object().child_by_field_name("type")) { let code = &code[name.start_byte()..name.end_byte()]; std::str::from_utf8(code).ok() @@ -360,7 +360,7 @@ impl Getter for RustCode { fn get_space_kind(node: &Node) -> SpaceKind { use Rust::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { FunctionItem | ClosureExpression => SpaceKind::Function, TraitItem => SpaceKind::Trait, @@ -373,7 +373,7 @@ impl Getter for RustCode { fn get_op_type(node: &Node) -> HalsteadType { use Rust::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { LPAREN | LBRACE | LBRACK | EQGT | PLUS | STAR | Async | Await | Continue | For | If | Let | Loop | Match | Return | Unsafe | While | BANG | EQ | COMMA | DASHGT | QMARK @@ -390,21 +390,22 @@ impl Getter for RustCode { impl Getter for CppCode { fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> { - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { Cpp::FunctionDefinition | Cpp::FunctionDefinition2 | Cpp::FunctionDefinition3 => { if let Some(op_cast) = node.first_child(|id| Cpp::OperatorCast == id) { - let code = &code[op_cast.start_byte()..op_cast.end_byte()]; + let code = &code[op_cast.object().start_byte()..op_cast.object().end_byte()]; return std::str::from_utf8(code).ok(); } // we're in a function_definition so need to get the declarator - if let Some(declarator) = node.child_by_field_name("declarator") { - if let Some(fd) = declarator.first_occurence(|id| { + if let Some(declarator) = node.object().child_by_field_name("declarator") { + let declarator_node = Node::new(declarator); + if let Some(fd) = declarator_node.first_occurence(|id| { Cpp::FunctionDeclarator == id || Cpp::FunctionDeclarator2 == id || Cpp::FunctionDeclarator3 == id }) { - if let Some(first) = fd.child(0) { + if let Some(first) = fd.object().child(0) { match first.kind_id().into() { Cpp::ScopedIdentifier | Cpp::Identifier @@ -424,7 +425,7 @@ impl Getter for CppCode { } } _ => { - if let Some(name) = node.child_by_field_name("name") { + if let Some(name) = node.object().child_by_field_name("name") { let code = &code[name.start_byte()..name.end_byte()]; return std::str::from_utf8(code).ok(); } @@ -436,7 +437,7 @@ impl Getter for CppCode { fn get_space_kind(node: &Node) -> SpaceKind { use Cpp::*; - let typ = node.kind_id(); + let typ = node.object().kind_id(); match typ.into() { FunctionDefinition | FunctionDefinition2 | FunctionDefinition3 => SpaceKind::Function, StructSpecifier => SpaceKind::Struct, @@ -450,7 +451,7 @@ impl Getter for CppCode { fn get_op_type(node: &Node) -> HalsteadType { use Cpp::*; - let id = node.kind_id(); + let id = node.object().kind_id(); match id.into() { DOT | LPAREN | LPAREN2 | COMMA | STAR | GTGT | COLON | SEMI | Return | Break | Continue | If | Else | Switch | Case | Default | For | While | Goto | Do | Delete diff --git a/src/macros.rs b/src/macros.rs index 47514f11e..bff6b49fa 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -5,7 +5,7 @@ macro_rules! mk_checker { #[inline(always)] #[allow(unused_variables)] fn $name(node: &Node) -> bool { - let typ = node.kind_id(); + let typ = node.object().kind_id(); false $( || typ == ::BaseLang::$type diff --git a/src/metrics/cyclomatic.rs b/src/metrics/cyclomatic.rs index 92cbc0089..814b1074e 100644 --- a/src/metrics/cyclomatic.rs +++ b/src/metrics/cyclomatic.rs @@ -1,7 +1,6 @@ use serde::ser::Serializer; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::checker::Checker; use crate::*; @@ -62,7 +61,7 @@ impl Cyclomatic for PythonCode { fn compute(node: &Node, stats: &mut Stats) { use Python::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | Elif | For | While | Except | With | Assert | And | Or => { stats.cyclomatic += 1.; } @@ -80,7 +79,7 @@ impl Cyclomatic for MozjsCode { fn compute(node: &Node, stats: &mut Stats) { use Mozjs::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } @@ -93,7 +92,7 @@ impl Cyclomatic for JavascriptCode { fn compute(node: &Node, stats: &mut Stats) { use Javascript::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } @@ -106,7 +105,7 @@ impl Cyclomatic for TypescriptCode { fn compute(node: &Node, stats: &mut Stats) { use Typescript::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } @@ -119,7 +118,7 @@ impl Cyclomatic for TsxCode { fn compute(node: &Node, stats: &mut Stats) { use Tsx::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Case | Catch | TernaryExpression | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } @@ -132,7 +131,7 @@ impl Cyclomatic for RustCode { fn compute(node: &Node, stats: &mut Stats) { use Rust::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Loop | MatchArm | MatchArm2 | QMARK | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } @@ -145,7 +144,7 @@ impl Cyclomatic for CppCode { fn compute(node: &Node, stats: &mut Stats) { use Cpp::*; - match node.kind_id().into() { + match node.object().kind_id().into() { If | For | While | Case | Catch | ConditionalExpression | AMPAMP | PIPEPIPE => { stats.cyclomatic += 1.; } diff --git a/src/metrics/exit.rs b/src/metrics/exit.rs index 23eed0a23..d1bdc7f64 100644 --- a/src/metrics/exit.rs +++ b/src/metrics/exit.rs @@ -1,7 +1,6 @@ use serde::ser::Serializer; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::checker::Checker; use crate::*; @@ -58,7 +57,7 @@ where impl Exit for PythonCode { fn compute(node: &Node, stats: &mut Stats) { - if let Python::ReturnStatement = node.kind_id().into() { + if let Python::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } @@ -66,7 +65,7 @@ impl Exit for PythonCode { impl Exit for MozjsCode { fn compute(node: &Node, stats: &mut Stats) { - if let Mozjs::ReturnStatement = node.kind_id().into() { + if let Mozjs::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } @@ -74,7 +73,7 @@ impl Exit for MozjsCode { impl Exit for JavascriptCode { fn compute(node: &Node, stats: &mut Stats) { - if let Javascript::ReturnStatement = node.kind_id().into() { + if let Javascript::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } @@ -82,7 +81,7 @@ impl Exit for JavascriptCode { impl Exit for TypescriptCode { fn compute(node: &Node, stats: &mut Stats) { - if let Typescript::ReturnStatement = node.kind_id().into() { + if let Typescript::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } @@ -90,7 +89,7 @@ impl Exit for TypescriptCode { impl Exit for TsxCode { fn compute(node: &Node, stats: &mut Stats) { - if let Tsx::ReturnStatement = node.kind_id().into() { + if let Tsx::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } @@ -98,9 +97,10 @@ impl Exit for TsxCode { impl Exit for RustCode { fn compute(node: &Node, stats: &mut Stats) { - if let Rust::ReturnExpression = node.kind_id().into() { + if let Rust::ReturnExpression = node.object().kind_id().into() { stats.exit += 1; - } else if Self::is_func(node) && node.child_by_field_name("return_type").is_some() { + } else if Self::is_func(node) && node.object().child_by_field_name("return_type").is_some() + { stats.exit += 1; } } @@ -108,7 +108,7 @@ impl Exit for RustCode { impl Exit for CppCode { fn compute(node: &Node, stats: &mut Stats) { - if let Cpp::ReturnStatement = node.kind_id().into() { + if let Cpp::ReturnStatement = node.object().kind_id().into() { stats.exit += 1; } } diff --git a/src/metrics/fn_args.rs b/src/metrics/fn_args.rs index 1b43192b0..5ddc02ce6 100644 --- a/src/metrics/fn_args.rs +++ b/src/metrics/fn_args.rs @@ -1,7 +1,6 @@ use serde::ser::Serializer; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::checker::Checker; use crate::*; @@ -56,8 +55,9 @@ where return; } - if let Some(params) = node.child_by_field_name("parameters") { - params.act_on_child(&mut |n| { + if let Some(params) = node.object().child_by_field_name("parameters") { + let node_params = Node::new(params); + node_params.act_on_child(&mut |n| { if !Self::is_non_arg(n) { stats.n_args += 1; } @@ -72,9 +72,10 @@ impl NArgs for CppCode { return; } - if let Some(declarator) = node.child_by_field_name("declarator") { + if let Some(declarator) = node.object().child_by_field_name("declarator") { if let Some(params) = declarator.child_by_field_name("parameters") { - params.act_on_child(&mut |n| { + let node_params = Node::new(params); + node_params.act_on_child(&mut |n| { if !Self::is_non_arg(n) { stats.n_args += 1; } diff --git a/src/metrics/halstead.rs b/src/metrics/halstead.rs index 5ddcb9d14..aff817ecf 100644 --- a/src/metrics/halstead.rs +++ b/src/metrics/halstead.rs @@ -2,7 +2,6 @@ use fxhash::FxHashMap; use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::checker::Checker; use crate::getter::Getter; @@ -190,13 +189,13 @@ pub enum HalsteadType { #[inline(always)] fn get_id<'a>(node: &Node<'a>, code: &'a [u8]) -> &'a [u8] { - &code[node.start_byte()..node.end_byte()] + &code[node.object().start_byte()..node.object().end_byte()] } #[inline(always)] fn compute_halstead<'a, T: Getter>(node: &Node<'a>, code: &'a [u8], stats: &mut Stats<'a>) { match T::get_op_type(&node) { - HalsteadType::Operator => *stats.operators.entry(node.kind_id()).or_insert(0) += 1, + HalsteadType::Operator => *stats.operators.entry(node.object().kind_id()).or_insert(0) += 1, HalsteadType::Operand => *stats.operands.entry(get_id(node, code)).or_insert(0) += 1, _ => {} } diff --git a/src/metrics/loc.rs b/src/metrics/loc.rs index b386f0164..760a37591 100644 --- a/src/metrics/loc.rs +++ b/src/metrics/loc.rs @@ -3,7 +3,6 @@ use fxhash::FxHashSet; use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::*; @@ -132,8 +131,8 @@ where #[inline(always)] fn init(node: &Node, stats: &mut Stats, is_func_space: bool, is_unit: bool) -> (usize, usize) { - let start = node.start_position().row; - let end = node.end_position().row; + let start = node.object().start_position().row; + let end = node.object().end_position().row; if is_func_space { stats.start = start; @@ -149,13 +148,13 @@ impl Loc for PythonCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { DQUOTE | DQUOTE2 | Block | Module => {} Comment => { stats.comment_lines += (end - start) + 1; } String => { - let parent = node.parent().unwrap(); + let parent = node.object().parent().unwrap(); if let ExpressionStatement = parent.kind_id().into() { stats.comment_lines += (end - start) + 1; } @@ -197,7 +196,7 @@ impl Loc for MozjsCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { String | DQUOTE | Program => {} Comment => { stats.comment_lines += (end - start) + 1; @@ -222,7 +221,7 @@ impl Loc for JavascriptCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { String | DQUOTE | Program => {} Comment => { stats.comment_lines += (end - start) + 1; @@ -247,7 +246,7 @@ impl Loc for TypescriptCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { String | DQUOTE | Program => {} Comment => { stats.comment_lines += (end - start) + 1; @@ -272,7 +271,7 @@ impl Loc for TsxCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { String | DQUOTE | Program => {} Comment => { stats.comment_lines += (end - start) + 1; @@ -297,7 +296,7 @@ impl Loc for RustCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { StringLiteral | RawStringLiteral | Block | SourceFile => {} LineComment | BlockComment => { stats.comment_lines += (end - start) + 1; @@ -342,7 +341,7 @@ impl Loc for CppCode { let (start, end) = init(node, stats, is_func_space, is_unit); - match node.kind_id().into() { + match node.object().kind_id().into() { RawStringLiteral | StringLiteral | DeclarationList | FieldDeclarationList | TranslationUnit => {} Comment => { diff --git a/src/metrics/mi.rs b/src/metrics/mi.rs index 6661bb5d7..db301bc9b 100644 --- a/src/metrics/mi.rs +++ b/src/metrics/mi.rs @@ -1,7 +1,6 @@ use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use super::cyclomatic; use super::halstead; diff --git a/src/metrics/nom.rs b/src/metrics/nom.rs index 0fab0465c..ee694bdd9 100644 --- a/src/metrics/nom.rs +++ b/src/metrics/nom.rs @@ -1,7 +1,6 @@ use serde::ser::{SerializeStruct, Serializer}; use serde::Serialize; use std::fmt; -use tree_sitter::Node; use crate::checker::Checker; @@ -81,7 +80,7 @@ impl Nom for PythonCode { fn compute(node: &Node, stats: &mut Stats) { use Python::*; - match node.kind_id().into() { + match node.object().kind_id().into() { FunctionDefinition => { stats.functions += 1; } @@ -97,7 +96,7 @@ impl Nom for MozjsCode { fn compute(node: &Node, stats: &mut Stats) { use Mozjs::*; - match node.kind_id().into() { + match node.object().kind_id().into() { Function | FunctionDeclaration | MethodDefinition => { stats.functions += 1; } @@ -113,7 +112,7 @@ impl Nom for JavascriptCode { fn compute(node: &Node, stats: &mut Stats) { use Javascript::*; - match node.kind_id().into() { + match node.object().kind_id().into() { Function | FunctionDeclaration | MethodDefinition => { stats.functions += 1; } @@ -129,7 +128,7 @@ impl Nom for TypescriptCode { fn compute(node: &Node, stats: &mut Stats) { use Typescript::*; - match node.kind_id().into() { + match node.object().kind_id().into() { Function | FunctionDeclaration | MethodDefinition => { stats.functions += 1; } @@ -145,7 +144,7 @@ impl Nom for TsxCode { fn compute(node: &Node, stats: &mut Stats) { use Tsx::*; - match node.kind_id().into() { + match node.object().kind_id().into() { Function | FunctionDeclaration | MethodDefinition => { stats.functions += 1; } @@ -161,7 +160,7 @@ impl Nom for RustCode { fn compute(node: &Node, stats: &mut Stats) { use Rust::*; - match node.kind_id().into() { + match node.object().kind_id().into() { FunctionItem => { stats.functions += 1; } @@ -177,7 +176,7 @@ impl Nom for CppCode { fn compute(node: &Node, stats: &mut Stats) { use Cpp::*; - match node.kind_id().into() { + match node.object().kind_id().into() { FunctionDefinition | FunctionDefinition2 | FunctionDefinition3 diff --git a/src/node.rs b/src/node.rs index 249ba7f58..8e1a11449 100644 --- a/src/node.rs +++ b/src/node.rs @@ -1,22 +1,43 @@ +use tree_sitter::Node as OtherNode; + use crate::traits::Search; -use tree_sitter::Node; + +/// An `AST` node. +#[derive(Clone, Copy)] +pub struct Node<'a>(OtherNode<'a>); + +impl<'a> Node<'a> { + /// Checks if a node represents a syntax error or contains any syntax errors + /// anywhere within it. + pub fn has_error(&self) -> bool { + self.0.has_error() + } + + pub(crate) fn new(node: OtherNode<'a>) -> Self { + Node(node) + } + + pub(crate) fn object(&self) -> OtherNode<'a> { + self.0 + } +} impl<'a> Search<'a> for Node<'a> { fn first_occurence(&self, pred: fn(u16) -> bool) -> Option> { - let mut cursor = self.walk(); + let mut cursor = self.0.walk(); let mut stack = Vec::new(); let mut children = Vec::new(); stack.push(*self); while let Some(node) = stack.pop() { - if pred(node.kind_id()) { + if pred(node.0.kind_id()) { return Some(node); } - cursor.reset(node); + cursor.reset(node.0); if cursor.goto_first_child() { loop { - children.push(cursor.node()); + children.push(Node::new(cursor.node())); if !cursor.goto_next_sibling() { break; } @@ -31,7 +52,7 @@ impl<'a> Search<'a> for Node<'a> { } fn act_on_node(&self, action: &mut dyn FnMut(&Node<'a>)) { - let mut cursor = self.walk(); + let mut cursor = self.0.walk(); let mut stack = Vec::new(); let mut children = Vec::new(); @@ -39,10 +60,10 @@ impl<'a> Search<'a> for Node<'a> { while let Some(node) = stack.pop() { action(&node); - cursor.reset(node); + cursor.reset(node.0); if cursor.goto_first_child() { loop { - children.push(cursor.node()); + children.push(Node::new(cursor.node())); if !cursor.goto_next_sibling() { break; } @@ -55,19 +76,19 @@ impl<'a> Search<'a> for Node<'a> { } fn first_child(&self, pred: fn(u16) -> bool) -> Option> { - let mut cursor = self.walk(); - for child in self.children(&mut cursor) { + let mut cursor = self.0.walk(); + for child in self.0.children(&mut cursor) { if pred(child.kind_id()) { - return Some(child); + return Some(Node::new(child)); } } None } fn act_on_child(&self, action: &mut dyn FnMut(&Node<'a>)) { - let mut cursor = self.walk(); - for child in self.children(&mut cursor) { - action(&child); + let mut cursor = self.0.walk(); + for child in self.0.children(&mut cursor) { + action(&Node::new(child)); } } } diff --git a/src/output/dump.rs b/src/output/dump.rs index 380605110..64849fd44 100644 --- a/src/output/dump.rs +++ b/src/output/dump.rs @@ -1,6 +1,7 @@ use std::io::Write; use termcolor::{Color, ColorChoice, ColorSpec, StandardStream, StandardStreamLock, WriteColor}; -use tree_sitter::Node; + +use crate::node::Node; use crate::traits::*; @@ -76,7 +77,7 @@ fn dump_tree_helper( let (pref_child, pref) = if last { (" ", "`- ") } else { ("| ", "|- ") }; - let node_row = node.start_position().row + 1; + let node_row = node.object().start_position().row + 1; let mut display = true; if let Some(line_start) = line_start { display = node_row >= *line_start @@ -90,28 +91,33 @@ fn dump_tree_helper( write!(stdout, "{}{}", prefix, pref)?; color!(stdout, Yellow, true); - write!(stdout, "{{{}:{}}} ", node.kind(), node.kind_id())?; + write!( + stdout, + "{{{}:{}}} ", + node.object().kind(), + node.object().kind_id() + )?; color!(stdout, White); write!(stdout, "from ")?; color!(stdout, Green); - let pos = node.start_position(); + let pos = node.object().start_position(); write!(stdout, "({}, {}) ", pos.row + 1, pos.column + 1)?; color!(stdout, White); write!(stdout, "to ")?; color!(stdout, Green); - let pos = node.end_position(); + let pos = node.object().end_position(); write!(stdout, "({}, {}) ", pos.row + 1, pos.column + 1)?; - if node.start_position().row == node.end_position().row { + if node.object().start_position().row == node.object().end_position().row { color!(stdout, White); write!(stdout, ": ")?; color!(stdout, Red, true); - let code = &code[node.start_byte()..node.end_byte()]; + let code = &code[node.object().start_byte()..node.object().end_byte()]; if let Ok(code) = String::from_utf8(code.to_vec()) { write!(stdout, "{} ", code)?; } else { @@ -122,18 +128,18 @@ fn dump_tree_helper( writeln!(stdout)?; } - let count = node.child_count(); + let count = node.object().child_count(); if count != 0 { let prefix = format!("{}{}", prefix, pref_child); let mut i = count; - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); cursor.goto_first_child(); loop { i -= 1; dump_tree_helper( &code, - &cursor.node(), + &Node::new(cursor.node()), &prefix, i == 0, stdout, diff --git a/src/parser.rs b/src/parser.rs index fe8aed194..a73198942 100644 --- a/src/parser.rs +++ b/src/parser.rs @@ -1,13 +1,14 @@ use std::marker::PhantomData; use std::path::PathBuf; use std::sync::Arc; -use tree_sitter::{Node, Parser as TSParser, Tree}; +use tree_sitter::{Parser as TSParser, Tree}; use crate::alterator::Alterator; use crate::c_macro; use crate::checker::*; use crate::getter::Getter; use crate::langs::*; +use crate::node::Node; use crate::preproc::{get_macros, PreprocResults}; use crate::traits::*; @@ -106,7 +107,7 @@ impl Pars #[inline(always)] fn get_root(&self) -> Node { - self.tree.root_node() + Node::new(self.tree.root_node()) } #[inline(always)] @@ -126,7 +127,9 @@ impl Pars "function" => res.push(Box::new(T::is_func)), _ => { if let Ok(n) = f.parse::() { - res.push(Box::new(move |node: &Node| -> bool { node.kind_id() == n })); + res.push(Box::new(move |node: &Node| -> bool { + node.object().kind_id() == n + })); } } } diff --git a/src/preproc.rs b/src/preproc.rs index ff448b32c..939997713 100644 --- a/src/preproc.rs +++ b/src/preproc.rs @@ -4,6 +4,8 @@ use petgraph::{ use std::collections::{hash_map, HashMap, HashSet}; use std::path::PathBuf; +use crate::node::Node; + use crate::langs::*; use crate::languages::language_preproc::*; use crate::tools::*; @@ -183,7 +185,7 @@ pub fn fix_includes( /// [`PreprocResults`]: struct.PreprocResults.html pub fn preprocess(parser: &PreprocParser, path: &PathBuf, results: &mut PreprocResults) { let node = parser.get_root(); - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); let mut stack = Vec::new(); let code = parser.get_code(); let mut file_result = PreprocFile::default(); @@ -193,20 +195,20 @@ pub fn preprocess(parser: &PreprocParser, path: &PathBuf, results: &mut PreprocR stack.push(node); while let Some(node) = stack.pop() { - cursor.reset(node); + cursor.reset(node.object()); if cursor.goto_first_child() { loop { - stack.push(cursor.node()); + stack.push(Node::new(cursor.node())); if !cursor.goto_next_sibling() { break; } } } - let id = Preproc::from(node.kind_id()); + let id = Preproc::from(node.object().kind_id()); match id { Preproc::Define | Preproc::Undef => { - cursor.reset(node); + cursor.reset(node.object()); cursor.goto_first_child(); let identifier = cursor.node(); @@ -218,7 +220,7 @@ pub fn preprocess(parser: &PreprocParser, path: &PathBuf, results: &mut PreprocR } } Preproc::PreprocInclude => { - cursor.reset(node); + cursor.reset(node.object()); cursor.goto_first_child(); let file = cursor.node(); diff --git a/src/spaces.rs b/src/spaces.rs index d112677e6..d66eacf45 100644 --- a/src/spaces.rs +++ b/src/spaces.rs @@ -1,9 +1,10 @@ use serde::Serialize; use std::fmt; use std::path::PathBuf; -use tree_sitter::Node; use crate::checker::Checker; +use crate::node::Node; + use crate::cyclomatic::{self, Cyclomatic}; use crate::exit::{self, Exit}; use crate::fn_args::{self, NArgs}; @@ -136,13 +137,19 @@ impl<'a> FuncSpace<'a> { fn new(node: &Node<'a>, code: &'a [u8], kind: SpaceKind) -> Self { let (start_position, end_position) = match kind { SpaceKind::Unit => { - if node.child_count() == 0 { + if node.object().child_count() == 0 { (0, 0) } else { - (node.start_position().row + 1, node.end_position().row) + ( + node.object().start_position().row + 1, + node.object().end_position().row, + ) } } - _ => (node.start_position().row + 1, node.end_position().row + 1), + _ => ( + node.object().start_position().row + 1, + node.object().end_position().row + 1, + ), }; Self { name: T::get_func_space_name(&node, code), @@ -193,7 +200,7 @@ fn finalize<'a>(space_stack: &mut Vec>, diff_level: usize) { pub fn metrics<'a, T: ParserTrait>(parser: &'a T, path: &'a PathBuf) -> Option> { let code = parser.get_code(); let node = parser.get_root(); - let mut cursor = node.walk(); + let mut cursor = node.object().walk(); let mut stack = Vec::new(); let mut children = Vec::new(); let mut space_stack: Vec = Vec::new(); @@ -236,10 +243,10 @@ pub fn metrics<'a, T: ParserTrait>(parser: &'a T, path: &'a PathBuf) -> Option