fix(config): complete project language overrides - #10
Conversation
Independent review and integration gateReviewed head: The condensed contract, correctness/hostile-input, test-honesty, and simplicity review passed with no findings remaining. Review invocation: OMP
Per-file disposition
No blocking or optional findings remain. Exact-head CI and external review are the remaining landing gates. |
|
@coderabbitai review |
|
@coderabbitai review |
There was a problem hiding this comment.
🟡 Changes recommended
Seven unresolved moderate findings affect override-aware passes, resolution, call-scope handling, and ignored .graphifyrc events.
Get a fresh assessment by requesting another Copilot review.
Pull request overview
Completes project-language override support across extraction, resolution, incremental manifests, and watcher lifecycle.
Changes:
- Applies declared suffixes to extractors and JS/Python resolution.
- Invalidates manifests and handles configuration/source watcher events.
- Adds documentation and regression coverage.
File summaries
| File | Summary | Review status |
|---|---|---|
tests/test_language_overrides.py |
Tests extractor and cross-file integration. | No final comments. |
tests/test_language_override_lifecycle.py |
Tests manifests and watcher lifecycle. | No final comments. |
tests/test_language_override_imports.py |
Tests declared module and package imports. | No final comments. |
README.md |
Documents override and lifecycle behavior. | No final comments. |
graphify/watch.py |
Handles configuration and source events. | Moderate (1 vote): process root .graphifyrc events before ignore filtering. |
graphify/symbol_resolution.py |
Includes declared Python files in symbol resolution. | No final comments. |
graphify/extractors/robot.py |
Supports declared Robot resource suffixes. | No final comments. |
graphify/extractors/resolution.py |
Resolves declared JS/Python modules and packages. | Four moderate findings (1 vote each): gate native candidates, package initializers, module paths, and call-scope checks with effective suffixes. |
graphify/extractors/ocaml.py |
Selects OCaml parsing by effective suffix. | No final comments. |
graphify/extractors/csharp.py |
Applies overrides to C# detection. | Moderate (1 vote): propagate effective suffixes through partial, inherited, and dispatch checks. |
graphify/extract.py |
Applies overrides during extraction and cross-file passes. | Moderate (2 votes): replace remaining raw .cs checks in partial merging and base-chain filtering. |
graphify/detect.py |
Tracks overrides in incremental manifests. | No final comments. |
Review details
Suppressed comments (6)
graphify/extractors/csharp.py:153
- Making
_is_cs_file()override-aware does not reach all downstream C# consumers.extract.pystill filters partial-class nodes and inherited-base edges by physical.cs, whilecsharp_dispatch.pyuses the same raw suffix for both its activation guard and node checks. Withlanguage.rzr=csharp, partial types stay split, inherited member calls cannot walk their bases, and interface dispatch exits without adding edges. Propagate the effective-suffix predicate through these passes and add regressions for the declared suffix.
def _is_cs_file(value: object) -> bool:
return isinstance(value, str) and effective_suffix(value) == ".cs"
graphify/extractors/resolution.py:74
- The native candidate loop checks raw suffixes only, so it can return a file that the override has explicitly changed to another language. For example, with
language.ts=phpandlanguage.tpl=typescript, an extensionless./depresolves todep.tshere even though that file is no longer JS; the native directory-index loop below has the same problem. Filter native candidates/indexes througheffective_suffixbefore returning so native precedence is preserved only among JS files.
for ext in _JS_RESOLVE_EXTS + declared_exts:
with_ext = candidate.parent / f"{candidate.name}{ext}"
if with_ext.is_file():
return with_ext
graphify/extractors/resolution.py:2088
- This package-scope check ignores overrides on the native Python suffix. With
language.py=javascript(or another non-Python target),__init__.pyis not a Python initializer, but this still marks its directory as a Python package and suppresses the sys.path-root walk. Check the initializer witheffective_suffixbefore treating it as a Python package.
if any((directory / f"__init__{suffix}").is_file() for suffix in suffixes):
graphify/extractors/resolution.py:2115
- The native package probe (and the
.pymodule probe immediately below it) returns raw.pypaths without checking whether the project remapped.pyaway from Python. Thus a Python file using a declared suffix can bind to a non-Pythondep.pyordep/__init__.py, contrary to the override contract and the intended native-precedence rule. Gate both native returns witheffective_suffix(...) == ".py"before falling back to declared Python suffixes.
if candidate.is_dir():
init_path = candidate / "__init__.py"
if init_path.is_file():
return init_path
if candidate.is_file():
graphify/extractors/resolution.py:1802
- By including remapped files in the JS symbol-resolution path here, the PR also sends them through the generic cross-file call pipeline, but that pipeline's no-implicit-scope guard in
extract.pystill checksrc.source_file.endswith(_JS_TS_CALL_SUFFIXES)against the physical suffix. Alanguage.tpl=typescriptcaller therefore bypasses the guard and can bind an unimported call to a lone same-named export, unlike a native.tscaller. Useeffective_suffixfor that raw-call gate and add a declared-suffix no-import regression.
def _collect_js_symbol_resolution_facts(paths: list[Path], facts: _SymbolResolutionFacts) -> None:
js_paths = [
path for path in paths
if effective_suffix(path) in _JS_CACHE_BYPASS_SUFFIXES
]
graphify/watch.py:2238
- The watcher applies
_is_ignoredbefore checking the root.graphifyrc, so an ignore pattern such as.graphifyrcor.*causes config modify/delete events—and atomic moves whose destination is.graphifyrc—to return here. The old override snapshot then remains active and no rebuild is scheduled. Check the root config (includingdest_path) before the ignore filter.
if ignore_patterns and _is_ignored(path, watch_root_for_ignore, ignore_patterns):
- Files reviewed: 12/12 changed files
- Comments generated: 1
- Review effort level: Lite
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
| _DOTNET_TYPE_EXTS = {".cs", ".razor", ".cshtml"} | ||
| cs_paths = [p for p in paths if p.suffix.lower() in _DOTNET_TYPE_EXTS] | ||
| cs_paths = [p for p in paths if effective_suffix(p).lower() in _DOTNET_TYPE_EXTS] | ||
| if cs_paths: | ||
| cs_results = [r for r, p in zip(per_file, paths) if p.suffix.lower() in _DOTNET_TYPE_EXTS] | ||
| cs_results = [r for r, p in zip(per_file, paths) if effective_suffix(p).lower() in _DOTNET_TYPE_EXTS] |
There was a problem hiding this comment.
Applied in a59563e. Shared C# predicates now cover partial merging, inherited-member base chains, scoped rewiring and interface dispatch. Native/declared regressions failed before the fix and pass unchanged afterward; full suite: 5,720 passed, 14 existing skips.
|
Applied in
Targeted tests ran before production edits: 10 failed / 13 passed, plus 2 failed watcher cases. The same frozen tests now pass; the combined focused set is 124 passed. Full suite: 5,720 passed / 14 existing skips. Ruff, lock and package builds passed. These are the review's concrete corrections, not a new investigation or feature pass. Per the concrete-suggestion fix-round exception, no additional broad adversarial round was opened. Exact-head CI is being rerun. CodeRabbit was requested twice on this fork PR and produced no response. This is recorded as unavailable, not a clean review; the missed-review ledger will reference the landed SHA. |
a59563e
into
issue/3275-refresh-graphify-0-9-59-and
|
Landed by signed fast-forward of the maintained fork branch at |
Summary
Complete the project-language override integration from Graphify-Labs#3075 on top of upstream 0.9.59. This PR targets the maintained fork branch, preserving the upstream-tracking
v8branch and all existing tags.Verification
Current head:
a59563e5c0f63d6a71eaf7df6c4c97ae30564098. The initial changes were independently reviewed at481574300794093d44ea40d5371db0ef058b21fa; the final commit applies the received Copilot corrections with frozen regressions.9be01cc. Copilot regressions ran 10 failed / 13 passed, plus 2 failed watcher cases before their fixes; the same frozen tests now pass.uv lock --check, Ruff, wheel and source-distribution builds passed. Built production bytes match the reviewed source.Chronological regression evidence and the integration history are recorded in pfBlockerNG/pfBlockerNG#3275. No test assertions were weakened; fixture-only maintenance is explicitly separated from production red/green proof.
Refs pfBlockerNG/pfBlockerNG#3275.
External review disposition
All seven Copilot findings were validated and addressed in the final commit; see the resolution audit and inline reply. CodeRabbit was requested twice and remained unavailable (not reported as a clean review).