Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
351 changes: 351 additions & 0 deletions src/nodekind.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,3 +111,354 @@ impl NodeKind {
}
}
}

#[cfg(test)]
mod test {
use super::*;
use tree_sitter::Parser;

fn parse_proto(source: &str) -> tree_sitter::Tree {
let mut parser = Parser::new();
parser
.set_language(&tree_sitter_proto::LANGUAGE.into())
.unwrap();
parser.parse(source, None).unwrap()
}

#[test]
fn test_is_identifier() {
let tree = parse_proto("message Foo { string name = 1; }");
let mut cursor = tree.root_node().walk();
// Find the "name" identifier node (child of field)
let mut found = false;
loop {
let n = cursor.node();
if n.kind() == "identifier" {
assert!(NodeKind::is_identifier(&n));
found = true;
} else {
assert!(!NodeKind::is_identifier(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
assert!(found, "expected at least one identifier node");
}

#[test]
fn test_is_message_name() {
let tree = parse_proto("message Foo {}");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "message_name" {
assert!(NodeKind::is_message_name(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_enum_name() {
let tree = parse_proto("enum Color { RED = 0; }");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "enum_name" {
assert!(NodeKind::is_enum_name(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_field_name() {
let tree = parse_proto("message Foo { string bar = 1; }");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "message_or_enum_type" {
assert!(NodeKind::is_field_name(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_rpc_name() {
let tree = parse_proto("service S { rpc Foo(Empty) returns (Empty); }");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "rpc_name" {
assert!(NodeKind::is_rpc_name(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_service_name_node_kind() {
let tree = parse_proto("service MyService {}");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "service_name" {
assert_eq!(n.kind(), "service_name");
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_package_name() {
let tree = parse_proto("package foo.bar;");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "full_ident" {
assert!(NodeKind::is_package_name(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_import_path() {
let tree = parse_proto("import \"foo/bar.proto\";");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "import" {
assert!(NodeKind::is_import_path(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_error() {
let tree = parse_proto("message Foo { invalid_syntax }");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "ERROR" {
assert!(NodeKind::is_error(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_message() {
let tree = parse_proto("message Foo {}");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "message" {
assert!(NodeKind::is_message(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_userdefined() {
let tree = parse_proto("message Foo { enum Bar { X = 0; } }");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
if n.kind() == "message_name" || n.kind() == "enum_name" {
assert!(NodeKind::is_userdefined(&n));
} else {
assert!(!NodeKind::is_userdefined(&n));
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_renameable() {
let tree = parse_proto(
"message Foo { string bar = 1; } enum E { X = 0; } service S { rpc F(Empty) returns (Empty); }",
);
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
match n.kind() {
"message_name"
| "enum_name"
| "service_name"
| "rpc_name"
| "message_or_enum_type"
| "field"
| "map_field"
| "oneof_field"
| "oneof"
| "enum_field" => {
assert!(
NodeKind::is_renameable(&n),
"expected {} to be renameable",
n.kind()
);
}
_ => {
assert!(
!NodeKind::is_renameable(&n),
"expected {} to NOT be renameable",
n.kind()
);
}
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_field_decl_parent() {
let tree = parse_proto(
"message Foo { string a = 1; map<string,int> m = 2; oneof o { string b = 3; } } enum E { X = 0; }",
);
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
match n.kind() {
"field" | "map_field" | "oneof_field" | "oneof" | "enum_field" => {
assert!(NodeKind::is_field_decl_parent(&n));
}
_ => {
assert!(!NodeKind::is_field_decl_parent(&n));
}
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_is_actionable() {
let tree = parse_proto(
"message Foo { string bar = 1; } service S { rpc F(Empty) returns (Empty); }",
);
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
match n.kind() {
"message_name"
| "enum_name"
| "message_or_enum_type"
| "full_ident"
| "service_name"
| "rpc_name" => {
assert!(NodeKind::is_actionable(&n));
}
_ => {
assert!(!NodeKind::is_actionable(&n));
}
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_to_symbolkind() {
let tree = parse_proto("message Foo {} enum Bar { X = 0; } syntax = \"proto3\";");
let mut cursor = tree.root_node().walk();
loop {
let n = cursor.node();
match n.kind() {
"message_name" => assert_eq!(NodeKind::to_symbolkind(&n), SymbolKind::STRUCT),
"enum_name" => assert_eq!(NodeKind::to_symbolkind(&n), SymbolKind::ENUM),
_ => assert_eq!(NodeKind::to_symbolkind(&n), SymbolKind::NULL),
}
if cursor.goto_first_child() {
continue;
}
if !cursor.goto_next_sibling() {
break;
}
}
}

#[test]
fn test_as_str() {
assert_eq!(NodeKind::Identifier.as_str(), "identifier");
assert_eq!(NodeKind::Error.as_str(), "ERROR");
assert_eq!(NodeKind::MessageName.as_str(), "message_name");
assert_eq!(NodeKind::Message.as_str(), "message");
assert_eq!(NodeKind::EnumName.as_str(), "enum_name");
assert_eq!(NodeKind::FieldName.as_str(), "message_or_enum_type");
assert_eq!(NodeKind::ServiceName.as_str(), "service_name");
assert_eq!(NodeKind::RpcName.as_str(), "rpc_name");
assert_eq!(NodeKind::PackageName.as_str(), "full_ident");
assert_eq!(NodeKind::PackageImport.as_str(), "import");
}
}
Loading
Loading