refactor: simplify Swift fixes after code review

- Extract shared addSwiftImplicitImports() helper (DRY — was duplicated
  in processImports and processImportsFromExtracted)
- Cache importMap.get(srcFile) outside inner loop (avoids redundant
  Map lookups per iteration)
- Fix export-detection: use \bprivate\b regex instead of includes()
  to avoid substring false positives
- Fix groupSwiftFilesByTarget: check path boundary with indexOf + char
  check instead of loose includes()

All 141 relevant tests pass (queries + imports + calls).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
marxo126 2026-03-21 10:15:09 +01:00
parent 65bc99c448
commit 561a54a154
2 changed files with 3 additions and 51 deletions

View file

@ -205,7 +205,7 @@ const swiftExportChecker: ExportChecker = (node, _name) => {
while (current) {
if (current.type === 'modifiers' || current.type === 'visibility_modifier') {
const text = current.text || '';
if (text.includes('private') || text.includes('fileprivate')) return false;
if (/\bprivate\b|\bfileprivate\b/.test(text)) return false;
}
current = current.parent;
}

View file

@ -306,34 +306,7 @@ export const processImports = async (
// Tree is now owned by the LRU cache — no manual delete needed
}
// ---- Swift: implicit module-level visibility ----
// In Swift, all files in the same module/target see each other without explicit imports.
// Add implicit import edges between all Swift files so the call resolver can find
// cross-file symbols at Tier 2a (import-scoped) instead of falling to Tier 3 (global).
const swiftFiles = files
.filter(f => getLanguageFromFilename(f.path) === SupportedLanguages.Swift)
.map(f => f.path);
if (swiftFiles.length > 1) {
// Group Swift files by target directory (SPM target or common root)
const targetGroups = groupSwiftFilesByTarget(swiftFiles, configs.swiftPackageConfig);
for (const group of targetGroups.values()) {
for (const srcFile of group) {
for (const otherFile of group) {
if (srcFile === otherFile) continue;
// Only add if not already imported (from explicit `import TargetName`)
if (importMap.has(srcFile) && importMap.get(srcFile)!.has(otherFile)) continue;
addImportEdge(srcFile, otherFile);
}
}
}
if (isDev) {
const totalGroups = targetGroups.size;
console.log(`📊 Swift: ${swiftFiles.length} files in ${totalGroups} target group(s), implicit imports added`);
}
}
addSwiftImplicitImports(files, configs.swiftPackageConfig, importMap, addImportEdge);
if (skippedByLang && skippedByLang.size > 0) {
for (const [lang, count] of skippedByLang.entries()) {
@ -404,28 +377,7 @@ export const processImportsFromExtracted = async (
onProgress?.(totalFiles, totalFiles);
// ---- Swift: implicit module-level visibility (fast path) ----
const swiftFilePaths = files
.filter(f => getLanguageFromFilename(f.path) === SupportedLanguages.Swift)
.map(f => f.path);
if (swiftFilePaths.length > 1) {
const targetGroups = groupSwiftFilesByTarget(swiftFilePaths, configs.swiftPackageConfig);
for (const group of targetGroups.values()) {
for (const srcFile of group) {
for (const otherFile of group) {
if (srcFile === otherFile) continue;
if (importMap.has(srcFile) && importMap.get(srcFile)!.has(otherFile)) continue;
addImportEdge(srcFile, otherFile);
}
}
}
if (isDev) {
console.log(`📊 Swift: ${swiftFilePaths.length} files in ${targetGroups.size} target group(s), implicit imports added (fast path)`);
}
}
addSwiftImplicitImports(files, configs.swiftPackageConfig, importMap, addImportEdge, ' (fast path)');
if (isDev) {
console.log(`📊 Import processing (fast path): ${getResolvedCount()}/${totalImportsFound} imports resolved to graph edges`);