gitnexus 1.4.7 → 1.4.9
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/README.md +29 -1
- package/dist/cli/ai-context.d.ts +1 -1
- package/dist/cli/ai-context.js +1 -1
- package/dist/cli/analyze.d.ts +2 -0
- package/dist/cli/analyze.js +54 -21
- package/dist/cli/index-repo.d.ts +15 -0
- package/dist/cli/index-repo.js +115 -0
- package/dist/cli/index.js +13 -3
- package/dist/cli/setup.js +90 -10
- package/dist/cli/wiki.d.ts +4 -0
- package/dist/cli/wiki.js +174 -53
- package/dist/config/supported-languages.d.ts +33 -1
- package/dist/config/supported-languages.js +32 -0
- package/dist/core/embeddings/embedder.d.ts +6 -1
- package/dist/core/embeddings/embedder.js +65 -5
- package/dist/core/embeddings/embedding-pipeline.js +11 -9
- package/dist/core/embeddings/http-client.d.ts +31 -0
- package/dist/core/embeddings/http-client.js +179 -0
- package/dist/core/embeddings/index.d.ts +1 -0
- package/dist/core/embeddings/index.js +1 -0
- package/dist/core/embeddings/types.d.ts +1 -1
- package/dist/core/graph/graph.js +9 -1
- package/dist/core/graph/types.d.ts +11 -2
- package/dist/core/ingestion/call-processor.d.ts +66 -2
- package/dist/core/ingestion/call-processor.js +650 -30
- package/dist/core/ingestion/call-routing.d.ts +9 -18
- package/dist/core/ingestion/call-routing.js +0 -19
- package/dist/core/ingestion/cobol/cobol-copy-expander.d.ts +57 -0
- package/dist/core/ingestion/cobol/cobol-copy-expander.js +385 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.d.ts +210 -0
- package/dist/core/ingestion/cobol/cobol-preprocessor.js +1509 -0
- package/dist/core/ingestion/cobol/jcl-parser.d.ts +68 -0
- package/dist/core/ingestion/cobol/jcl-parser.js +217 -0
- package/dist/core/ingestion/cobol/jcl-processor.d.ts +33 -0
- package/dist/core/ingestion/cobol/jcl-processor.js +229 -0
- package/dist/core/ingestion/cobol-processor.d.ts +54 -0
- package/dist/core/ingestion/cobol-processor.js +1186 -0
- package/dist/core/ingestion/entry-point-scoring.d.ts +17 -0
- package/dist/core/ingestion/entry-point-scoring.js +52 -28
- package/dist/core/ingestion/export-detection.d.ts +47 -8
- package/dist/core/ingestion/export-detection.js +29 -50
- package/dist/core/ingestion/field-extractor.d.ts +29 -0
- package/dist/core/ingestion/field-extractor.js +25 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/c-cpp.js +108 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/csharp.js +73 -0
- package/dist/core/ingestion/field-extractors/configs/dart.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/dart.js +76 -0
- package/dist/core/ingestion/field-extractors/configs/go.d.ts +11 -0
- package/dist/core/ingestion/field-extractors/configs/go.js +64 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.d.ts +44 -0
- package/dist/core/ingestion/field-extractors/configs/helpers.js +134 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/jvm.js +118 -0
- package/dist/core/ingestion/field-extractors/configs/php.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/php.js +67 -0
- package/dist/core/ingestion/field-extractors/configs/python.d.ts +12 -0
- package/dist/core/ingestion/field-extractors/configs/python.js +91 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.d.ts +16 -0
- package/dist/core/ingestion/field-extractors/configs/ruby.js +75 -0
- package/dist/core/ingestion/field-extractors/configs/rust.d.ts +9 -0
- package/dist/core/ingestion/field-extractors/configs/rust.js +55 -0
- package/dist/core/ingestion/field-extractors/configs/swift.d.ts +8 -0
- package/dist/core/ingestion/field-extractors/configs/swift.js +63 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.d.ts +3 -0
- package/dist/core/ingestion/field-extractors/configs/typescript-javascript.js +60 -0
- package/dist/core/ingestion/field-extractors/generic.d.ts +46 -0
- package/dist/core/ingestion/field-extractors/generic.js +111 -0
- package/dist/core/ingestion/field-extractors/typescript.d.ts +77 -0
- package/dist/core/ingestion/field-extractors/typescript.js +291 -0
- package/dist/core/ingestion/field-types.d.ts +59 -0
- package/dist/core/ingestion/field-types.js +2 -0
- package/dist/core/ingestion/framework-detection.d.ts +97 -2
- package/dist/core/ingestion/framework-detection.js +114 -14
- package/dist/core/ingestion/heritage-processor.js +62 -66
- package/dist/core/ingestion/import-processor.d.ts +9 -10
- package/dist/core/ingestion/import-processor.js +150 -196
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.d.ts +6 -9
- package/dist/core/ingestion/{resolvers → import-resolvers}/csharp.js +20 -2
- package/dist/core/ingestion/import-resolvers/dart.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/dart.js +44 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.d.ts +4 -5
- package/dist/core/ingestion/{resolvers → import-resolvers}/go.js +17 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/jvm.d.ts +10 -1
- package/dist/core/ingestion/import-resolvers/jvm.js +159 -0
- package/dist/core/ingestion/import-resolvers/php.d.ts +25 -0
- package/dist/core/ingestion/import-resolvers/php.js +80 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.d.ts +9 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/python.js +35 -3
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/ruby.js +7 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.d.ts +5 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/rust.js +41 -2
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.d.ts +15 -7
- package/dist/core/ingestion/{resolvers → import-resolvers}/standard.js +22 -3
- package/dist/core/ingestion/import-resolvers/swift.d.ts +7 -0
- package/dist/core/ingestion/import-resolvers/swift.js +23 -0
- package/dist/core/ingestion/import-resolvers/types.d.ts +44 -0
- package/dist/core/ingestion/import-resolvers/types.js +6 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.d.ts +2 -0
- package/dist/core/ingestion/{resolvers → import-resolvers}/utils.js +7 -0
- package/dist/core/ingestion/language-config.d.ts +6 -0
- package/dist/core/ingestion/language-config.js +13 -0
- package/dist/core/ingestion/language-provider.d.ts +121 -0
- package/dist/core/ingestion/language-provider.js +24 -0
- package/dist/core/ingestion/languages/c-cpp.d.ts +12 -0
- package/dist/core/ingestion/languages/c-cpp.js +71 -0
- package/dist/core/ingestion/languages/cobol.d.ts +1 -0
- package/dist/core/ingestion/languages/cobol.js +26 -0
- package/dist/core/ingestion/languages/csharp.d.ts +8 -0
- package/dist/core/ingestion/languages/csharp.js +49 -0
- package/dist/core/ingestion/languages/dart.d.ts +12 -0
- package/dist/core/ingestion/languages/dart.js +58 -0
- package/dist/core/ingestion/languages/go.d.ts +11 -0
- package/dist/core/ingestion/languages/go.js +28 -0
- package/dist/core/ingestion/languages/index.d.ts +38 -0
- package/dist/core/ingestion/languages/index.js +63 -0
- package/dist/core/ingestion/languages/java.d.ts +9 -0
- package/dist/core/ingestion/languages/java.js +29 -0
- package/dist/core/ingestion/languages/kotlin.d.ts +9 -0
- package/dist/core/ingestion/languages/kotlin.js +53 -0
- package/dist/core/ingestion/languages/php.d.ts +8 -0
- package/dist/core/ingestion/languages/php.js +145 -0
- package/dist/core/ingestion/languages/python.d.ts +12 -0
- package/dist/core/ingestion/languages/python.js +39 -0
- package/dist/core/ingestion/languages/ruby.d.ts +9 -0
- package/dist/core/ingestion/languages/ruby.js +44 -0
- package/dist/core/ingestion/languages/rust.d.ts +12 -0
- package/dist/core/ingestion/languages/rust.js +44 -0
- package/dist/core/ingestion/languages/swift.d.ts +12 -0
- package/dist/core/ingestion/languages/swift.js +133 -0
- package/dist/core/ingestion/languages/typescript.d.ts +10 -0
- package/dist/core/ingestion/languages/typescript.js +60 -0
- package/dist/core/ingestion/markdown-processor.d.ts +17 -0
- package/dist/core/ingestion/markdown-processor.js +124 -0
- package/dist/core/ingestion/mro-processor.js +22 -18
- package/dist/core/ingestion/named-binding-processor.d.ts +18 -0
- package/dist/core/ingestion/named-binding-processor.js +42 -0
- package/dist/core/ingestion/named-bindings/csharp.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/csharp.js +37 -0
- package/dist/core/ingestion/named-bindings/java.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/java.js +29 -0
- package/dist/core/ingestion/named-bindings/kotlin.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/kotlin.js +36 -0
- package/dist/core/ingestion/named-bindings/php.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/php.js +61 -0
- package/dist/core/ingestion/named-bindings/python.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/python.js +49 -0
- package/dist/core/ingestion/named-bindings/rust.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/rust.js +64 -0
- package/dist/core/ingestion/named-bindings/types.d.ts +16 -0
- package/dist/core/ingestion/named-bindings/types.js +6 -0
- package/dist/core/ingestion/named-bindings/typescript.d.ts +3 -0
- package/dist/core/ingestion/named-bindings/typescript.js +58 -0
- package/dist/core/ingestion/parsing-processor.d.ts +6 -2
- package/dist/core/ingestion/parsing-processor.js +125 -85
- package/dist/core/ingestion/pipeline.d.ts +10 -0
- package/dist/core/ingestion/pipeline.js +1235 -317
- package/dist/core/ingestion/resolution-context.d.ts +5 -0
- package/dist/core/ingestion/resolution-context.js +8 -5
- package/dist/core/ingestion/route-extractors/expo.d.ts +1 -0
- package/dist/core/ingestion/route-extractors/expo.js +36 -0
- package/dist/core/ingestion/route-extractors/middleware.d.ts +47 -0
- package/dist/core/ingestion/route-extractors/middleware.js +143 -0
- package/dist/core/ingestion/route-extractors/nextjs.d.ts +3 -0
- package/dist/core/ingestion/route-extractors/nextjs.js +76 -0
- package/dist/core/ingestion/route-extractors/php.d.ts +7 -0
- package/dist/core/ingestion/route-extractors/php.js +21 -0
- package/dist/core/ingestion/route-extractors/response-shapes.d.ts +20 -0
- package/dist/core/ingestion/route-extractors/response-shapes.js +290 -0
- package/dist/core/ingestion/symbol-table.d.ts +16 -0
- package/dist/core/ingestion/symbol-table.js +20 -6
- package/dist/core/ingestion/tree-sitter-queries.d.ts +10 -9
- package/dist/core/ingestion/tree-sitter-queries.js +274 -11
- package/dist/core/ingestion/type-env.d.ts +42 -18
- package/dist/core/ingestion/type-env.js +481 -106
- package/dist/core/ingestion/type-extractors/c-cpp.d.ts +5 -0
- package/dist/core/ingestion/type-extractors/c-cpp.js +119 -0
- package/dist/core/ingestion/type-extractors/csharp.js +149 -16
- package/dist/core/ingestion/type-extractors/dart.d.ts +15 -0
- package/dist/core/ingestion/type-extractors/dart.js +371 -0
- package/dist/core/ingestion/type-extractors/jvm.js +169 -66
- package/dist/core/ingestion/type-extractors/rust.js +35 -1
- package/dist/core/ingestion/type-extractors/shared.d.ts +1 -15
- package/dist/core/ingestion/type-extractors/shared.js +14 -112
- package/dist/core/ingestion/type-extractors/swift.js +338 -7
- package/dist/core/ingestion/type-extractors/types.d.ts +40 -8
- package/dist/core/ingestion/type-extractors/typescript.js +141 -9
- package/dist/core/ingestion/utils/ast-helpers.d.ts +83 -0
- package/dist/core/ingestion/utils/ast-helpers.js +817 -0
- package/dist/core/ingestion/utils/call-analysis.d.ts +73 -0
- package/dist/core/ingestion/utils/call-analysis.js +527 -0
- package/dist/core/ingestion/utils/event-loop.d.ts +5 -0
- package/dist/core/ingestion/utils/event-loop.js +5 -0
- package/dist/core/ingestion/utils/language-detection.d.ts +9 -0
- package/dist/core/ingestion/utils/language-detection.js +70 -0
- package/dist/core/ingestion/utils/verbose.d.ts +1 -0
- package/dist/core/ingestion/utils/verbose.js +7 -0
- package/dist/core/ingestion/workers/parse-worker.d.ts +55 -5
- package/dist/core/ingestion/workers/parse-worker.js +415 -225
- package/dist/core/lbug/csv-generator.js +51 -1
- package/dist/core/lbug/lbug-adapter.d.ts +10 -0
- package/dist/core/lbug/lbug-adapter.js +75 -4
- package/dist/core/lbug/schema.d.ts +8 -4
- package/dist/core/lbug/schema.js +65 -4
- package/dist/core/tree-sitter/parser-loader.js +7 -1
- package/dist/core/wiki/cursor-client.d.ts +31 -0
- package/dist/core/wiki/cursor-client.js +127 -0
- package/dist/core/wiki/generator.d.ts +28 -9
- package/dist/core/wiki/generator.js +115 -18
- package/dist/core/wiki/graph-queries.d.ts +4 -0
- package/dist/core/wiki/graph-queries.js +7 -1
- package/dist/core/wiki/llm-client.d.ts +2 -0
- package/dist/core/wiki/llm-client.js +8 -4
- package/dist/core/wiki/prompts.d.ts +3 -3
- package/dist/core/wiki/prompts.js +6 -0
- package/dist/mcp/core/embedder.js +11 -3
- package/dist/mcp/core/lbug-adapter.d.ts +5 -0
- package/dist/mcp/core/lbug-adapter.js +23 -2
- package/dist/mcp/local/local-backend.d.ts +38 -5
- package/dist/mcp/local/local-backend.js +804 -63
- package/dist/mcp/resources.js +2 -0
- package/dist/mcp/tools.js +73 -4
- package/dist/server/api.d.ts +19 -1
- package/dist/server/api.js +66 -6
- package/dist/storage/git.d.ts +12 -0
- package/dist/storage/git.js +21 -0
- package/dist/storage/repo-manager.d.ts +3 -0
- package/package.json +25 -16
- package/dist/core/ingestion/named-binding-extraction.d.ts +0 -61
- package/dist/core/ingestion/named-binding-extraction.js +0 -363
- package/dist/core/ingestion/resolvers/index.d.ts +0 -18
- package/dist/core/ingestion/resolvers/index.js +0 -13
- package/dist/core/ingestion/resolvers/jvm.js +0 -87
- package/dist/core/ingestion/resolvers/php.d.ts +0 -15
- package/dist/core/ingestion/resolvers/php.js +0 -35
- package/dist/core/ingestion/type-extractors/index.d.ts +0 -22
- package/dist/core/ingestion/type-extractors/index.js +0 -31
- package/dist/core/ingestion/utils.d.ts +0 -138
- package/dist/core/ingestion/utils.js +0 -1290
- package/scripts/patch-tree-sitter-swift.cjs +0 -74
|
@@ -3,13 +3,15 @@
|
|
|
3
3
|
* Handles wildcard imports, member/static imports, and Kotlin-specific patterns.
|
|
4
4
|
*/
|
|
5
5
|
import type { SuffixIndex } from './utils.js';
|
|
6
|
+
import type { SyntaxNode } from '../utils/ast-helpers.js';
|
|
7
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
6
8
|
/** Kotlin file extensions for JVM resolver reuse */
|
|
7
9
|
export declare const KOTLIN_EXTENSIONS: readonly string[];
|
|
8
10
|
/**
|
|
9
11
|
* Append .* to a Kotlin import path if the AST has a wildcard_import sibling node.
|
|
10
12
|
* Pure function — returns a new string without mutating the input.
|
|
11
13
|
*/
|
|
12
|
-
export declare const appendKotlinWildcard: (importPath: string, importNode:
|
|
14
|
+
export declare const appendKotlinWildcard: (importPath: string, importNode: SyntaxNode) => string;
|
|
13
15
|
/**
|
|
14
16
|
* Resolve a JVM wildcard import (com.example.*) to all matching files.
|
|
15
17
|
* Works for both Java (.java) and Kotlin (.kt, .kts).
|
|
@@ -21,3 +23,10 @@ export declare function resolveJvmWildcard(importPath: string, normalizedFileLis
|
|
|
21
23
|
* Kotlin: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
|
|
22
24
|
*/
|
|
23
25
|
export declare function resolveJvmMemberImport(importPath: string, normalizedFileList: string[], allFileList: string[], extensions: readonly string[], index?: SuffixIndex): string | null;
|
|
26
|
+
/** Java: JVM wildcard -> member import -> standard fallthrough */
|
|
27
|
+
export declare function resolveJavaImport(rawImportPath: string, filePath: string, ctx: ResolveCtx): ImportResult;
|
|
28
|
+
/**
|
|
29
|
+
* Kotlin: JVM wildcard/member with Java-interop fallback -> top-level function imports -> standard.
|
|
30
|
+
* Kotlin can import from .kt/.kts files OR from .java files (Java interop).
|
|
31
|
+
*/
|
|
32
|
+
export declare function resolveKotlinImport(rawImportPath: string, filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JVM import resolution (Java + Kotlin).
|
|
3
|
+
* Handles wildcard imports, member/static imports, and Kotlin-specific patterns.
|
|
4
|
+
*/
|
|
5
|
+
import { SupportedLanguages } from '../../../config/supported-languages.js';
|
|
6
|
+
import { resolveStandard } from './standard.js';
|
|
7
|
+
/** Kotlin file extensions for JVM resolver reuse */
|
|
8
|
+
export const KOTLIN_EXTENSIONS = ['.kt', '.kts'];
|
|
9
|
+
/**
|
|
10
|
+
* Append .* to a Kotlin import path if the AST has a wildcard_import sibling node.
|
|
11
|
+
* Pure function — returns a new string without mutating the input.
|
|
12
|
+
*/
|
|
13
|
+
export const appendKotlinWildcard = (importPath, importNode) => {
|
|
14
|
+
for (let i = 0; i < importNode.childCount; i++) {
|
|
15
|
+
if (importNode.child(i)?.type === 'wildcard_import') {
|
|
16
|
+
return importPath.endsWith('.*') ? importPath : `${importPath}.*`;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return importPath;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Resolve a JVM wildcard import (com.example.*) to all matching files.
|
|
23
|
+
* Works for both Java (.java) and Kotlin (.kt, .kts).
|
|
24
|
+
*/
|
|
25
|
+
export function resolveJvmWildcard(importPath, normalizedFileList, allFileList, extensions, index) {
|
|
26
|
+
// "com.example.util.*" -> "com/example/util"
|
|
27
|
+
const packagePath = importPath.slice(0, -2).replace(/\./g, '/');
|
|
28
|
+
if (index) {
|
|
29
|
+
const candidates = extensions.flatMap(ext => index.getFilesInDir(packagePath, ext));
|
|
30
|
+
// Filter to only direct children (no subdirectories)
|
|
31
|
+
const packageSuffix = '/' + packagePath + '/';
|
|
32
|
+
const packagePrefix = packagePath + '/';
|
|
33
|
+
return candidates.filter(f => {
|
|
34
|
+
const normalized = f.replace(/\\/g, '/');
|
|
35
|
+
// Match both nested (src/models/User.kt) and root-level (models/User.kt) packages
|
|
36
|
+
let afterPkg;
|
|
37
|
+
const idx = normalized.lastIndexOf(packageSuffix);
|
|
38
|
+
if (idx >= 0) {
|
|
39
|
+
afterPkg = normalized.substring(idx + packageSuffix.length);
|
|
40
|
+
}
|
|
41
|
+
else if (normalized.startsWith(packagePrefix)) {
|
|
42
|
+
afterPkg = normalized.substring(packagePrefix.length);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
return !afterPkg.includes('/');
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
// Fallback: linear scan
|
|
51
|
+
const packageSuffix = '/' + packagePath + '/';
|
|
52
|
+
const packagePrefix = packagePath + '/';
|
|
53
|
+
const matches = [];
|
|
54
|
+
for (let i = 0; i < normalizedFileList.length; i++) {
|
|
55
|
+
const normalized = normalizedFileList[i];
|
|
56
|
+
if (!extensions.some(ext => normalized.endsWith(ext)))
|
|
57
|
+
continue;
|
|
58
|
+
// Match both nested (src/models/User.kt) and root-level (models/User.kt) packages
|
|
59
|
+
let afterPackage = null;
|
|
60
|
+
if (normalized.includes(packageSuffix)) {
|
|
61
|
+
afterPackage = normalized.substring(normalized.lastIndexOf(packageSuffix) + packageSuffix.length);
|
|
62
|
+
}
|
|
63
|
+
else if (normalized.startsWith(packagePrefix)) {
|
|
64
|
+
afterPackage = normalized.substring(packagePrefix.length);
|
|
65
|
+
}
|
|
66
|
+
if (afterPackage !== null && !afterPackage.includes('/')) {
|
|
67
|
+
matches.push(allFileList[i]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return matches;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Try to resolve a JVM member/static import by stripping the member name.
|
|
74
|
+
* Java: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
|
|
75
|
+
* Kotlin: "com.example.Constants.VALUE" -> resolve "com.example.Constants"
|
|
76
|
+
*/
|
|
77
|
+
export function resolveJvmMemberImport(importPath, normalizedFileList, allFileList, extensions, index) {
|
|
78
|
+
// Member imports: com.example.Constants.VALUE or com.example.Constants.*
|
|
79
|
+
// The last segment is a member name if it starts with lowercase, is ALL_CAPS, or is a wildcard
|
|
80
|
+
const segments = importPath.split('.');
|
|
81
|
+
if (segments.length < 3)
|
|
82
|
+
return null;
|
|
83
|
+
const lastSeg = segments[segments.length - 1];
|
|
84
|
+
if (lastSeg === '*' || /^[a-z]/.test(lastSeg) || /^[A-Z_]+$/.test(lastSeg)) {
|
|
85
|
+
const classPath = segments.slice(0, -1).join('/');
|
|
86
|
+
for (const ext of extensions) {
|
|
87
|
+
const classSuffix = classPath + ext;
|
|
88
|
+
if (index) {
|
|
89
|
+
const result = index.get(classSuffix) || index.getInsensitive(classSuffix);
|
|
90
|
+
if (result)
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
const fullSuffix = '/' + classSuffix;
|
|
95
|
+
for (let i = 0; i < normalizedFileList.length; i++) {
|
|
96
|
+
if (normalizedFileList[i].endsWith(fullSuffix) ||
|
|
97
|
+
normalizedFileList[i].toLowerCase().endsWith(fullSuffix.toLowerCase())) {
|
|
98
|
+
return allFileList[i];
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
return null;
|
|
105
|
+
}
|
|
106
|
+
/** Java: JVM wildcard -> member import -> standard fallthrough */
|
|
107
|
+
export function resolveJavaImport(rawImportPath, filePath, ctx) {
|
|
108
|
+
if (rawImportPath.endsWith('.*')) {
|
|
109
|
+
const matchedFiles = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
|
|
110
|
+
if (matchedFiles.length > 0)
|
|
111
|
+
return { kind: 'files', files: matchedFiles };
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
const memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
|
|
115
|
+
if (memberResolved)
|
|
116
|
+
return { kind: 'files', files: [memberResolved] };
|
|
117
|
+
}
|
|
118
|
+
return resolveStandard(rawImportPath, filePath, ctx, SupportedLanguages.Java);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Kotlin: JVM wildcard/member with Java-interop fallback -> top-level function imports -> standard.
|
|
122
|
+
* Kotlin can import from .kt/.kts files OR from .java files (Java interop).
|
|
123
|
+
*/
|
|
124
|
+
export function resolveKotlinImport(rawImportPath, filePath, ctx) {
|
|
125
|
+
if (rawImportPath.endsWith('.*')) {
|
|
126
|
+
const matchedFiles = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
|
|
127
|
+
if (matchedFiles.length === 0) {
|
|
128
|
+
const javaMatches = resolveJvmWildcard(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
|
|
129
|
+
if (javaMatches.length > 0)
|
|
130
|
+
return { kind: 'files', files: javaMatches };
|
|
131
|
+
}
|
|
132
|
+
if (matchedFiles.length > 0)
|
|
133
|
+
return { kind: 'files', files: matchedFiles };
|
|
134
|
+
}
|
|
135
|
+
else {
|
|
136
|
+
let memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
|
|
137
|
+
if (!memberResolved) {
|
|
138
|
+
memberResolved = resolveJvmMemberImport(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
|
|
139
|
+
}
|
|
140
|
+
if (memberResolved)
|
|
141
|
+
return { kind: 'files', files: [memberResolved] };
|
|
142
|
+
// Kotlin: top-level function imports (e.g. import models.getUser) have only 2 segments,
|
|
143
|
+
// which resolveJvmMemberImport skips (requires >=3). Fall back to package-directory scan
|
|
144
|
+
// for lowercase last segments (function/property imports). Uppercase last segments
|
|
145
|
+
// (class imports like models.User) fall through to standard suffix resolution.
|
|
146
|
+
const segments = rawImportPath.split('.');
|
|
147
|
+
const lastSeg = segments[segments.length - 1];
|
|
148
|
+
if (segments.length >= 2 && lastSeg[0] && lastSeg[0] === lastSeg[0].toLowerCase()) {
|
|
149
|
+
const pkgWildcard = segments.slice(0, -1).join('.') + '.*';
|
|
150
|
+
let dirFiles = resolveJvmWildcard(pkgWildcard, ctx.normalizedFileList, ctx.allFileList, KOTLIN_EXTENSIONS, ctx.index);
|
|
151
|
+
if (dirFiles.length === 0) {
|
|
152
|
+
dirFiles = resolveJvmWildcard(pkgWildcard, ctx.normalizedFileList, ctx.allFileList, ['.java'], ctx.index);
|
|
153
|
+
}
|
|
154
|
+
if (dirFiles.length > 0)
|
|
155
|
+
return { kind: 'files', files: dirFiles };
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
return resolveStandard(rawImportPath, filePath, ctx, SupportedLanguages.Kotlin);
|
|
159
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP PSR-4 import resolution.
|
|
3
|
+
* Handles use-statement resolution via composer.json autoload mappings.
|
|
4
|
+
*/
|
|
5
|
+
import type { SuffixIndex } from './utils.js';
|
|
6
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
7
|
+
import type { ComposerConfig } from '../language-config.js';
|
|
8
|
+
/**
|
|
9
|
+
* Resolve a PHP use-statement import path using PSR-4 mappings (low-level helper).
|
|
10
|
+
* e.g. "App\Http\Controllers\UserController" -> "app/Http/Controllers/UserController.php"
|
|
11
|
+
*
|
|
12
|
+
* For function/constant imports (use function App\Models\getUser), the last
|
|
13
|
+
* segment is the symbol name, not a class name, so it may not map directly to
|
|
14
|
+
* a file. When PSR-4 class-style resolution fails, we fall back to scanning
|
|
15
|
+
* .php files in the namespace directory.
|
|
16
|
+
*
|
|
17
|
+
* NOTE: The function-import fallback returns the first matching .php file in the
|
|
18
|
+
* namespace directory. When multiple files exist in the same namespace directory,
|
|
19
|
+
* resolution is non-deterministic (depends on Set/index iteration order). This is
|
|
20
|
+
* a known limitation — PHP function imports cannot be resolved to a specific file
|
|
21
|
+
* without parsing all candidate files.
|
|
22
|
+
*/
|
|
23
|
+
export declare function resolvePhpImportInternal(importPath: string, composerConfig: ComposerConfig | null, allFiles: Set<string>, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
|
|
24
|
+
/** PHP: namespace-based resolution via composer.json PSR-4. */
|
|
25
|
+
export declare function resolvePhpImport(rawImportPath: string, _filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PHP PSR-4 import resolution.
|
|
3
|
+
* Handles use-statement resolution via composer.json autoload mappings.
|
|
4
|
+
*/
|
|
5
|
+
import { suffixResolve } from './utils.js';
|
|
6
|
+
/** Get or compute the sorted PSR-4 entries (cached after first call). */
|
|
7
|
+
function getSortedPsr4(config) {
|
|
8
|
+
if (!config.psr4Sorted) {
|
|
9
|
+
const sorted = [...config.psr4.entries()].sort((a, b) => b[0].length - a[0].length);
|
|
10
|
+
config.psr4Sorted = sorted;
|
|
11
|
+
}
|
|
12
|
+
return config.psr4Sorted;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Resolve a PHP use-statement import path using PSR-4 mappings (low-level helper).
|
|
16
|
+
* e.g. "App\Http\Controllers\UserController" -> "app/Http/Controllers/UserController.php"
|
|
17
|
+
*
|
|
18
|
+
* For function/constant imports (use function App\Models\getUser), the last
|
|
19
|
+
* segment is the symbol name, not a class name, so it may not map directly to
|
|
20
|
+
* a file. When PSR-4 class-style resolution fails, we fall back to scanning
|
|
21
|
+
* .php files in the namespace directory.
|
|
22
|
+
*
|
|
23
|
+
* NOTE: The function-import fallback returns the first matching .php file in the
|
|
24
|
+
* namespace directory. When multiple files exist in the same namespace directory,
|
|
25
|
+
* resolution is non-deterministic (depends on Set/index iteration order). This is
|
|
26
|
+
* a known limitation — PHP function imports cannot be resolved to a specific file
|
|
27
|
+
* without parsing all candidate files.
|
|
28
|
+
*/
|
|
29
|
+
export function resolvePhpImportInternal(importPath, composerConfig, allFiles, normalizedFileList, allFileList, index) {
|
|
30
|
+
// Normalize: replace backslashes with forward slashes
|
|
31
|
+
const normalized = importPath.replace(/\\/g, '/');
|
|
32
|
+
// Reject path traversal attempts (defense-in-depth — walker whitelist also prevents this)
|
|
33
|
+
if (normalized.includes('..'))
|
|
34
|
+
return null;
|
|
35
|
+
if (composerConfig) {
|
|
36
|
+
const sorted = getSortedPsr4(composerConfig);
|
|
37
|
+
for (const [nsPrefix, dirPrefix] of sorted) {
|
|
38
|
+
const nsPrefixSlash = nsPrefix.replace(/\\/g, '/');
|
|
39
|
+
if (normalized.startsWith(nsPrefixSlash + '/') || normalized === nsPrefixSlash) {
|
|
40
|
+
const remainder = normalized.slice(nsPrefixSlash.length).replace(/^\//, '');
|
|
41
|
+
// 1. Try class-style PSR-4: full path → file (e.g. App\Models\User → app/Models/User.php)
|
|
42
|
+
const filePath = dirPrefix + (remainder ? '/' + remainder : '') + '.php';
|
|
43
|
+
if (allFiles.has(filePath))
|
|
44
|
+
return filePath;
|
|
45
|
+
if (index) {
|
|
46
|
+
const result = index.getInsensitive(filePath);
|
|
47
|
+
if (result)
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
// 2. Function/constant fallback: strip last segment (symbol name), scan namespace directory.
|
|
51
|
+
// e.g. App\Models\getUser → directory app/Models/, find first .php file in that dir.
|
|
52
|
+
const lastSlash = remainder.lastIndexOf('/');
|
|
53
|
+
const nsDir = lastSlash >= 0
|
|
54
|
+
? dirPrefix + '/' + remainder.slice(0, lastSlash)
|
|
55
|
+
: dirPrefix;
|
|
56
|
+
// Prefer SuffixIndex directory lookup (O(log n + matches)) over linear scan
|
|
57
|
+
if (index) {
|
|
58
|
+
const candidates = index.getFilesInDir(nsDir, '.php');
|
|
59
|
+
if (candidates.length > 0)
|
|
60
|
+
return candidates[0];
|
|
61
|
+
}
|
|
62
|
+
// Fallback: linear scan (only when SuffixIndex unavailable)
|
|
63
|
+
const nsDirPrefix = nsDir.endsWith('/') ? nsDir : nsDir + '/';
|
|
64
|
+
for (const f of allFiles) {
|
|
65
|
+
if (f.startsWith(nsDirPrefix) && f.endsWith('.php') && !f.slice(nsDirPrefix.length).includes('/')) {
|
|
66
|
+
return f;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// Fallback: suffix matching (works without composer.json)
|
|
73
|
+
const pathParts = normalized.split('/').filter(Boolean);
|
|
74
|
+
return suffixResolve(pathParts, normalizedFileList, allFileList, index);
|
|
75
|
+
}
|
|
76
|
+
/** PHP: namespace-based resolution via composer.json PSR-4. */
|
|
77
|
+
export function resolvePhpImport(rawImportPath, _filePath, ctx) {
|
|
78
|
+
const resolved = resolvePhpImportInternal(rawImportPath, ctx.configs.composerConfig, ctx.allFilePaths, ctx.normalizedFileList, ctx.allFileList, ctx.index);
|
|
79
|
+
return resolved ? { kind: 'files', files: [resolved] } : null;
|
|
80
|
+
}
|
|
@@ -2,8 +2,9 @@
|
|
|
2
2
|
* Python import resolution — PEP 328 relative imports and proximity-based bare imports.
|
|
3
3
|
* Import system spec: PEP 302 (original), PEP 451 (current).
|
|
4
4
|
*/
|
|
5
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
5
6
|
/**
|
|
6
|
-
* Resolve a Python import to a file path.
|
|
7
|
+
* Resolve a Python import to a file path (low-level helper).
|
|
7
8
|
*
|
|
8
9
|
* 1. Relative (PEP 328): `.module`, `..module` — 1 dot = current package, each extra dot goes up one level.
|
|
9
10
|
* 2. Proximity bare import: static heuristic — checks the importer's own directory first.
|
|
@@ -12,8 +13,13 @@
|
|
|
12
13
|
* Checks package (__init__.py) before module (.py), matching CPython's finder order (PEP 451 §4).
|
|
13
14
|
* Coexistence of both is physically impossible (same name = file vs directory), so the order
|
|
14
15
|
* only matters for spec compliance.
|
|
15
|
-
* Note: namespace packages (
|
|
16
|
+
* Note: implicit namespace packages (Python 3.3+, directory without __init__.py) are not handled.
|
|
16
17
|
*
|
|
17
18
|
* Returns null to let the caller fall through to suffixResolve.
|
|
18
19
|
*/
|
|
19
|
-
export declare function
|
|
20
|
+
export declare function resolvePythonImportInternal(currentFile: string, importPath: string, allFiles: Set<string>): string | null;
|
|
21
|
+
/**
|
|
22
|
+
* Python: relative imports (PEP 328) + proximity-based bare imports.
|
|
23
|
+
* Falls through to standard suffix resolution when proximity finds no match.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolvePythonImport(rawImportPath: string, filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -3,8 +3,10 @@
|
|
|
3
3
|
* Import system spec: PEP 302 (original), PEP 451 (current).
|
|
4
4
|
*/
|
|
5
5
|
import { tryResolveWithExtensions } from './utils.js';
|
|
6
|
+
import { SupportedLanguages } from '../../../config/supported-languages.js';
|
|
7
|
+
import { resolveStandard } from './standard.js';
|
|
6
8
|
/**
|
|
7
|
-
* Resolve a Python import to a file path.
|
|
9
|
+
* Resolve a Python import to a file path (low-level helper).
|
|
8
10
|
*
|
|
9
11
|
* 1. Relative (PEP 328): `.module`, `..module` — 1 dot = current package, each extra dot goes up one level.
|
|
10
12
|
* 2. Proximity bare import: static heuristic — checks the importer's own directory first.
|
|
@@ -13,11 +15,11 @@ import { tryResolveWithExtensions } from './utils.js';
|
|
|
13
15
|
* Checks package (__init__.py) before module (.py), matching CPython's finder order (PEP 451 §4).
|
|
14
16
|
* Coexistence of both is physically impossible (same name = file vs directory), so the order
|
|
15
17
|
* only matters for spec compliance.
|
|
16
|
-
* Note: namespace packages (
|
|
18
|
+
* Note: implicit namespace packages (Python 3.3+, directory without __init__.py) are not handled.
|
|
17
19
|
*
|
|
18
20
|
* Returns null to let the caller fall through to suffixResolve.
|
|
19
21
|
*/
|
|
20
|
-
export function
|
|
22
|
+
export function resolvePythonImportInternal(currentFile, importPath, allFiles) {
|
|
21
23
|
// Relative import — PEP 328 (https://peps.python.org/pep-0328/)
|
|
22
24
|
if (importPath.startsWith('.')) {
|
|
23
25
|
const dotMatch = importPath.match(/^(\.+)(.*)/);
|
|
@@ -48,5 +50,35 @@ export function resolvePythonImport(currentFile, importPath, allFiles) {
|
|
|
48
50
|
return `${importerDir}/${pathLike}/__init__.py`;
|
|
49
51
|
if (allFiles.has(`${importerDir}/${pathLike}.py`))
|
|
50
52
|
return `${importerDir}/${pathLike}.py`;
|
|
53
|
+
// Ancestor directory walk — Python resolves bare imports against sys.path entries,
|
|
54
|
+
// which typically includes the project root and package directories. Walk up from the
|
|
55
|
+
// importer's directory to find the module in an ancestor, preferring the closest match.
|
|
56
|
+
// This prevents cross-language misresolution (e.g., Python `from middleware import X`
|
|
57
|
+
// resolving to a TypeScript middleware.ts via suffix matching). Issue #417.
|
|
58
|
+
const dirParts = importerDir.split('/');
|
|
59
|
+
for (let i = dirParts.length - 1; i >= 0; i--) {
|
|
60
|
+
const ancestorDir = dirParts.slice(0, i).join('/');
|
|
61
|
+
const prefix = ancestorDir ? `${ancestorDir}/` : '';
|
|
62
|
+
if (allFiles.has(`${prefix}${pathLike}/__init__.py`))
|
|
63
|
+
return `${prefix}${pathLike}/__init__.py`;
|
|
64
|
+
if (allFiles.has(`${prefix}${pathLike}.py`))
|
|
65
|
+
return `${prefix}${pathLike}.py`;
|
|
66
|
+
}
|
|
51
67
|
return null;
|
|
52
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Python: relative imports (PEP 328) + proximity-based bare imports.
|
|
71
|
+
* Falls through to standard suffix resolution when proximity finds no match.
|
|
72
|
+
*/
|
|
73
|
+
export function resolvePythonImport(rawImportPath, filePath, ctx) {
|
|
74
|
+
const resolved = resolvePythonImportInternal(filePath, rawImportPath, ctx.allFilePaths);
|
|
75
|
+
if (resolved) {
|
|
76
|
+
// Store in resolveCache so other files importing the same module skip the
|
|
77
|
+
// ancestor walk. The cache key matches resolveStandard's convention.
|
|
78
|
+
ctx.resolveCache.set(`${filePath}::${rawImportPath}`, resolved);
|
|
79
|
+
return { kind: 'files', files: [resolved] };
|
|
80
|
+
}
|
|
81
|
+
if (rawImportPath.startsWith('.'))
|
|
82
|
+
return null; // relative but unresolved -- don't suffix-match
|
|
83
|
+
return resolveStandard(rawImportPath, filePath, ctx, SupportedLanguages.Python);
|
|
84
|
+
}
|
|
@@ -3,10 +3,13 @@
|
|
|
3
3
|
* Handles path resolution for Ruby's require and require_relative calls.
|
|
4
4
|
*/
|
|
5
5
|
import type { SuffixIndex } from './utils.js';
|
|
6
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
6
7
|
/**
|
|
7
|
-
* Resolve a Ruby require/require_relative path to a matching .rb file.
|
|
8
|
+
* Resolve a Ruby require/require_relative path to a matching .rb file (low-level helper).
|
|
8
9
|
*
|
|
9
10
|
* require_relative paths are pre-normalized to './' prefix by the caller.
|
|
10
11
|
* require paths use suffix matching (gem-style paths like 'json', 'net/http').
|
|
11
12
|
*/
|
|
12
|
-
export declare function
|
|
13
|
+
export declare function resolveRubyImportInternal(importPath: string, normalizedFileList: string[], allFileList: string[], index?: SuffixIndex): string | null;
|
|
14
|
+
/** Ruby: require / require_relative. */
|
|
15
|
+
export declare function resolveRubyImport(rawImportPath: string, _filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -4,12 +4,17 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { suffixResolve } from './utils.js';
|
|
6
6
|
/**
|
|
7
|
-
* Resolve a Ruby require/require_relative path to a matching .rb file.
|
|
7
|
+
* Resolve a Ruby require/require_relative path to a matching .rb file (low-level helper).
|
|
8
8
|
*
|
|
9
9
|
* require_relative paths are pre-normalized to './' prefix by the caller.
|
|
10
10
|
* require paths use suffix matching (gem-style paths like 'json', 'net/http').
|
|
11
11
|
*/
|
|
12
|
-
export function
|
|
12
|
+
export function resolveRubyImportInternal(importPath, normalizedFileList, allFileList, index) {
|
|
13
13
|
const pathParts = importPath.replace(/^\.\//, '').split('/').filter(Boolean);
|
|
14
14
|
return suffixResolve(pathParts, normalizedFileList, allFileList, index);
|
|
15
15
|
}
|
|
16
|
+
/** Ruby: require / require_relative. */
|
|
17
|
+
export function resolveRubyImport(rawImportPath, _filePath, ctx) {
|
|
18
|
+
const resolved = resolveRubyImportInternal(rawImportPath, ctx.normalizedFileList, ctx.allFileList, ctx.index);
|
|
19
|
+
return resolved ? { kind: 'files', files: [resolved] } : null;
|
|
20
|
+
}
|
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
* Rust module import resolution.
|
|
3
3
|
* Handles crate::, super::, self:: prefix paths and :: separators.
|
|
4
4
|
*/
|
|
5
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
5
6
|
/**
|
|
6
|
-
* Resolve Rust use-path to a file.
|
|
7
|
+
* Resolve Rust use-path to a file (low-level helper).
|
|
7
8
|
* Handles crate::, super::, self:: prefixes and :: path separators.
|
|
8
9
|
*/
|
|
9
|
-
export declare function
|
|
10
|
+
export declare function resolveRustImportInternal(currentFile: string, importPath: string, allFiles: Set<string>): string | null;
|
|
10
11
|
/**
|
|
11
12
|
* Try to resolve a Rust module path to a file.
|
|
12
13
|
* Tries: path.rs, path/mod.rs, and with the last segment stripped
|
|
13
14
|
* (last segment might be a symbol name, not a module).
|
|
14
15
|
*/
|
|
15
16
|
export declare function tryRustModulePath(modulePath: string, allFiles: Set<string>): string | null;
|
|
17
|
+
/** Rust: expand grouped imports: use {crate::a, crate::b} and use crate::models::{User, Repo}. */
|
|
18
|
+
export declare function resolveRustImport(rawImportPath: string, filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -2,11 +2,13 @@
|
|
|
2
2
|
* Rust module import resolution.
|
|
3
3
|
* Handles crate::, super::, self:: prefix paths and :: separators.
|
|
4
4
|
*/
|
|
5
|
+
import { SupportedLanguages } from '../../../config/supported-languages.js';
|
|
6
|
+
import { resolveStandard } from './standard.js';
|
|
5
7
|
/**
|
|
6
|
-
* Resolve Rust use-path to a file.
|
|
8
|
+
* Resolve Rust use-path to a file (low-level helper).
|
|
7
9
|
* Handles crate::, super::, self:: prefixes and :: path separators.
|
|
8
10
|
*/
|
|
9
|
-
export function
|
|
11
|
+
export function resolveRustImportInternal(currentFile, importPath, allFiles) {
|
|
10
12
|
let rustPath;
|
|
11
13
|
if (importPath.startsWith('crate::')) {
|
|
12
14
|
// crate:: resolves from src/ directory (standard Rust layout)
|
|
@@ -71,3 +73,40 @@ export function tryRustModulePath(modulePath, allFiles) {
|
|
|
71
73
|
}
|
|
72
74
|
return null;
|
|
73
75
|
}
|
|
76
|
+
/** Rust: expand grouped imports: use {crate::a, crate::b} and use crate::models::{User, Repo}. */
|
|
77
|
+
export function resolveRustImport(rawImportPath, filePath, ctx) {
|
|
78
|
+
// Top-level grouped: use {crate::a, crate::b}
|
|
79
|
+
if (rawImportPath.startsWith('{') && rawImportPath.endsWith('}')) {
|
|
80
|
+
const inner = rawImportPath.slice(1, -1);
|
|
81
|
+
const parts = inner.split(',').map(p => p.trim()).filter(Boolean);
|
|
82
|
+
const resolved = [];
|
|
83
|
+
for (const part of parts) {
|
|
84
|
+
const r = resolveRustImportInternal(filePath, part, ctx.allFilePaths);
|
|
85
|
+
if (r)
|
|
86
|
+
resolved.push(r);
|
|
87
|
+
}
|
|
88
|
+
return resolved.length > 0 ? { kind: 'files', files: resolved } : null;
|
|
89
|
+
}
|
|
90
|
+
// Scoped grouped: use crate::models::{User, Repo}
|
|
91
|
+
const braceIdx = rawImportPath.indexOf('::{');
|
|
92
|
+
if (braceIdx !== -1 && rawImportPath.endsWith('}')) {
|
|
93
|
+
const pathPrefix = rawImportPath.substring(0, braceIdx);
|
|
94
|
+
const braceContent = rawImportPath.substring(braceIdx + 3, rawImportPath.length - 1);
|
|
95
|
+
const items = braceContent.split(',').map(s => s.trim()).filter(Boolean);
|
|
96
|
+
const resolved = [];
|
|
97
|
+
for (const item of items) {
|
|
98
|
+
// Handle `use crate::models::{User, Repo as R}` — strip alias for resolution
|
|
99
|
+
const itemName = item.includes(' as ') ? item.split(' as ')[0].trim() : item;
|
|
100
|
+
const r = resolveRustImportInternal(filePath, `${pathPrefix}::${itemName}`, ctx.allFilePaths);
|
|
101
|
+
if (r)
|
|
102
|
+
resolved.push(r);
|
|
103
|
+
}
|
|
104
|
+
if (resolved.length > 0)
|
|
105
|
+
return { kind: 'files', files: resolved };
|
|
106
|
+
// Fallback: resolve the prefix path itself (e.g. crate::models -> models.rs)
|
|
107
|
+
const prefixResult = resolveRustImportInternal(filePath, pathPrefix, ctx.allFilePaths);
|
|
108
|
+
if (prefixResult)
|
|
109
|
+
return { kind: 'files', files: [prefixResult] };
|
|
110
|
+
}
|
|
111
|
+
return resolveStandard(rawImportPath, filePath, ctx, SupportedLanguages.Rust);
|
|
112
|
+
}
|
|
@@ -5,13 +5,8 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import type { SuffixIndex } from './utils.js';
|
|
7
7
|
import { SupportedLanguages } from '../../../config/supported-languages.js';
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/** Map of alias prefix -> target prefix (e.g., "@/" -> "src/") */
|
|
11
|
-
aliases: Map<string, string>;
|
|
12
|
-
/** Base URL for path resolution (relative to repo root) */
|
|
13
|
-
baseUrl: string;
|
|
14
|
-
}
|
|
8
|
+
import type { ImportResult, ImportResolverFn, ResolveCtx } from './types.js';
|
|
9
|
+
import type { TsconfigPaths } from '../language-config.js';
|
|
15
10
|
/** Max entries in the resolve cache. Beyond this, entries are evicted.
|
|
16
11
|
* 100K entries ≈ 15MB — covers the most common import patterns. */
|
|
17
12
|
export declare const RESOLVE_CACHE_CAP = 100000;
|
|
@@ -26,3 +21,16 @@ export declare const RESOLVE_CACHE_CAP = 100000;
|
|
|
26
21
|
* because they resolve to multiple files.
|
|
27
22
|
*/
|
|
28
23
|
export declare const resolveImportPath: (currentFile: string, importPath: string, allFiles: Set<string>, allFileList: string[], normalizedFileList: string[], resolveCache: Map<string, string | null>, language: SupportedLanguages, tsconfigPaths: TsconfigPaths | null, index?: SuffixIndex) => string | null;
|
|
24
|
+
/**
|
|
25
|
+
* Standard single-file resolution (TS/JS/C/C++ and fallback for other languages).
|
|
26
|
+
* Handles relative imports, tsconfig path aliases, and suffix matching.
|
|
27
|
+
*/
|
|
28
|
+
export declare function resolveStandard(rawImportPath: string, filePath: string, ctx: ResolveCtx, language: SupportedLanguages): ImportResult;
|
|
29
|
+
/** JavaScript: standard single-file resolution. */
|
|
30
|
+
export declare const resolveJavascriptImport: ImportResolverFn;
|
|
31
|
+
/** TypeScript: standard single-file resolution. */
|
|
32
|
+
export declare const resolveTypescriptImport: ImportResolverFn;
|
|
33
|
+
/** C: standard single-file resolution for #include directives. */
|
|
34
|
+
export declare const resolveCImport: ImportResolverFn;
|
|
35
|
+
/** C++: standard single-file resolution for #include directives. */
|
|
36
|
+
export declare const resolveCppImport: ImportResolverFn;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* Used as the fallback when language-specific resolvers don't match.
|
|
5
5
|
*/
|
|
6
6
|
import { tryResolveWithExtensions, suffixResolve } from './utils.js';
|
|
7
|
-
import {
|
|
7
|
+
import { resolveRustImportInternal } from './rust.js';
|
|
8
8
|
import { SupportedLanguages } from '../../../config/supported-languages.js';
|
|
9
9
|
/** Max entries in the resolve cache. Beyond this, entries are evicted.
|
|
10
10
|
* 100K entries ≈ 15MB — covers the most common import patterns. */
|
|
@@ -78,13 +78,13 @@ export const resolveImportPath = (currentFile, importPath, allFiles, allFileList
|
|
|
78
78
|
const inner = importPath.slice(1, -1);
|
|
79
79
|
const parts = inner.split(',').map(p => p.trim()).filter(Boolean);
|
|
80
80
|
for (const part of parts) {
|
|
81
|
-
const partResult =
|
|
81
|
+
const partResult = resolveRustImportInternal(currentFile, part, allFiles);
|
|
82
82
|
if (partResult)
|
|
83
83
|
return cache(partResult);
|
|
84
84
|
}
|
|
85
85
|
return cache(null);
|
|
86
86
|
}
|
|
87
|
-
const rustResult =
|
|
87
|
+
const rustResult = resolveRustImportInternal(currentFile, rustImportPath, allFiles);
|
|
88
88
|
if (rustResult)
|
|
89
89
|
return cache(rustResult);
|
|
90
90
|
// Fall through to generic resolution if Rust-specific didn't match
|
|
@@ -121,3 +121,22 @@ export const resolveImportPath = (currentFile, importPath, allFiles, allFileList
|
|
|
121
121
|
const resolved = suffixResolve(pathParts, normalizedFileList, allFileList, index);
|
|
122
122
|
return cache(resolved);
|
|
123
123
|
};
|
|
124
|
+
// ============================================================================
|
|
125
|
+
// Per-language dispatch functions (moved from import-resolution.ts)
|
|
126
|
+
// ============================================================================
|
|
127
|
+
/**
|
|
128
|
+
* Standard single-file resolution (TS/JS/C/C++ and fallback for other languages).
|
|
129
|
+
* Handles relative imports, tsconfig path aliases, and suffix matching.
|
|
130
|
+
*/
|
|
131
|
+
export function resolveStandard(rawImportPath, filePath, ctx, language) {
|
|
132
|
+
const resolvedPath = resolveImportPath(filePath, rawImportPath, ctx.allFilePaths, ctx.allFileList, ctx.normalizedFileList, ctx.resolveCache, language, ctx.configs.tsconfigPaths, ctx.index);
|
|
133
|
+
return resolvedPath ? { kind: 'files', files: [resolvedPath] } : null;
|
|
134
|
+
}
|
|
135
|
+
/** JavaScript: standard single-file resolution. */
|
|
136
|
+
export const resolveJavascriptImport = (raw, fp, ctx) => resolveStandard(raw, fp, ctx, SupportedLanguages.JavaScript);
|
|
137
|
+
/** TypeScript: standard single-file resolution. */
|
|
138
|
+
export const resolveTypescriptImport = (raw, fp, ctx) => resolveStandard(raw, fp, ctx, SupportedLanguages.TypeScript);
|
|
139
|
+
/** C: standard single-file resolution for #include directives. */
|
|
140
|
+
export const resolveCImport = (raw, fp, ctx) => resolveStandard(raw, fp, ctx, SupportedLanguages.C);
|
|
141
|
+
/** C++: standard single-file resolution for #include directives. */
|
|
142
|
+
export const resolveCppImport = (raw, fp, ctx) => resolveStandard(raw, fp, ctx, SupportedLanguages.CPlusPlus);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swift module import resolution.
|
|
3
|
+
* Handles module imports via Package.swift target map.
|
|
4
|
+
*/
|
|
5
|
+
import type { ImportResult, ResolveCtx } from './types.js';
|
|
6
|
+
/** Swift: module imports via Package.swift target map. */
|
|
7
|
+
export declare function resolveSwiftImport(rawImportPath: string, _filePath: string, ctx: ResolveCtx): ImportResult;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Swift module import resolution.
|
|
3
|
+
* Handles module imports via Package.swift target map.
|
|
4
|
+
*/
|
|
5
|
+
/** Swift: module imports via Package.swift target map. */
|
|
6
|
+
export function resolveSwiftImport(rawImportPath, _filePath, ctx) {
|
|
7
|
+
const swiftPackageConfig = ctx.configs.swiftPackageConfig;
|
|
8
|
+
if (swiftPackageConfig) {
|
|
9
|
+
const targetDir = swiftPackageConfig.targets.get(rawImportPath);
|
|
10
|
+
if (targetDir) {
|
|
11
|
+
const dirPrefix = targetDir + '/';
|
|
12
|
+
const files = [];
|
|
13
|
+
for (let i = 0; i < ctx.normalizedFileList.length; i++) {
|
|
14
|
+
if (ctx.normalizedFileList[i].startsWith(dirPrefix) && ctx.normalizedFileList[i].endsWith('.swift')) {
|
|
15
|
+
files.push(ctx.allFileList[i]);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
if (files.length > 0)
|
|
19
|
+
return { kind: 'files', files };
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
return null; // External framework (Foundation, UIKit, etc.)
|
|
23
|
+
}
|