#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
use crate::metrics::halstead::HalsteadType;
use crate::spaces::SpaceKind;
use crate::traits::Search;
use crate::*;
#[inline]
fn node_text<'a>(code: &'a [u8], node: &Node) -> Option<&'a str> {
code.get(node.start_byte()..node.end_byte())
.and_then(|bytes| std::str::from_utf8(bytes).ok())
}
macro_rules! get_operator {
($language:ident) => {
#[inline]
fn get_operator_id_as_str(id: u16) -> &'static str {
let typ = id.into();
match typ {
$language::LPAREN => "()",
$language::LBRACK => "[]",
$language::LBRACE => "{}",
_ => typ.into(),
}
}
};
}
macro_rules! impl_js_family_get_op_type {
(
$lang:ident,
op_extras: [$($op_extra:ident),* $(,)?],
operand_extras: [$($operand_extra:ident),* $(,)?]
$(, predefined_void: $predefined_type:ident)? $(,)?
) => {
fn get_op_type(node: &Node) -> HalsteadType {
use $lang::*;
$(
if node.kind_id() == $predefined_type as u16
&& node
.child(0)
.is_some_and(|child| child.kind_id() == Void as u16)
{
return HalsteadType::Unknown;
}
)?
match node.kind_id().into() {
Export | Import | Import2 | Extends | DOT | From | LPAREN | COMMA | As | STAR
| GTGT | GTGTGT | COLON | Return | Delete | Throw | Break | Continue | If
| Else | Switch | Case | Default | Async | Do | For | In | Of | While | Try
| Catch | Finally | With | EQ | AT | AMPAMP | PIPEPIPE | PLUS | DASH | DASHDASH
| PLUSPLUS | SLASH | PERCENT | STARSTAR | PIPE | AMP | LTLT | TILDE | LT | LTEQ
| EQEQ | BANGEQ | GTEQ | GT | PLUSEQ | BANG | BANGEQEQ | EQEQEQ | DASHEQ
| STAREQ | SLASHEQ | PERCENTEQ | STARSTAREQ | GTGTEQ | GTGTGTEQ | LTLTEQ | AMPEQ
| CARET | CARETEQ | PIPEEQ | Yield | LBRACK | LBRACE | Await | QMARK
| QMARKQMARK | EQGT | DOTDOTDOT | New | Let | Var | Const | Function
| FunctionExpression | SEMI | Typeof | Instanceof | Void
| Set | Get
$(| $op_extra)* => HalsteadType::Operator,
Identifier | MemberExpression | MemberExpression2 | MemberExpression3
| PropertyIdentifier | String | Number | True | False | Null | This | Super
| Undefined
$(| $operand_extra)* => HalsteadType::Operand,
TemplateString => {
Self::string_operand_type(node, &[TemplateSubstitution as u16])
}
_ => HalsteadType::Unknown,
}
}
};
}
#[doc(hidden)]
pub(crate) trait Getter {
fn get_func_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
Self::get_func_space_name(node, code)
}
fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
if let Some(name) = node.child_by_field_name("name") {
node_text(code, &name)
} else {
Some("<anonymous>")
}
}
fn get_space_kind(_node: &Node) -> SpaceKind {
SpaceKind::Unknown
}
#[inline]
fn get_space_kind_with_code(node: &Node, _code: &[u8]) -> SpaceKind {
Self::get_space_kind(node)
}
fn get_op_type(_node: &Node) -> HalsteadType {
HalsteadType::Unknown
}
#[inline]
fn get_op_type_with_code(node: &Node, _code: &[u8]) -> HalsteadType {
Self::get_op_type(node)
}
#[inline]
fn get_operand_id<'a>(node: &Node, code: &'a [u8]) -> &'a [u8] {
&code[node.start_byte()..node.end_byte()]
}
fn string_operand_type(node: &Node, interp_kinds: &[u16]) -> HalsteadType {
if node.wraps_any(interp_kinds) {
HalsteadType::Unknown
} else {
HalsteadType::Operand
}
}
fn get_operator_id_as_str(_id: u16) -> &'static str {
""
}
}
mod bash;
mod c;
mod ccomment;
mod cpp;
mod csharp;
mod elixir;
mod go;
mod groovy;
mod irules;
mod java;
mod javascript;
mod kotlin;
mod lua;
mod mozcpp;
mod mozjs;
mod objc;
mod perl;
mod php;
mod preproc;
mod python;
mod ruby;
mod rust;
mod tcl;
mod tsx;
mod typescript;
#[cfg(test)]
mod node_text_tests {
use super::node_text;
use crate::langs::RustParser;
use crate::traits::ParserTrait;
use std::path::PathBuf;
#[test]
fn in_bounds_span_returns_text() {
let src = "fn x() {}";
let parser = RustParser::new(src.as_bytes().to_vec(), &PathBuf::from("t.rs"), None);
let root = parser.root();
assert_eq!(node_text(parser.code(), &root), Some(src));
}
#[test]
fn out_of_bounds_span_returns_none_not_panic() {
let src = "fn x() {}";
let parser = RustParser::new(src.as_bytes().to_vec(), &PathBuf::from("t.rs"), None);
let root = parser.root();
assert!(root.end_byte() > 2);
let truncated = &src.as_bytes()[..2];
assert_eq!(node_text(truncated, &root), None);
}
}