#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
use super::*;
use crate::c_declarator::declarator_name;
const GENERIC_ANGLES: GenericAngleKinds = GenericAngleKinds {
lists: &[
Objc::GenericSpecifier as u16,
Objc::ProtocolReferenceList as u16,
Objc::ParameterizedArguments as u16,
Objc::ArgumentList2 as u16,
],
openers: &[Objc::LT as u16, Objc::LT2 as u16],
closers: &[Objc::GT as u16],
is_misparse: objc_argument_list_misparse,
};
fn objc_argument_list_misparse(list: &Node, _ancestors: Ancestors) -> bool {
list.kind_id() == Objc::ArgumentList2 as u16 && list.has_error()
}
fn is_property_attribute_name(node: &Node, ancestors: Ancestors) -> bool {
ancestors.parent(node).is_some_and(|attribute| {
attribute.kind_id() == Objc::PropertyAttribute as u16
&& attribute.start_byte() == node.start_byte()
})
}
impl Getter for ObjcCode {
fn get_func_space_name<'a, 'tree>(
node: &Node<'tree>,
code: &'a [u8],
_ancestors: Ancestors<'tree, '_>,
) -> Option<&'a str> {
match node.kind_id().into() {
Objc::FunctionDefinition | Objc::FunctionDefinition2 => {
if let Some(name) = declarator_name::<Self>(node)
&& matches!(
name.kind_id().into(),
Objc::TypeIdentifier | Objc::Identifier | Objc::FieldIdentifier
)
{
return node_text(code, &name);
}
}
Objc::MethodDefinition
| Objc::ClassInterface
| Objc::ClassImplementation
| Objc::ProtocolDeclaration => {
if let Some(ident) = node.first_child(|id| Objc::Identifier == id) {
return node_text(code, &ident);
}
}
_ => {
if let Some(name) = node.child_by_field_name("name") {
return node_text(code, &name);
}
}
}
None
}
fn get_space_kind(node: &Node) -> SpaceKind {
use Objc::*;
match node.kind_id().into() {
FunctionDefinition | FunctionDefinition2 | MethodDefinition => SpaceKind::Function,
ClassImplementation => SpaceKind::Class,
ClassInterface | ProtocolDeclaration => SpaceKind::Interface,
TranslationUnit => SpaceKind::Unit,
_ => SpaceKind::Unknown,
}
}
fn get_op_type<'a>(node: &Node<'a>, ancestors: Ancestors<'a, '_>) -> TokenRole {
use Objc::*;
if GENERIC_ANGLES.is_closer(node, ancestors) {
return TokenRole::Unknown;
}
match node.kind_id().into() {
AT if ancestors.parent_has_kind(node, StringLiteral as u16) => TokenRole::Unknown,
DOT | LPAREN | LPAREN2 | COMMA | STAR | GTGT | COLON | SEMI | Return | Break
| Continue | If | Else | Switch | Case | Default | For | While | Goto | Do | EQ
| AMPAMP | PIPEPIPE | DASH | DASHDASH | DASHGT | PLUS | PLUSPLUS | SLASH | PERCENT
| PIPE | AMP | LTLT | TILDE | LT | LT2 | LTEQ | EQEQ | BANGEQ | GTEQ | GT | PLUSEQ
| DASHEQ | BANG | STAREQ | SLASHEQ | PERCENTEQ | GTGTEQ | LTLTEQ | AMPEQ | CARET
| CARETEQ | PIPEEQ | LBRACK | LBRACE | QMARK | PrimitiveType | TypeSpecifier
| Sizeof | Signed | Unsigned | Long | Short | In | AT | ATtry | ATcatch | ATfinally
| ATthrow | ATsynchronized | ATautoreleasepool | ATselector | ATencode | Struct
| Union | Enum | Typedef | ATinterface | ATimplementation | ATprotocol | Static
| Extern | Register | Auto | Inline | Inline2 | Inline3 | Forceinline | ThreadLocal
| Thread | Const | Constexpr | Volatile | Volatile2 | Restrict | Restrict2 | Atomic
| Noreturn | Noreturn2 | Nonnull | Alignas | Alignas2 | Extension | Const2
| Complex | Complex2 | Nullable | Nullable2 | Nullable3 | NullableResult
| NullUnspecified | Nonnull2 | Autoreleasing | Block | Strong | UnsafeUnretained
| Weak | Bridge | BridgeRetained | BridgeTransfer | Kindof | Covariant
| Contravariant | Out | Inout | Bycopy | Byref | Oneway | ATpublic | ATprivate
| ATprotected | ATpackage | AToptional | ATrequired => TokenRole::Operator,
Identifier if is_property_attribute_name(node, ancestors) => TokenRole::Operator,
Identifier | TypeIdentifier | FieldIdentifier | StringLiteral | CharLiteral
| NumberLiteral | True | False | Null | DOTDOTDOT => TokenRole::Operand,
_ => TokenRole::Unknown,
}
}
fn get_operator_spelling<'a>(
node: &Node<'a>,
ancestors: Ancestors<'a, '_>,
) -> Option<&'static str> {
GENERIC_ANGLES.opener_spelling(node, ancestors)
}
get_operator!(Objc);
}