use smol_str::SmolStr;
use super::ast::{
self, FunctionDeclaration, FunctionDeclarationGreen, Item, ItemEnum, ItemExternFunction,
ItemExternFunctionPtr, ItemExternType, ItemFreeFunction, ItemFreeFunctionPtr, ItemImpl,
ItemModule, ItemStruct, ItemTrait, ItemTypeAlias, ItemUse, Modifier, TerminalIdentifierGreen,
TokenIdentifierGreen, TraitItemFunctionPtr,
};
use super::db::SyntaxGroup;
use super::kind::SyntaxKind;
use super::Terminal;
use crate::node::green::GreenNodeDetails;
pub trait GetIdentifier {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr;
}
impl GetIdentifier for ast::ExprPathGreen {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
let children = match db.lookup_intern_green(self.0).details {
GreenNodeDetails::Node { children, width: _ } => children,
_ => panic!("Unexpected token"),
};
assert_eq!(children.len() & 1, 1, "Expected an odd number of elements in the path.");
ast::TerminalIdentifierGreen(*children.last().unwrap()).identifier(db)
}
}
impl GetIdentifier for ast::TerminalIdentifierGreen {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
match db.lookup_intern_green(self.0).details {
GreenNodeDetails::Token(_) => "Unexpected token".into(),
GreenNodeDetails::Node { children, width: _ } => {
TokenIdentifierGreen(children[1]).text(db)
}
}
}
}
impl GetIdentifier for ast::ExprPath {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
self.elements(db).last().cloned().unwrap().identifier(db)
}
}
impl GetIdentifier for ast::ParamNameGreen {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
let green_node = db.lookup_intern_green(self.0);
match green_node.details {
GreenNodeDetails::Token(_) => "Unexpected token".into(),
GreenNodeDetails::Node { .. } => match green_node.kind {
SyntaxKind::TerminalIdentifier => TerminalIdentifierGreen(self.0).identifier(db),
SyntaxKind::TerminalUnderscore => "_".into(),
_ => "Unexpected identifier for param name".into(),
},
}
}
}
pub trait PathSegmentEx {
fn identifier_ast(&self, db: &dyn SyntaxGroup) -> ast::TerminalIdentifier;
}
impl PathSegmentEx for ast::PathSegment {
fn identifier_ast(&self, db: &dyn SyntaxGroup) -> ast::TerminalIdentifier {
match self {
ast::PathSegment::Simple(segment) => segment.ident(db),
ast::PathSegment::WithGenericArgs(segment) => segment.ident(db),
}
}
}
impl GetIdentifier for ast::PathSegment {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
self.identifier_ast(db).text(db)
}
}
impl GetIdentifier for ast::ParamName {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
match self {
ast::ParamName::Underscore(_) => "_".into(),
ast::ParamName::Name(name) => name.text(db),
}
}
}
impl GetIdentifier for ast::Modifier {
fn identifier(&self, db: &dyn SyntaxGroup) -> SmolStr {
match self {
Modifier::Ref(r) => r.text(db),
Modifier::Mut(m) => m.text(db),
}
}
}
pub trait NameGreen {
fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen;
}
impl NameGreen for FunctionDeclarationGreen {
fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
TerminalIdentifierGreen(
db.lookup_intern_green(self.0).children()[FunctionDeclaration::INDEX_NAME],
)
}
}
impl NameGreen for ItemFreeFunctionPtr {
fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
self.declaration_green(db).name_green(db)
}
}
impl NameGreen for ItemExternFunctionPtr {
fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
self.declaration_green(db).name_green(db)
}
}
impl NameGreen for TraitItemFunctionPtr {
fn name_green(self, db: &dyn SyntaxGroup) -> TerminalIdentifierGreen {
self.declaration_green(db).name_green(db)
}
}
pub trait QueryAttrs {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool;
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool;
}
impl QueryAttrs for ItemModule {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemFreeFunction {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemUse {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemExternFunction {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemExternType {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemTrait {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemImpl {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemStruct {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemEnum {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for ItemTypeAlias {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
self.attributes(db).elements(db).iter().any(|a| a.attr(db).text(db) == attr)
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self.attributes(db).elements(db).last() {
None => false,
Some(last_attr) => last_attr.attr(db).text(db) == attr,
}
}
}
impl QueryAttrs for Item {
fn has_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self {
ast::Item::Module(item) => item.has_attr(db, attr),
ast::Item::FreeFunction(item) => item.has_attr(db, attr),
ast::Item::Use(item) => item.has_attr(db, attr),
ast::Item::ExternFunction(item) => item.has_attr(db, attr),
ast::Item::ExternType(item) => item.has_attr(db, attr),
ast::Item::Trait(item) => item.has_attr(db, attr),
ast::Item::Impl(item) => item.has_attr(db, attr),
ast::Item::Struct(item) => item.has_attr(db, attr),
ast::Item::Enum(item) => item.has_attr(db, attr),
ast::Item::TypeAlias(item) => item.has_attr(db, attr),
}
}
fn last_attr(&self, db: &dyn SyntaxGroup, attr: &str) -> bool {
match self {
ast::Item::Module(item) => item.last_attr(db, attr),
ast::Item::FreeFunction(item) => item.last_attr(db, attr),
ast::Item::Use(item) => item.last_attr(db, attr),
ast::Item::ExternFunction(item) => item.last_attr(db, attr),
ast::Item::ExternType(item) => item.last_attr(db, attr),
ast::Item::Trait(item) => item.last_attr(db, attr),
ast::Item::Impl(item) => item.last_attr(db, attr),
ast::Item::Struct(item) => item.last_attr(db, attr),
ast::Item::Enum(item) => item.last_attr(db, attr),
ast::Item::TypeAlias(item) => item.last_attr(db, attr),
}
}
}