code-gauge 4.8.0 → 5.1.0

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.
Files changed (66) hide show
  1. package/README.md +34 -9
  2. package/THIRD-PARTY-NOTICES.txt +1152 -798
  3. package/dist/cli.cjs +3 -3
  4. package/dist/cli.cjs.map +1 -1
  5. package/dist/cli.js +3 -3
  6. package/dist/cli.js.map +1 -1
  7. package/dist/cliConfig.cjs +1 -1
  8. package/dist/cliConfig.cjs.map +1 -1
  9. package/dist/cliConfig.d.ts +13 -3
  10. package/dist/cliConfig.js +1 -1
  11. package/dist/cliConfig.js.map +1 -1
  12. package/dist/diffCommand.cjs +3 -3
  13. package/dist/diffCommand.cjs.map +1 -1
  14. package/dist/diffCommand.js +3 -3
  15. package/dist/diffCommand.js.map +1 -1
  16. package/dist/duplication.cjs +1 -1
  17. package/dist/duplication.cjs.map +1 -1
  18. package/dist/duplication.js +1 -1
  19. package/dist/duplication.js.map +1 -1
  20. package/dist/exclusion.cjs +2 -0
  21. package/dist/exclusion.cjs.map +1 -0
  22. package/dist/exclusion.d.ts +30 -0
  23. package/dist/exclusion.js +2 -0
  24. package/dist/exclusion.js.map +1 -0
  25. package/dist/git.cjs +1 -1
  26. package/dist/git.cjs.map +1 -1
  27. package/dist/git.d.ts +16 -0
  28. package/dist/git.js +1 -1
  29. package/dist/git.js.map +1 -1
  30. package/dist/index.cjs +1 -1
  31. package/dist/index.d.ts +2 -0
  32. package/dist/index.js +1 -1
  33. package/dist/nativeMetrics.cjs +3 -3
  34. package/dist/nativeMetrics.cjs.map +1 -1
  35. package/dist/nativeMetrics.js +3 -3
  36. package/dist/nativeMetrics.js.map +1 -1
  37. package/dist/newDuplication.cjs +2 -0
  38. package/dist/newDuplication.cjs.map +1 -0
  39. package/dist/newDuplication.d.ts +40 -0
  40. package/dist/newDuplication.js +2 -0
  41. package/dist/newDuplication.js.map +1 -0
  42. package/dist/regressionGate.cjs +1 -1
  43. package/dist/regressionGate.cjs.map +1 -1
  44. package/dist/regressionGate.d.ts +8 -6
  45. package/dist/regressionGate.js +1 -1
  46. package/dist/regressionGate.js.map +1 -1
  47. package/dist/scan.cjs +1 -1
  48. package/dist/scan.cjs.map +1 -1
  49. package/dist/scan.d.ts +12 -4
  50. package/dist/scan.js +1 -1
  51. package/dist/scan.js.map +1 -1
  52. package/dist/worker.cjs +1 -1
  53. package/dist/worker.cjs.map +1 -1
  54. package/dist/worker.js +1 -1
  55. package/dist/worker.js.map +1 -1
  56. package/native/Cargo.lock +73 -73
  57. package/native/Cargo.toml +16 -21
  58. package/native/code-gauge.wasm +0 -0
  59. package/native/src/dep_degree.rs +6 -6
  60. package/native/src/duplication.rs +143 -14
  61. package/native/src/functions.rs +10 -7
  62. package/native/src/languages.rs +14 -13
  63. package/native/src/measure.rs +16 -8
  64. package/native/src/tree_index.rs +4 -4
  65. package/native/src/util.rs +9 -2
  66. package/package.json +9 -8
@@ -41,24 +41,24 @@ const GRAMMAR_COUNT: usize = GrammarId::Tsx as usize + 1;
41
41
  impl LanguageDefinition {
42
42
  pub fn grammar(&self) -> Language {
43
43
  match self.grammar_id {
44
- GrammarId::C => tree_sitter_c::language(),
45
- GrammarId::Cpp => tree_sitter_cpp::language(),
46
- GrammarId::CSharp => tree_sitter_c_sharp::language(),
47
- GrammarId::Go => tree_sitter_go::language(),
48
- GrammarId::Java => tree_sitter_java::language(),
44
+ GrammarId::C => tree_sitter_c::LANGUAGE.into(),
45
+ GrammarId::Cpp => tree_sitter_cpp::LANGUAGE.into(),
46
+ GrammarId::CSharp => tree_sitter_c_sharp::LANGUAGE.into(),
47
+ GrammarId::Go => tree_sitter_go::LANGUAGE.into(),
48
+ GrammarId::Java => tree_sitter_java::LANGUAGE.into(),
49
49
  GrammarId::JavaScript => tree_sitter_javascript::LANGUAGE.into(),
50
50
  GrammarId::Kotlin => tree_sitter_kotlin::LANGUAGE.into(),
51
- GrammarId::Python => tree_sitter_python::language(),
52
- GrammarId::Ruby => tree_sitter_ruby::language(),
53
- GrammarId::Rust => tree_sitter_rust::language(),
54
- GrammarId::TypeScript => tree_sitter_typescript::language_typescript(),
55
- GrammarId::Tsx => tree_sitter_typescript::language_tsx(),
51
+ GrammarId::Python => tree_sitter_python::LANGUAGE.into(),
52
+ GrammarId::Ruby => tree_sitter_ruby::LANGUAGE.into(),
53
+ GrammarId::Rust => tree_sitter_rust::LANGUAGE.into(),
54
+ GrammarId::TypeScript => tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(),
55
+ GrammarId::Tsx => tree_sitter_typescript::LANGUAGE_TSX.into(),
56
56
  }
57
57
  }
58
58
 
59
59
  /// The grammar's node kind names, indexed by kind id.
60
- pub fn kind_names(&self) -> &'static [&'static str] {
61
- static KIND_NAMES: [OnceLock<Vec<&'static str>>; GRAMMAR_COUNT] =
60
+ pub fn kind_names(&self) -> &'static [String] {
61
+ static KIND_NAMES: [OnceLock<Vec<String>>; GRAMMAR_COUNT] =
62
62
  [const { OnceLock::new() }; GRAMMAR_COUNT];
63
63
  KIND_NAMES[self.grammar_id as usize].get_or_init(|| {
64
64
  let grammar = self.grammar();
@@ -68,6 +68,7 @@ impl LanguageDefinition {
68
68
  .ok()
69
69
  .and_then(|id| grammar.node_kind_for_id(id))
70
70
  .unwrap_or_default()
71
+ .to_string()
71
72
  })
72
73
  .collect()
73
74
  })
@@ -361,7 +362,6 @@ const PYTHON_NCSS_NODES: &[&str] = &[
361
362
  "for_statement",
362
363
  "while_statement",
363
364
  "except_clause",
364
- "except_group_clause",
365
365
  "finally_clause",
366
366
  "with_statement",
367
367
  "match_statement",
@@ -595,6 +595,7 @@ const CSHARP_NCSS_NODES: &[&str] = &[
595
595
  "interface_declaration",
596
596
  "enum_declaration",
597
597
  "record_declaration",
598
+ "extension_declaration",
598
599
  "delegate_declaration",
599
600
  "field_declaration",
600
601
  "event_field_declaration",
@@ -16,7 +16,9 @@ use crate::tree_index::{NodeExt, TreeIndex};
16
16
  use crate::types::{
17
17
  CrossFileFileData, FunctionMetrics, HalsteadCounts, LineMetrics, NativeMetrics,
18
18
  };
19
- use crate::util::{all_children, is_js_whitespace, named_children, node_text, split_lines, Source};
19
+ use crate::util::{
20
+ all_children, is_js_whitespace, is_token, named_children, node_text, split_lines, Source,
21
+ };
20
22
 
21
23
  pub fn measure(
22
24
  code: &str,
@@ -274,11 +276,11 @@ fn collect_token_symbols(
274
276
  ) {
275
277
  return;
276
278
  }
277
- if atomic_operand_node_types().contains(node.kind_name()) {
279
+ if is_atomic_operand(node) {
278
280
  symbols.push(hash_text(node.kind_name()));
279
281
  return;
280
282
  }
281
- if node.child_count() != 0 {
283
+ if !is_token(node) {
282
284
  for child in all_children(node) {
283
285
  collect_token_symbols(child, code, symbols, id_index_by_name);
284
286
  }
@@ -584,8 +586,6 @@ const OPERAND_NODE_TYPES: &[&str] = &[
584
586
  "hex_floating_point_literal",
585
587
  "string",
586
588
  "string_literal",
587
- // Go raw strings are leaves with no content child, unlike Rust/C++ `raw_string_literal`s.
588
- "raw_string_literal",
589
589
  "verbatim_string_literal",
590
590
  "string_fragment",
591
591
  "multiline_string_fragment",
@@ -638,7 +638,7 @@ fn measure_halstead(root: Node<'_>, code: &Source<'_>) -> HalsteadCounts {
638
638
  let mut operands: FxHashMap<&str, u64> = FxHashMap::default();
639
639
 
640
640
  fn visit<'a>(
641
- node: Node<'_>,
641
+ node: Node<'a>,
642
642
  code: &Source<'a>,
643
643
  operators: &mut FxHashMap<&'a str, u64>,
644
644
  operands: &mut FxHashMap<&'a str, u64>,
@@ -650,14 +650,14 @@ fn measure_halstead(root: Node<'_>, code: &Source<'_>) -> HalsteadCounts {
650
650
  return;
651
651
  }
652
652
 
653
- if atomic_operand_node_types().contains(node.kind_name()) {
653
+ if is_atomic_operand(node) {
654
654
  *operands.entry(node_text(node, code)).or_insert(0) += 1;
655
655
  return;
656
656
  }
657
657
 
658
658
  // Operators are counted from leaf tokens only: keyword-named nodes always contain a
659
659
  // same-text anonymous keyword leaf, so counting the named node as well would double-count.
660
- if node.child_count() == 0 {
660
+ if is_token(node) {
661
661
  let text = node_text(node, code);
662
662
  // Operands win over text matches so identifiers spelled like word operators stay operands;
663
663
  // C# `nameof(x)` is the one keyword operator the grammar parses as a plain callee.
@@ -694,6 +694,14 @@ fn measure_halstead(root: Node<'_>, code: &Source<'_>) -> HalsteadCounts {
694
694
  }
695
695
  }
696
696
 
697
+ /// A literal counted as one operand without descending: ATOMIC_OPERAND_NODE_TYPES, or a Go raw
698
+ /// string, which wraps its content like Go's interpreted strings (the Rust and C++
699
+ /// `raw_string_literal`s count their content leaves instead).
700
+ fn is_atomic_operand(node: Node<'_>) -> bool {
701
+ atomic_operand_node_types().contains(node.kind_name())
702
+ || (node.kind_name() == "raw_string_literal" && crate::tree_index::language_name() == "go")
703
+ }
704
+
697
705
  /// tree-sitter-c-sharp parses `nameof(x)` as an invocation of an identifier named `nameof`.
698
706
  fn is_csharp_nameof_callee(node: Node<'_>, text: &str) -> bool {
699
707
  text == "nameof"
@@ -11,7 +11,7 @@ thread_local! {
11
11
  /// nodes; TreeIndex borrows the tree and clears the map on drop, so no entry outlives it.
12
12
  static PARENTS: RefCell<FxHashMap<usize, Node<'static>>> = RefCell::new(FxHashMap::default());
13
13
  /// Node kind names of the indexed tree's language, indexed by kind id.
14
- static KIND_NAMES: Cell<&'static [&'static str]> = const { Cell::new(&[]) };
14
+ static KIND_NAMES: Cell<&'static [String]> = const { Cell::new(&[]) };
15
15
  /// Name of the indexed tree's language.
16
16
  static LANGUAGE_NAME: Cell<&'static str> = const { Cell::new("") };
17
17
  }
@@ -87,7 +87,7 @@ pub trait NodeExt<'t> {
87
87
  /// `Node::parent`, answered from the TreeIndex when one is installed.
88
88
  fn parent_node(self) -> Option<Node<'t>>;
89
89
  /// `Node::kind`, answered from the TreeIndex when one is installed.
90
- fn kind_name(self) -> &'static str;
90
+ fn kind_name(self) -> &'t str;
91
91
  }
92
92
 
93
93
  impl<'t> NodeExt<'t> for Node<'t> {
@@ -109,11 +109,11 @@ impl<'t> NodeExt<'t> for Node<'t> {
109
109
  .or_else(|| self.parent())
110
110
  }
111
111
 
112
- fn kind_name(self) -> &'static str {
112
+ fn kind_name(self) -> &'t str {
113
113
  KIND_NAMES
114
114
  .get()
115
115
  .get(usize::from(self.kind_id()))
116
- .copied()
116
+ .map(String::as_str)
117
117
  .unwrap_or_else(|| self.kind())
118
118
  }
119
119
  }
@@ -61,6 +61,13 @@ pub fn is_kotlin_keyword_literal(node: Node<'_>, code: &Source<'_>) -> bool {
61
61
  && matches!(node_text(node, code), "true" | "false" | "null")
62
62
  }
63
63
 
64
+ /// Whether the node stands for one source token. C# spells a contextual keyword used as a name
65
+ /// (`type`, `field`, `alias`) as an `identifier` or `implicit_parameter` wrapping the keyword token,
66
+ /// which still names a variable like any other identifier.
67
+ pub fn is_token(node: Node<'_>) -> bool {
68
+ node.child_count() == 0 || matches!(node.kind_name(), "identifier" | "implicit_parameter")
69
+ }
70
+
64
71
  pub fn named_children<'t>(node: Node<'t>) -> Vec<Node<'t>> {
65
72
  let mut cursor = node.walk();
66
73
  node.named_children(&mut cursor).collect()
@@ -77,13 +84,13 @@ pub fn all_children<'t>(node: Node<'t>) -> Vec<Node<'t>> {
77
84
  /// them), which would desynchronize field-based extraction on malformed source.
78
85
  pub fn find_children_by_field_name<'t>(node: Node<'t>, field_name: &str) -> Vec<Node<'t>> {
79
86
  let mut children = Vec::new();
80
- let mut preceding_structural_field: Option<&'static str> = None;
87
+ let mut preceding_structural_field = None;
81
88
  for index in 0..node.child_count() {
82
89
  if let Some(child) = node.child(index) {
83
90
  let field = if child.is_extra() {
84
91
  preceding_structural_field
85
92
  } else {
86
- let field = node.field_name_for_child(index as u32);
93
+ let field = node.field_name_for_child(index);
87
94
  preceding_structural_field = field;
88
95
  field
89
96
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-gauge",
3
- "version": "4.8.0",
3
+ "version": "5.1.0",
4
4
  "description": "Measure code metrics with tree-sitter.",
5
5
  "keywords": [
6
6
  "cli",
@@ -62,6 +62,7 @@
62
62
  "verify-full": "bun wb verify --full"
63
63
  },
64
64
  "dependencies": {
65
+ "@willbooster/shared-lib": "10.18.0",
65
66
  "commander": "15.0.0"
66
67
  },
67
68
  "devDependencies": {
@@ -94,12 +95,12 @@
94
95
  "registry": "https://registry.npmjs.org/"
95
96
  },
96
97
  "optionalDependencies": {
97
- "code-gauge-linux-x64-gnu": "4.8.0",
98
- "code-gauge-linux-arm64-gnu": "4.8.0",
99
- "code-gauge-linux-x64-musl": "4.8.0",
100
- "code-gauge-linux-arm64-musl": "4.8.0",
101
- "code-gauge-darwin-x64": "4.8.0",
102
- "code-gauge-darwin-arm64": "4.8.0",
103
- "code-gauge-win32-x64-msvc": "4.8.0"
98
+ "code-gauge-linux-x64-gnu": "5.1.0",
99
+ "code-gauge-linux-arm64-gnu": "5.1.0",
100
+ "code-gauge-linux-x64-musl": "5.1.0",
101
+ "code-gauge-linux-arm64-musl": "5.1.0",
102
+ "code-gauge-darwin-x64": "5.1.0",
103
+ "code-gauge-darwin-arm64": "5.1.0",
104
+ "code-gauge-win32-x64-msvc": "5.1.0"
104
105
  }
105
106
  }