1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
//! `Getter` implementation for Objective-C.
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
use super::*;
impl Getter for ObjcCode {
fn get_func_space_name<'a>(node: &Node, code: &'a [u8]) -> Option<&'a str> {
// Issue #285 contract: every `Objc::FunctionDefinition*` alias
// must be enumerated here AND in `get_space_kind` below AND in
// `is_func` / `is_func_space` (see `src/checker.rs`). Free
// functions reach their name through the C declarator chain; the
// ObjC containers (`method_definition`, `class_interface` /
// `class_implementation`, `protocol_declaration`) carry no `name`
// field, so their name is the first `identifier` child — the
// class / protocol name, or a method's first selector keyword.
match node.kind_id().into() {
Objc::FunctionDefinition | Objc::FunctionDefinition2 => {
if let Some(declarator) = node.child_by_field_name("declarator")
&& let Some(fd) = declarator.first_occurrence(|id| {
Objc::FunctionDeclarator == id
|| Objc::FunctionDeclarator2 == id
|| Objc::FunctionDeclarator3 == id
|| Objc::FunctionDeclarator4 == id
})
&& let Some(first) = fd.child(0)
{
match first.kind_id().into() {
Objc::TypeIdentifier | Objc::Identifier | Objc::FieldIdentifier => {
return node_text(code, &first);
}
_ => {}
}
}
}
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::*;
// `@interface` / `@protocol` declare members without bodies →
// `Interface`; `@implementation` carries the method bodies →
// `Class`; free functions and `method_definition`s are
// `Function` spaces. ObjC blocks (`^{ … }`) are closures counted
// by `nom` rather than their own space, mirroring the C++ lambda
// (so they fall through to `Unknown` here). Keep the
// `FunctionDefinition*` aliases listed (#285).
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(node: &Node) -> HalsteadType {
use Objc::*;
// ObjC is C plus message sends, blocks, and the `@`-directives.
// The operator alphabet is therefore the C set (`src/getter.rs`
// `impl Getter for CCode`) extended with the ObjC structural
// keywords: fast-enumeration `in`, the boxing/`@`-literal marker
// `@`, the `@try` / `@catch` / `@finally` / `@throw` /
// `@synchronized` / `@autoreleasepool` control keywords, and the
// `@selector` / `@encode` compile-time directives. Each keeps a
// distinct kind_id, so keying by kind_id keeps them distinct in n1.
// `LPAREN2` is a defensive arm (collapsed to `LPAREN` before
// `kind_id()`; #768, see the Cpp note).
match node.kind_id().into() {
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 | 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
// ObjC-specific structural keywords / markers.
| In | AT | ATtry | ATcatch | ATfinally | ATthrow | ATsynchronized
| ATautoreleasepool | ATselector | ATencode => HalsteadType::Operator,
Identifier | TypeIdentifier | FieldIdentifier | StringLiteral | NumberLiteral
| True | False | Null | DOTDOTDOT => HalsteadType::Operand,
_ => HalsteadType::Unknown,
}
}
get_operator!(Objc);
}