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
//! `Getter` implementation for C#.
#![allow(clippy::wildcard_imports, clippy::enum_glob_use)]
use super::*;
impl Getter for CsharpCode {
fn get_space_kind(node: &Node) -> SpaceKind {
use Csharp::*;
// `EnumDeclaration` maps to `SpaceKind::Class` for cross-language
// parity with Java/PHP/Groovy (issue #429): a C# enum opens a
// FuncSpace via `is_func_space`, so it must classify here too or
// it falls through to `_ => SpaceKind::Unknown`.
// A bodied indexer (#464) or property (#472) defers to its
// `accessor_declaration` children; only the accessor-less
// expression-bodied form opens a Function space directly. Keep this
// gate in lockstep with `CsharpCode::is_func` / `is_func_space` so the
// walker and the space-kind classifier agree on which nodes promote.
if matches!(
node.kind_id().into(),
IndexerDeclaration | PropertyDeclaration
) {
return if crate::checker::csharp_member_has_accessors(node) {
SpaceKind::Unknown
} else {
SpaceKind::Function
};
}
match node.kind_id().into() {
ClassDeclaration | StructDeclaration | RecordDeclaration | EnumDeclaration => {
SpaceKind::Class
}
InterfaceDeclaration => SpaceKind::Interface,
MethodDeclaration
| ConstructorDeclaration
| DestructorDeclaration
| LocalFunctionStatement
| LambdaExpression
| AnonymousMethodExpression
| AccessorDeclaration
| OperatorDeclaration
| ConversionOperatorDeclaration => SpaceKind::Function,
CompilationUnit => SpaceKind::Unit,
_ => SpaceKind::Unknown,
}
}
fn get_op_type(node: &Node) -> HalsteadType {
use Csharp::*;
match node.kind_id().into() {
// Control-flow keywords
If | Else | Switch | Case | Default | Try | Catch | Finally | Throw
| Return | Yield | Break | Continue | Goto | For | Foreach | While | Do
// Declaration / namespace keywords
| Class | Struct | Interface | Enum | Record | Delegate | Namespace | Using
// Modifiers
| Public | Private | Protected | Internal | Static | Abstract | Virtual
| Override | Sealed | Partial | Readonly | Const | Extern | Unsafe
| Volatile | Async | Required | File | New | Fixed | Implicit | Explicit
// Expression-keyword operators
| Await | Is | As | Typeof | Sizeof | Checked | Unchecked | Ref | Out | In
| Params | This | Base | Lock | Stackalloc | Where | With | When | Operator
| Scoped | Not | And | Or
// Property/event accessor keywords
| Get | Set | Init | Add | Remove
// Structural punctuation
| LBRACE | LBRACK | LPAREN | COMMA | SEMI | COLON | COLONCOLON | DOT
| DOTDOT | EQGT | DASHGT | QMARK
// Arithmetic / comparison / logical / bitwise / assignment operators
| EQ | EQEQ | BANGEQ | LT | GT | LTEQ | GTEQ
| PLUS | DASH | STAR | SLASH | PERCENT
| AMP | PIPE | CARET | TILDE | BANG
| AMPAMP | PIPEPIPE | QMARKQMARK
| LTLT | GTGT | GTGTGT
| PLUSPLUS | DASHDASH
| PLUSEQ | DASHEQ | STAREQ | SLASHEQ | PERCENTEQ
| AMPEQ | PIPEEQ | CARETEQ | LTLTEQ | GTGTEQ | GTGTGTEQ | QMARKQMARKEQ
// Predefined / primitive types
| PredefinedType
=> HalsteadType::Operator,
// Operands: identifiers and literals.
Identifier | GenericName | QualifiedName | AliasQualifiedName
| IntegerLiteral | RealLiteral | BooleanLiteral | NullLiteral | True | False
| CharacterLiteral | StringLiteral | VerbatimStringLiteral | RawStringLiteral
=> HalsteadType::Operand,
// `$"..."` counts as one operand when inert. When it carries
// any `Interpolation` child the inner expressions are
// already walked and classified as operands; counting the
// wrapping literal too would double-count the inner
// identifiers' contribution to `N2` (issue #183, same
// pattern as #180 for Elixir/Bash).
InterpolatedStringExpression => {
Self::string_operand_type(node, &[Interpolation as u16])
}
_ => HalsteadType::Unknown,
}
}
get_operator!(Csharp);
}