mirror of
https://github.com/colbymchenry/codegraph.git
synced 2026-10-22 17:48:44 +08:00
fix(sync): an import of a folder further up links its index file when it appears (#2669)
An import that names a folder only through where it is written (`.`, `..`, `../..`) is parked under no key, so sync tries each where it is written when files are added (#2528). That lookup listed `.`, `./`, `..` and `../` only, so `import { Excalidraw } from "../.."` in excalidraw's tests, or any import of a folder two or more levels up, stayed unlinked after its folder's `index` file was added or restored, though a fresh index links it. It now lists the folder up to twelve levels above, with or without the trailing slash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
+19
-4
@@ -45,6 +45,20 @@ function isLowValueFile(filePath: string, generated?: ReadonlySet<string>): bool
|
||||
|
||||
const SQLITE_PARAM_CHUNK_SIZE = 500;
|
||||
|
||||
/**
|
||||
* How an import names a folder only through where it is written: `.`, or a
|
||||
* folder up to twelve levels above (`..`, `../..`, with or without the
|
||||
* trailing `/`).
|
||||
*/
|
||||
const FOLDER_SPECIFIERS: readonly string[] = (() => {
|
||||
const names = ['.', './'];
|
||||
for (let levels = 1; levels <= 12; levels++) {
|
||||
const up = Array.from({ length: levels }, () => '..').join('/');
|
||||
names.push(up, `${up}/`);
|
||||
}
|
||||
return names;
|
||||
})();
|
||||
|
||||
/** A name a member reference's receiver can be: not a file's name, nor a `module:` key. */
|
||||
const RECEIVER_NAME = /^[A-Za-z_$][\w$]*$/;
|
||||
|
||||
@@ -4222,16 +4236,17 @@ export class QueryBuilder {
|
||||
|
||||
/**
|
||||
* Failed imports of the folder the importing file is in or under (`.`,
|
||||
* `..`). Their tail is empty, since they name a folder only through where
|
||||
* they are written, so no added file's keys find them.
|
||||
* `..`, `../..`). Their tail is empty, since they name a folder only
|
||||
* through where they are written, so no added file's keys find them.
|
||||
*/
|
||||
getFailedFolderImports(): UnresolvedReference[] {
|
||||
const placeholders = FOLDER_SPECIFIERS.map(() => '?').join(',');
|
||||
return (this.db
|
||||
.prepare(
|
||||
`SELECT * FROM unresolved_refs
|
||||
WHERE status = 'failed' AND reference_kind = 'imports' AND reference_name IN ('.', './', '..', '../')`
|
||||
WHERE status = 'failed' AND reference_kind = 'imports' AND reference_name IN (${placeholders})`
|
||||
)
|
||||
.all() as UnresolvedRefRow[])
|
||||
.all(...FOLDER_SPECIFIERS) as UnresolvedRefRow[])
|
||||
.map((row) => ({
|
||||
fromNodeId: row.from_node_id,
|
||||
referenceName: row.reference_name,
|
||||
|
||||
+3
-2
@@ -1064,8 +1064,9 @@ export class CodeGraph {
|
||||
// to an added file (`@excalidraw/common` to `packages/common/src/
|
||||
// index.ts`) waits under its last segment, which that file's keys
|
||||
// never give: look its failed imports up by the specifier itself.
|
||||
// An import of the importer's own folder or the one above (`.`,
|
||||
// `..`) waits under no key at all, so each is tried where written.
|
||||
// An import of the importer's own folder or one above it (`.`,
|
||||
// `..`, `../..`) waits under no key at all, so each is tried
|
||||
// where written.
|
||||
const addedFiles = new Set(result.addedFilePaths ?? []);
|
||||
const resolvesToAdded = (specifier: string, fromFile: string, language: Language): boolean => {
|
||||
const file = this.resolver.resolveModuleFile(specifier, fromFile, language);
|
||||
|
||||
Reference in New Issue
Block a user