code-gauge 4.2.1 → 4.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/crossFileDuplication.cjs +1 -1
- package/dist/crossFileDuplication.cjs.map +1 -1
- package/dist/crossFileDuplication.d.ts +3 -1
- package/dist/crossFileDuplication.js +1 -1
- package/dist/crossFileDuplication.js.map +1 -1
- package/dist/duplicateSelection.cjs +1 -1
- package/dist/duplicateSelection.cjs.map +1 -1
- package/dist/duplicateSelection.d.ts +13 -4
- package/dist/duplicateSelection.js +1 -1
- package/dist/duplicateSelection.js.map +1 -1
- package/dist/duplication.cjs +1 -1
- package/dist/duplication.cjs.map +1 -1
- package/dist/duplication.d.ts +16 -7
- package/dist/duplication.js +1 -1
- package/dist/duplication.js.map +1 -1
- package/native/src/complexity.rs +11 -8
- package/native/src/dep_degree.rs +102 -11
- package/native/src/functions.rs +828 -22
- package/package.json +8 -8
package/native/src/dep_degree.rs
CHANGED
|
@@ -72,6 +72,20 @@ const CSHARP_QUERY_BINDING_PARENT_TYPES: &[&str] = &[
|
|
|
72
72
|
"query_expression",
|
|
73
73
|
];
|
|
74
74
|
|
|
75
|
+
/// C/C++ declarators wrapping the declared name (`int* p = q;`, `int& r = *q;`, `int a[n] = {};`,
|
|
76
|
+
/// `int (*fp)(int) = g;`, member pointer `int C::* p = q;`): the definition field is checked on the
|
|
77
|
+
/// outermost wrapper.
|
|
78
|
+
const DECLARATOR_WRAPPER_TYPES: &[&str] = &[
|
|
79
|
+
"pointer_declarator",
|
|
80
|
+
"reference_declarator",
|
|
81
|
+
"array_declarator",
|
|
82
|
+
"parenthesized_declarator",
|
|
83
|
+
"function_declarator",
|
|
84
|
+
"attributed_declarator",
|
|
85
|
+
"pointer_type_declarator",
|
|
86
|
+
"qualified_identifier",
|
|
87
|
+
];
|
|
88
|
+
|
|
75
89
|
/// Multi-target lists (`a, b = ...`, `a, b := ...`) whose holder's `left` field marks definitions.
|
|
76
90
|
const DEFINITION_LIST_NODE_TYPES: &[&str] = &["expression_list", "pattern_list", "tuple_pattern"];
|
|
77
91
|
const DEFINITION_LIST_HOLDER_TYPES: &[&str] = &[
|
|
@@ -119,9 +133,7 @@ pub fn measure_dep_degree(
|
|
|
119
133
|
let mut pairs = 0u64;
|
|
120
134
|
for index in 0..leaves.len() {
|
|
121
135
|
let leaf = &leaves[index];
|
|
122
|
-
if !
|
|
123
|
-
&& !crate::util::is_kotlin_callable_receiver(leaf.node)
|
|
124
|
-
{
|
|
136
|
+
if !is_variable_leaf(leaf.node) {
|
|
125
137
|
continue;
|
|
126
138
|
}
|
|
127
139
|
let name = node_text(leaf.node, code);
|
|
@@ -147,6 +159,33 @@ pub fn measure_dep_degree(
|
|
|
147
159
|
pairs
|
|
148
160
|
}
|
|
149
161
|
|
|
162
|
+
/// A C++ member-pointer variable (`int C::* p`, also `int C::* arr[1]`) is declared as a
|
|
163
|
+
/// `type_identifier` under the `pointer_type_declarator` spelling `C::*`, possibly through further
|
|
164
|
+
/// declarator wrappers; every other `type_identifier` names a type, not a variable.
|
|
165
|
+
fn is_variable_leaf(node: Node<'_>) -> bool {
|
|
166
|
+
VARIABLE_NODE_TYPES.contains(&node.kind())
|
|
167
|
+
|| crate::util::is_kotlin_callable_receiver(node)
|
|
168
|
+
|| (node.kind() == "type_identifier" && is_member_pointer_name(node))
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
fn is_member_pointer_name(node: Node<'_>) -> bool {
|
|
172
|
+
let mut current = node;
|
|
173
|
+
while let Some(parent) = current.parent() {
|
|
174
|
+
if parent.kind() == "pointer_type_declarator" {
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
// The climb follows the declared-name position only, exactly like unwrap_declarator_wrappers.
|
|
178
|
+
if !DECLARATOR_WRAPPER_TYPES.contains(&parent.kind())
|
|
179
|
+
|| parent.kind() == "qualified_identifier"
|
|
180
|
+
|| field_name_in_parent(current, parent).is_some_and(|field| field != "declarator")
|
|
181
|
+
{
|
|
182
|
+
return false;
|
|
183
|
+
}
|
|
184
|
+
current = parent;
|
|
185
|
+
}
|
|
186
|
+
false
|
|
187
|
+
}
|
|
188
|
+
|
|
150
189
|
/// Names a C# accessor body can read without declaring them in its own subtree: the owning
|
|
151
190
|
/// indexer's parameters (including a `params` array, which the grammar names directly on the
|
|
152
191
|
/// parameter list) and, in a setter, initializer, or event accessor, the implicit `value`.
|
|
@@ -270,11 +309,10 @@ fn is_structural_definition(leaf: &DepDegreeLeaf<'_>) -> bool {
|
|
|
270
309
|
{
|
|
271
310
|
return true;
|
|
272
311
|
}
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
.
|
|
276
|
-
|
|
277
|
-
})
|
|
312
|
+
let (declared, declared_field) = unwrap_declarator_wrappers(leaf);
|
|
313
|
+
if declared
|
|
314
|
+
.parent()
|
|
315
|
+
.is_some_and(|holder| is_definition_field(holder, declared_field))
|
|
278
316
|
{
|
|
279
317
|
return true;
|
|
280
318
|
}
|
|
@@ -288,6 +326,42 @@ fn is_structural_definition(leaf: &DepDegreeLeaf<'_>) -> bool {
|
|
|
288
326
|
&& field_name_in_parent(parent, holder) == Some("left")
|
|
289
327
|
}
|
|
290
328
|
|
|
329
|
+
fn is_definition_field(holder: Node<'_>, field_name: Option<&str>) -> bool {
|
|
330
|
+
DEFINITION_FIELD_BY_PARENT_TYPE
|
|
331
|
+
.iter()
|
|
332
|
+
.any(|(parent_type, definition_field)| {
|
|
333
|
+
*parent_type == holder.kind() && field_name == Some(definition_field)
|
|
334
|
+
})
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
/// Climbs from the identifier through the C/C++ declarator wrappers it is the declared name of
|
|
338
|
+
/// (`reference_declarator` and `parenthesized_declarator` expose no field, so their name is the
|
|
339
|
+
/// fieldless child; a member pointer's `pointer_type_declarator` is the `name` of a
|
|
340
|
+
/// `qualified_identifier`; an `array_declarator` size or a nested parameter has another field and
|
|
341
|
+
/// stops the climb) to the outermost wrapper and its field in the declaration.
|
|
342
|
+
fn unwrap_declarator_wrappers<'t>(leaf: &DepDegreeLeaf<'t>) -> (Node<'t>, Option<&'static str>) {
|
|
343
|
+
let mut current = leaf.node;
|
|
344
|
+
let mut field_name = leaf.field_name;
|
|
345
|
+
while let Some(parent) = current
|
|
346
|
+
.parent()
|
|
347
|
+
.filter(|parent| DECLARATOR_WRAPPER_TYPES.contains(&parent.kind()))
|
|
348
|
+
{
|
|
349
|
+
let declared_field = if parent.kind() == "qualified_identifier" {
|
|
350
|
+
"name"
|
|
351
|
+
} else {
|
|
352
|
+
"declarator"
|
|
353
|
+
};
|
|
354
|
+
if field_name.is_some_and(|name| name != declared_field) {
|
|
355
|
+
break;
|
|
356
|
+
}
|
|
357
|
+
field_name = parent
|
|
358
|
+
.parent()
|
|
359
|
+
.and_then(|grandparent| field_name_in_parent(parent, grandparent));
|
|
360
|
+
current = parent;
|
|
361
|
+
}
|
|
362
|
+
(current, field_name)
|
|
363
|
+
}
|
|
364
|
+
|
|
291
365
|
/// Mirrors isParameterDefinition in metrics.ts: an ancestor reached through declarator wrappers
|
|
292
366
|
/// (C/C++ function-pointer or array parameters) is a parameter-ish node, or the identifier
|
|
293
367
|
/// directly occupies a parameter field; type annotations and default values bind nothing.
|
|
@@ -306,14 +380,31 @@ fn is_parameter_definition(leaf: &DepDegreeLeaf<'_>) -> bool {
|
|
|
306
380
|
}
|
|
307
381
|
let mut current = leaf.node;
|
|
308
382
|
let mut depth = 0usize;
|
|
383
|
+
// Only the member pointer's own declared name may climb past its qualified name; a size or
|
|
384
|
+
// other expression inside the same declarator (`int C::* a[n]`) is a read.
|
|
385
|
+
let declares_member_pointer = is_member_pointer_name(leaf.node);
|
|
386
|
+
let mut in_member_pointer = false;
|
|
309
387
|
loop {
|
|
310
388
|
let Some(parent) = current.parent() else {
|
|
311
389
|
return false;
|
|
312
390
|
};
|
|
313
391
|
let parent_is_parameterish = parent.kind().contains("parameter");
|
|
314
|
-
// Beyond the grandparent, only declarator wrappers keep climbing
|
|
315
|
-
//
|
|
316
|
-
|
|
392
|
+
// Beyond the grandparent, only declarator wrappers keep climbing, plus the
|
|
393
|
+
// `qualified_identifier` nodes that spell a member-pointer parameter's class (`int C::* q`,
|
|
394
|
+
// `int N::C::* q`) — entered from the pointer declarator and continued through the `name`
|
|
395
|
+
// side, so a qualified constant in a default value or array size (`int x = N::M::C`) stays
|
|
396
|
+
// a read. Checking this before the field lookup also keeps reads inside high-arity nodes
|
|
397
|
+
// O(1).
|
|
398
|
+
let continues_member_pointer = declares_member_pointer
|
|
399
|
+
&& parent.kind() == "qualified_identifier"
|
|
400
|
+
&& (current.kind() == "pointer_type_declarator" || in_member_pointer)
|
|
401
|
+
&& field_name_in_parent(current, parent) == Some("name");
|
|
402
|
+
in_member_pointer = continues_member_pointer;
|
|
403
|
+
if depth >= 1
|
|
404
|
+
&& !parent_is_parameterish
|
|
405
|
+
&& !parent.kind().contains("declarator")
|
|
406
|
+
&& !continues_member_pointer
|
|
407
|
+
{
|
|
317
408
|
return false;
|
|
318
409
|
}
|
|
319
410
|
let field = if depth == 0 {
|