ucn 3.1.0 → 3.1.1
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/core/imports.js +83 -0
- package/package.json +2 -2
- package/test/parser.test.js +47 -0
package/core/imports.js
CHANGED
|
@@ -431,6 +431,12 @@ function resolveImport(importPath, fromFile, config = {}) {
|
|
|
431
431
|
}
|
|
432
432
|
}
|
|
433
433
|
|
|
434
|
+
// Check Go module imports
|
|
435
|
+
if (config.language === 'go') {
|
|
436
|
+
const resolved = resolveGoImport(importPath, fromFile, config.root);
|
|
437
|
+
if (resolved) return resolved;
|
|
438
|
+
}
|
|
439
|
+
|
|
434
440
|
return null; // External package
|
|
435
441
|
}
|
|
436
442
|
|
|
@@ -439,6 +445,83 @@ function resolveImport(importPath, fromFile, config = {}) {
|
|
|
439
445
|
return resolveFilePath(resolved, config.extensions || getExtensions(config.language));
|
|
440
446
|
}
|
|
441
447
|
|
|
448
|
+
// Cache for Go module paths
|
|
449
|
+
const goModuleCache = new Map();
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* Find and parse go.mod to get the module path
|
|
453
|
+
* @param {string} startDir - Directory to start searching from
|
|
454
|
+
* @returns {{modulePath: string, root: string}|null}
|
|
455
|
+
*/
|
|
456
|
+
function findGoModule(startDir) {
|
|
457
|
+
// Check cache first
|
|
458
|
+
if (goModuleCache.has(startDir)) {
|
|
459
|
+
return goModuleCache.get(startDir);
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
let dir = startDir;
|
|
463
|
+
while (dir !== path.dirname(dir)) {
|
|
464
|
+
const goModPath = path.join(dir, 'go.mod');
|
|
465
|
+
if (fs.existsSync(goModPath)) {
|
|
466
|
+
try {
|
|
467
|
+
const content = fs.readFileSync(goModPath, 'utf-8');
|
|
468
|
+
// Parse module line: module github.com/user/project
|
|
469
|
+
const match = content.match(/^module\s+(\S+)/m);
|
|
470
|
+
if (match) {
|
|
471
|
+
const result = { modulePath: match[1], root: dir };
|
|
472
|
+
goModuleCache.set(startDir, result);
|
|
473
|
+
return result;
|
|
474
|
+
}
|
|
475
|
+
} catch (e) {
|
|
476
|
+
// Ignore read errors
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
dir = path.dirname(dir);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
goModuleCache.set(startDir, null);
|
|
483
|
+
return null;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
/**
|
|
487
|
+
* Resolve Go package import to local files
|
|
488
|
+
* @param {string} importPath - Go import path (e.g., "github.com/user/proj/pkg/util")
|
|
489
|
+
* @param {string} fromFile - File containing the import
|
|
490
|
+
* @param {string} projectRoot - Project root directory
|
|
491
|
+
* @returns {string|null} - Directory path containing the package, or null if external
|
|
492
|
+
*/
|
|
493
|
+
function resolveGoImport(importPath, fromFile, projectRoot) {
|
|
494
|
+
const goMod = findGoModule(path.dirname(fromFile));
|
|
495
|
+
if (!goMod) return null;
|
|
496
|
+
|
|
497
|
+
const { modulePath, root } = goMod;
|
|
498
|
+
|
|
499
|
+
// Check if the import is within this module
|
|
500
|
+
if (importPath.startsWith(modulePath)) {
|
|
501
|
+
// Convert module path to relative path
|
|
502
|
+
// e.g., "github.com/user/proj/pkg/util" -> "pkg/util"
|
|
503
|
+
const relativePath = importPath.slice(modulePath.length).replace(/^\//, '');
|
|
504
|
+
const pkgDir = path.join(root, relativePath);
|
|
505
|
+
|
|
506
|
+
// Go imports are directories, find a .go file in the directory
|
|
507
|
+
if (fs.existsSync(pkgDir) && fs.statSync(pkgDir).isDirectory()) {
|
|
508
|
+
// Return the first .go file in the directory (not _test.go)
|
|
509
|
+
try {
|
|
510
|
+
const files = fs.readdirSync(pkgDir);
|
|
511
|
+
for (const file of files) {
|
|
512
|
+
if (file.endsWith('.go') && !file.endsWith('_test.go')) {
|
|
513
|
+
return path.join(pkgDir, file);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
} catch (e) {
|
|
517
|
+
// Ignore read errors
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
return null;
|
|
523
|
+
}
|
|
524
|
+
|
|
442
525
|
/**
|
|
443
526
|
* Try to resolve a path with various extensions
|
|
444
527
|
*/
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ucn",
|
|
3
|
-
"version": "3.1.
|
|
4
|
-
"description": "Code navigation built by AI, for AI. Reduces context usage
|
|
3
|
+
"version": "3.1.1",
|
|
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": {
|
|
7
7
|
"ucn": "./cli/index.js"
|
package/test/parser.test.js
CHANGED
|
@@ -4297,6 +4297,53 @@ class Product {
|
|
|
4297
4297
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
4298
4298
|
}
|
|
4299
4299
|
});
|
|
4300
|
+
|
|
4301
|
+
it('should resolve Go module imports for exporters', () => {
|
|
4302
|
+
const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ucn-go-import-'));
|
|
4303
|
+
try {
|
|
4304
|
+
// Create go.mod file
|
|
4305
|
+
fs.writeFileSync(path.join(tmpDir, 'go.mod'), `module example.com/myproject
|
|
4306
|
+
|
|
4307
|
+
go 1.21
|
|
4308
|
+
`);
|
|
4309
|
+
|
|
4310
|
+
// Create package structure
|
|
4311
|
+
fs.mkdirSync(path.join(tmpDir, 'pkg', 'config'), { recursive: true });
|
|
4312
|
+
fs.writeFileSync(path.join(tmpDir, 'pkg', 'config', 'config.go'), `package config
|
|
4313
|
+
|
|
4314
|
+
type Config struct {
|
|
4315
|
+
Name string
|
|
4316
|
+
}
|
|
4317
|
+
|
|
4318
|
+
func NewConfig() *Config {
|
|
4319
|
+
return &Config{}
|
|
4320
|
+
}
|
|
4321
|
+
`);
|
|
4322
|
+
|
|
4323
|
+
fs.writeFileSync(path.join(tmpDir, 'main.go'), `package main
|
|
4324
|
+
|
|
4325
|
+
import "example.com/myproject/pkg/config"
|
|
4326
|
+
|
|
4327
|
+
func main() {
|
|
4328
|
+
cfg := config.NewConfig()
|
|
4329
|
+
_ = cfg
|
|
4330
|
+
}
|
|
4331
|
+
`);
|
|
4332
|
+
|
|
4333
|
+
const index = new ProjectIndex(tmpDir);
|
|
4334
|
+
index.build('**/*.go', { quiet: true });
|
|
4335
|
+
|
|
4336
|
+
// Get exporters for the config package
|
|
4337
|
+
const exportersResult = index.exporters(path.join(tmpDir, 'pkg', 'config', 'config.go'));
|
|
4338
|
+
assert.ok(exportersResult.length > 0, 'Should find files that import the config package');
|
|
4339
|
+
|
|
4340
|
+
// main.go should be in the list
|
|
4341
|
+
const mainFile = exportersResult.find(e => e.file.includes('main.go'));
|
|
4342
|
+
assert.ok(mainFile, 'main.go should import the config package');
|
|
4343
|
+
} finally {
|
|
4344
|
+
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
4345
|
+
}
|
|
4346
|
+
});
|
|
4300
4347
|
});
|
|
4301
4348
|
|
|
4302
4349
|
console.log('UCN v3 Test Suite');
|