Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

- Symbols defined in Svelte and Vue `<script>` blocks were reported one line below where they actually are — a function on line 3 was reported at line 4 — which offset every script-block symbol's location in search, `codegraph_node`, and explore output. Line numbers now match the file exactly. Re-index a project to benefit. (Svelte, Vue)
- Doc comments are now captured for exported, `const`-assigned, and decorated declarations, and the documentation a symbol carries is now clean across every supported language. Previously a comment above `export class X`, `export const fn = () => …`, a plain `const fn = () => …`, or a decorated Python `def`/`class` (`@app.route(...)`, `@dataclass`) was dropped entirely — only comments directly above a plain declaration were kept. CodeGraph now finds the comment through the `export` / `const` / decorator wrapper. Comment-marker cleanup was also rounded out for every language CodeGraph supports: Rust/Swift/Kotlin doc lines (`///`, `//!`), Python/Ruby/shell `#`, Lua/Luau (`--` and `--[[ ]]`), and Pascal (`{ }` and `(* *)`) no longer leave stray markers in the stored text — validated end-to-end across all 19 code languages plus Svelte/Vue `<script>` blocks. (#780). Thanks @caleb-kaiser.
- `codegraph status` no longer reports a perpetual pending change for a file inside a committed dependency or build directory (for example `vendor/` or `node_modules/`) that the index deliberately excludes. Editing such a tracked-but-excluded file showed up as a pending addition that no `codegraph sync` or `codegraph index` could ever clear, because indexing correctly skips those directories — so `status` and a full re-index disagreed forever. Change detection now applies the same exclusion rules as indexing. Thanks @monochrome3694. (#766)
- Go method calls made through a chained factory function now resolve to the correct type. A call like `New().Method()` used to drop the receiver, so the chained method attached to a same-named method on an unrelated type — or didn't resolve. CodeGraph now captures Go return types (a pointer `*Foo` resolves to `Foo`, and a multi-return `(*Foo, error)` to its first result), infers the chained receiver's type from what the factory function returns, and resolves the method on it — including methods promoted from an embedded struct — creating the edge only when the type or an embedded type genuinely has the method. Existing Go indexes should be re-indexed (`codegraph index -f`) to benefit. (#750) (Go)
- Scala method calls made through a companion-object factory, a fluent chain, or a case-class `apply` now resolve to the correct type. A call like `Foo.create().bar()` or `Builder(cfg).bar()` used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated type — most often mis-attributing a standard-library `Option` / `Iterator` `.map` / `.flatMap` / `.foreach` onto your own same-named class. CodeGraph now captures Scala return types (a generic `List[Foo]` resolves to its container `List`, a qualified `pkg.Foo` to `Foo`), infers the chained receiver's type from what the inner call returns or constructs, and resolves the method on it — including methods inherited from a trait the type extends — creating the edge only when that type or one of its traits genuinely has the method (so a wrong inference produces no edge instead of a misleading one). Existing Scala indexes should be re-indexed (`codegraph index -f`) to benefit. (#750) (Scala)
- Rust method calls made through a chained associated function now resolve to the correct type. A call like `Foo::new().bar()` or `Foo::with(cfg).build()` used to drop the receiver, so the chained method silently attached to a same-named method on an unrelated type — or didn't resolve. CodeGraph now captures Rust return types (`-> Self` resolves to the implementing type), infers the chained receiver's type from what the associated function returns, and resolves the method on it — including methods provided by a trait the type implements (via the new `impl Trait for Type` relationships) — creating the edge only when the type or one of its traits genuinely has the method. Existing Rust indexes should be re-indexed (`codegraph index -f`) to benefit. (#750) (Rust)
Expand Down
30 changes: 30 additions & 0 deletions __tests__/sync.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -302,5 +302,35 @@ describe('Sync Module', () => {
expect(result.filesRemoved).toBe(0);
expect(result.changedFilePaths).toBeUndefined();
});

it('should not report changes to excluded tracked files (issue #766)', () => {
// A committed dependency dir (e.g. vendor/) is excluded from the index by
// the built-in default ignores, even though its files are tracked in git.
// git status still reports working-tree changes there, but the git
// fast-path of change detection must apply the same ignore matcher as
// enumeration — otherwise status flags a pending change that `index` will
// never produce (a perpetual phantom add that no sync can clear).
const vendorDir = path.join(testDir, 'vendor');
fs.mkdirSync(vendorDir);
fs.writeFileSync(path.join(vendorDir, 'lib.ts'), `export function vendored() { return 1; }`);
git('add', '-A');
git('commit', '-m', 'add vendored dep');

// Modify the tracked-but-excluded file → git status now flags it...
fs.writeFileSync(path.join(vendorDir, 'lib.ts'), `export function vendored() { return 2; }`);
// ...alongside a genuine change to real source code.
fs.writeFileSync(
path.join(testDir, 'src', 'index.ts'),
`export function hello() { return 'changed'; }`
);

const changes = cg.getChangedFiles();

// The excluded file must not leak into change detection...
expect(changes.added).not.toContain('vendor/lib.ts');
expect(changes.modified).not.toContain('vendor/lib.ts');
// ...while the genuine source change is still detected.
expect(changes.modified).toContain('src/index.ts');
});
});
});
11 changes: 11 additions & 0 deletions src/extraction/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1540,11 +1540,22 @@ export class ExtractionOrchestrator {
}
}

// Apply the same ignore matcher as enumeration (getGitVisibleFiles). git
// status reports working-tree changes to tracked files inside committed
// dependency/build dirs (vendor/, node_modules/, …) that the index
// deliberately excludes — without this filter those leak into `added`,
// disagreeing with what `index` produces (a phantom change no sync clears).
// Deletions stay unfiltered: they only act on paths already in the DB,
// where removal is always correct (and lets a now-excluded dir's stale
// entries clean up). (See issue #766.)
const ignoreMatcher = buildDefaultIgnore(this.rootDir);

// Modified + added files — read + hash, compare with DB. Untracked (`??`)
// files stay untracked in git even after indexing, so they must be
// hash-compared like modified files instead of always counting as added —
// otherwise status reports them as pending forever. (See issue #206.)
for (const filePath of [...gitChanges.modified, ...gitChanges.added]) {
if (ignoreMatcher.ignores(filePath)) continue;
const fullPath = path.join(this.rootDir, filePath);
let content: string;
try {
Expand Down