ucn 3.1.8 → 3.3.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.

Potentially problematic release.


This version of ucn might be problematic. Click here for more details.

package/languages/rust.js CHANGED
@@ -11,7 +11,11 @@ const {
11
11
  parseStructuredParams,
12
12
  extractRustDocstring
13
13
  } = require('./utils');
14
- const { PARSE_OPTIONS } = require('./index');
14
+ const { PARSE_OPTIONS, safeParse } = require('./index');
15
+
16
+ function parseTree(parser, code) {
17
+ return safeParse(parser, code, undefined, PARSE_OPTIONS);
18
+ }
15
19
 
16
20
  /**
17
21
  * Extract return type from Rust function
@@ -88,7 +92,7 @@ function extractAttributes(node, code) {
88
92
  * Find all functions in Rust code using tree-sitter
89
93
  */
90
94
  function findFunctions(code, parser) {
91
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
95
+ const tree = parseTree(parser, code);
92
96
  const functions = [];
93
97
  const processedRanges = new Set();
94
98
 
@@ -177,7 +181,7 @@ function extractGenerics(node) {
177
181
  * Find all types (structs, enums, traits, impls) in Rust code
178
182
  */
179
183
  function findClasses(code, parser) {
180
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
184
+ const tree = parseTree(parser, code);
181
185
  const types = [];
182
186
  const processedRanges = new Set();
183
187
 
@@ -492,7 +496,7 @@ function extractImplMembers(implNode, code, typeName) {
492
496
  * Find state objects (const/static) in Rust code
493
497
  */
494
498
  function findStateObjects(code, parser) {
495
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
499
+ const tree = parseTree(parser, code);
496
500
  const objects = [];
497
501
 
498
502
  const statePattern = /^([A-Z][A-Z0-9_]+|DEFAULT_[A-Z_]+)$/;
@@ -555,7 +559,7 @@ function parse(code, parser) {
555
559
  * @returns {Array<{name: string, line: number, isMethod: boolean, receiver?: string, isMacro?: boolean}>}
556
560
  */
557
561
  function findCallsInCode(code, parser) {
558
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
562
+ const tree = parseTree(parser, code);
559
563
  const calls = [];
560
564
  const functionStack = []; // Stack of { name, startLine, endLine }
561
565
 
@@ -679,7 +683,7 @@ function findCallsInCode(code, parser) {
679
683
  * @returns {Array<{module: string, names: string[], type: string, line: number}>}
680
684
  */
681
685
  function findImportsInCode(code, parser) {
682
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
686
+ const tree = parseTree(parser, code);
683
687
  const imports = [];
684
688
 
685
689
  traverseTree(tree.rootNode, (node) => {
@@ -698,6 +702,7 @@ function findImportsInCode(code, parser) {
698
702
  module: path,
699
703
  names: [segments[segments.length - 1]],
700
704
  type: 'use',
705
+ dynamic: false,
701
706
  line
702
707
  });
703
708
  } else if (child.type === 'use_wildcard') {
@@ -708,6 +713,7 @@ function findImportsInCode(code, parser) {
708
713
  module: scopedId.text,
709
714
  names: ['*'],
710
715
  type: 'use-glob',
716
+ dynamic: true,
711
717
  line
712
718
  });
713
719
  }
@@ -733,6 +739,7 @@ function findImportsInCode(code, parser) {
733
739
  module: basePath,
734
740
  names,
735
741
  type: 'use',
742
+ dynamic: false,
736
743
  line
737
744
  });
738
745
  }
@@ -754,6 +761,7 @@ function findImportsInCode(code, parser) {
754
761
  module: nameNode.text,
755
762
  names: [nameNode.text],
756
763
  type: 'mod',
764
+ dynamic: false,
757
765
  line
758
766
  });
759
767
  }
@@ -763,6 +771,26 @@ function findImportsInCode(code, parser) {
763
771
  return true;
764
772
  });
765
773
 
774
+ // include! macros with non-literal paths
775
+ traverseTree(tree.rootNode, (node) => {
776
+ if (node.type === 'macro_invocation') {
777
+ const nameNode = node.childForFieldName('macro');
778
+ if (nameNode && /^include(_str|_bytes)?!$/.test(nameNode.text)) {
779
+ const argsNode = node.childForFieldName('argument_list');
780
+ const arg = argsNode?.namedChild(0);
781
+ const dynamic = !arg || arg.type !== 'string_literal';
782
+ imports.push({
783
+ module: arg ? arg.text.replace(/^["']|["']$/g, '') : null,
784
+ names: [],
785
+ type: 'include',
786
+ dynamic,
787
+ line: node.startPosition.row + 1
788
+ });
789
+ }
790
+ }
791
+ return true;
792
+ });
793
+
766
794
  return imports;
767
795
  }
768
796
 
@@ -774,7 +802,7 @@ function findImportsInCode(code, parser) {
774
802
  * @returns {Array<{name: string, type: string, line: number}>}
775
803
  */
776
804
  function findExportsInCode(code, parser) {
777
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
805
+ const tree = parseTree(parser, code);
778
806
  const exports = [];
779
807
 
780
808
  function hasVisibility(node) {
@@ -906,7 +934,7 @@ function findExportsInCode(code, parser) {
906
934
  * @returns {Array<{line: number, column: number, usageType: string}>}
907
935
  */
908
936
  function findUsagesInCode(code, name, parser) {
909
- const tree = parser.parse(code, undefined, PARSE_OPTIONS);
937
+ const tree = parseTree(parser, code);
910
938
  const usages = [];
911
939
 
912
940
  traverseTree(tree.rootNode, (node) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ucn",
3
- "version": "3.1.8",
3
+ "version": "3.3.0",
4
4
  "description": "Code navigation built by AI, for AI. Reduces context usage when working with large codebases.",
5
5
  "main": "index.js",
6
6
  "bin": {