mirror of
https://github.com/abhigyanpatwari/GitNexus.git
synced 2026-09-09 22:33:39 +00:00
* Initial plan
* refactor(ingestion): split ImportSemantics into per-strategy hooks
- Add ImportResolverStrategy and ImportResolutionConfig types
- Create createImportResolver factory (resolver-factory.ts)
- Add createStandardStrategy to standard.ts
- Extract per-language strategies from existing resolvers:
goPackageStrategy, javaJvmStrategy, kotlinJvmStrategy,
rustModuleStrategy, pythonImportStrategy, csharpNamespaceStrategy,
phpPsr4Strategy, swiftPackageStrategy, dartPackageStrategy,
dartRelativeStrategy, rubyRequireStrategy
- Create per-language config files in import-resolvers/configs/
- Update all 15 language providers to use createImportResolver(config)
- Add 38 unit tests for factory and strategy composition
- All 3640+ existing tests pass, tsc --noEmit passes
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/c3aec32d-2155-4808-88df-9cd6b2384174
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* chore: remove unused resolver imports from language providers
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/c3aec32d-2155-4808-88df-9cd6b2384174
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* docs: add error propagation note to createImportResolver JSDoc
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/c3aec32d-2155-4808-88df-9cd6b2384174
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* refactor: consolidate strategies into configs, remove legacy resolvers
- Move all strategies from per-language files into their config files
- Remove swift.ts and vue.ts (no shared helpers needed)
- Remove legacy monolithic resolver functions from all per-language files
- Remove unused legacy wrapper functions from standard.ts
- Per-language files now only contain shared internal helpers
- Fix lint warning in languages/php.ts (no-non-null-assertion)
- Update test imports to reference configs/ instead of per-language files
- All 3262+ tests pass, tsc --noEmit passes, zero lint errors
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/f8da6bc2-957c-4d20-87ba-402fa223c6c8
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* refactor: address review feedback — remove dart.ts shim, JSDoc language field, update ARCHITECTURE.md
- Add JSDoc to ImportResolutionConfig.language clarifying it's
documentation-only metadata not used by the factory
- Remove dart.ts legacy shim (was only kept for backward-compat tests)
- Rewrite dart-import-resolver.test.ts to test production strategies
(dartPackageStrategy/dartRelativeStrategy) directly, including full
factory composition via dartImportConfig
- Fix lint warning (no-explicit-any) by using buildSuffixIndex in makeCtx
- Update ARCHITECTURE.md to mention import-resolvers/configs/ as the
extension point for per-language import resolution
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/53f09a4f-1ff1-4a3e-a29c-fda9cdb4c4ef
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* fix: address review comments — revert php.ts, tighten dart test assertion
- Revert php.ts: restore stack.pop()! (the while guard guarantees non-empty)
- Tighten dart relative import test to assert exact result instead of
permissive null-or-files check
Agent-Logs-Url: https://github.com/abhigyanpatwari/GitNexus/sessions/53f09a4f-1ff1-4a3e-a29c-fda9cdb4c4ef
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
* refactor(ingestion): strengthen import-resolver tests and document Vue config intent
Address non-blocking follow-ups from PR #886 review:
- Add inline comment to vueImportConfig explaining intentional
language: Vue / TypeScript-strategy mismatch (Vue SFCs are
preprocessed into TS upstream of import resolution).
- Replace 11 tautological typeof === 'function' assertions with
behavioral tests for goPackageStrategy, kotlinJvmStrategy, and
csharpNamespaceStrategy, including full-chain strategy-order
guards via createImportResolver(config).
- Apply prettier formatting to sibling configs touched during
factory introduction.
Test: 37 passed (previously 26), tsc --noEmit clean.
* test(ingestion): tighten import-resolver assertions and close coverage gaps
Apply ce-review findings on commit f4be87fb:
- Tighten dirSuffix assertions from toContain() to exact toEqual()
shape, catching format regressions (slash normalization, prefix
trimming) the loose matcher would miss.
- Collapse 'if (result?.kind === "package") { expect(dirSuffix)... }'
conditional-dead-branch pattern into single toEqual() assertions.
- Add goPackageStrategy fall-through test: module prefix matches but
package directory contains no .go files -> null (documented branch
in configs/go.ts:27 had no coverage).
- Honestly relabel kotlinImportConfig full-chain test as a behavioral
smoke test rather than a strategy-order guard — standard.ts:137
returns null for '.*' imports so reordering is not observable via
wildcard inputs. Added Kotlin member-import test for extra coverage.
- Add behavioral tests for javaJvmStrategy, rustModuleStrategy,
phpPsr4Strategy, swiftPackageStrategy, rubyRequireStrategy (10 tests
across 5 describe blocks) so strategy unwiring would be caught.
- Extend makeCtx() with optional overrides: Partial<ResolveCtx['configs']>
parameter for declarative per-test config setup.
Test: 50 passed (previously 37), tsc --noEmit clean.
---------
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: magyargergo <11230420+magyargergo@users.noreply.github.com>
Co-authored-by: Gergo Magyar <gergomagyar@icloud.com>
149 lines
6 KiB
TypeScript
149 lines
6 KiB
TypeScript
/**
|
|
* Unit tests for the production Dart import resolution strategies.
|
|
*
|
|
* Tests dartPackageStrategy and dartRelativeStrategy from configs/dart.ts —
|
|
* the actual strategies composed by createImportResolver(dartImportConfig).
|
|
*
|
|
* Key behavioral note:
|
|
* - dartPackageStrategy returns { kind: 'files', files: [] } (absorbing sentinel)
|
|
* for dart: SDK imports and unresolved external packages, which stops the
|
|
* strategy chain. This differs from the old monolithic resolver that returned null.
|
|
* Both produce zero import edges at runtime (applyImportResult treats them identically).
|
|
*/
|
|
|
|
import { describe, it, expect } from 'vitest';
|
|
import {
|
|
dartPackageStrategy,
|
|
dartRelativeStrategy,
|
|
} from '../../src/core/ingestion/import-resolvers/configs/dart.js';
|
|
import { createImportResolver } from '../../src/core/ingestion/import-resolvers/resolver-factory.js';
|
|
import { dartImportConfig } from '../../src/core/ingestion/import-resolvers/configs/dart.js';
|
|
import type { ResolveCtx } from '../../src/core/ingestion/import-resolvers/types.js';
|
|
import { buildSuffixIndex } from '../../src/core/ingestion/import-resolvers/utils.js';
|
|
|
|
function makeCtx(files: string[]): ResolveCtx {
|
|
const allFileList = files;
|
|
const normalizedFileList = files.map((f) => f.replace(/\\/g, '/'));
|
|
const index = buildSuffixIndex(normalizedFileList, allFileList);
|
|
return {
|
|
allFilePaths: new Set(files),
|
|
allFileList,
|
|
normalizedFileList,
|
|
index,
|
|
resolveCache: new Map(),
|
|
configs: {
|
|
tsconfigPaths: null,
|
|
goModule: null,
|
|
composerConfig: null,
|
|
swiftPackageConfig: null,
|
|
csharpConfigs: [],
|
|
},
|
|
};
|
|
}
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// dartPackageStrategy — absorbs SDK / external package imports
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('dartPackageStrategy', () => {
|
|
describe('dart: SDK imports', () => {
|
|
it('absorbs dart:async with empty-files sentinel', () => {
|
|
const result = dartPackageStrategy("'dart:async'", 'lib/main.dart', makeCtx([]));
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
|
|
it('absorbs dart:io with empty-files sentinel', () => {
|
|
const result = dartPackageStrategy("'dart:io'", 'lib/main.dart', makeCtx([]));
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
});
|
|
|
|
describe('package: imports', () => {
|
|
it('resolves local package import to lib/', () => {
|
|
const ctx = makeCtx(['lib/models/user.dart', 'lib/main.dart']);
|
|
const result = dartPackageStrategy("'package:my_app/models/user.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: ['lib/models/user.dart'] });
|
|
});
|
|
|
|
it('absorbs external package imports with empty-files sentinel', () => {
|
|
const ctx = makeCtx(['lib/main.dart']);
|
|
const result = dartPackageStrategy("'package:http/http.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
|
|
it('absorbs malformed package import (no slash) with empty-files sentinel', () => {
|
|
const result = dartPackageStrategy("'package:http'", 'lib/main.dart', makeCtx([]));
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
});
|
|
|
|
describe('relative imports', () => {
|
|
it('returns null for relative imports (chains to dartRelativeStrategy)', () => {
|
|
const ctx = makeCtx([]);
|
|
const result = dartPackageStrategy("'models.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
describe('quote stripping', () => {
|
|
it('strips single quotes', () => {
|
|
const result = dartPackageStrategy("'dart:core'", 'lib/main.dart', makeCtx([]));
|
|
// dart: is absorbed, proving quotes were stripped
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
|
|
it('strips double quotes', () => {
|
|
const result = dartPackageStrategy('"dart:core"', 'lib/main.dart', makeCtx([]));
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// dartRelativeStrategy — bare relative paths via standard resolution
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('dartRelativeStrategy', () => {
|
|
it('resolves bare relative path by prepending ./', () => {
|
|
const ctx = makeCtx(['lib/models/user.dart', 'lib/main.dart']);
|
|
const result = dartRelativeStrategy("'./models/user.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: ['lib/models/user.dart'] });
|
|
});
|
|
|
|
it('returns null for unresolvable relative import', () => {
|
|
const ctx = makeCtx([]);
|
|
const result = dartRelativeStrategy("'nonexistent.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toBeNull();
|
|
});
|
|
});
|
|
|
|
// ---------------------------------------------------------------------------
|
|
// Full resolver — dartImportConfig composed via factory
|
|
// ---------------------------------------------------------------------------
|
|
|
|
describe('Dart import resolver (full config)', () => {
|
|
const resolve = createImportResolver(dartImportConfig);
|
|
|
|
it('absorbs dart: SDK imports', () => {
|
|
const result = resolve("'dart:async'", 'lib/main.dart', makeCtx([]));
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
|
|
it('resolves local package: import', () => {
|
|
const ctx = makeCtx(['lib/models/user.dart']);
|
|
const result = resolve("'package:my_app/models/user.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: ['lib/models/user.dart'] });
|
|
});
|
|
|
|
it('absorbs external package: import', () => {
|
|
const ctx = makeCtx(['lib/main.dart']);
|
|
const result = resolve("'package:http/http.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: [] });
|
|
});
|
|
|
|
it('resolves relative import via second strategy', () => {
|
|
const ctx = makeCtx(['lib/models/user.dart', 'lib/main.dart']);
|
|
const result = resolve("'./models/user.dart'", 'lib/main.dart', ctx);
|
|
expect(result).toEqual({ kind: 'files', files: ['lib/models/user.dart'] });
|
|
});
|
|
});
|