The extension → language table was hardcoded, so a codebase using a
non-standard extension for a supported language (e.g. `.dota_lua` for Lua)
had those files silently skipped — no way to opt them in short of patching
the source.
Add an opt-in, project-scoped `codegraph.json` at the repo root:
{ "extensions": { ".dota_lua": "lua", ".tpl": "php" } }
Mappings merge on top of the built-in defaults and take precedence (so a
built-in can be re-pointed, e.g. `.h` → `cpp`). Absent or malformed config
is the zero-config default — byte-identical to prior behavior; an invalid
target language or unparseable file is warned-and-skipped, never fatal.
Implementation:
- New `src/project-config.ts` — `loadExtensionOverrides(rootDir)`, validated
against `isLanguageSupported`, mtime-cached per root.
- `detectLanguage` / `isSourceFile` gain an optional `overrides` arg
(omitting it is the existing behavior).
- Overrides threaded per-operation through every extraction call site
(scan/walk gates, git change-detection, grammar selection, extraction,
the file watcher), resolved from the project root — no process-global
state, so the multi-project daemon stays isolated. The parse worker
receives the resolved language in its message.
Tests: 13 new cases (unit, loader validation/normalization/caching, and a
full-index integration proving a custom-extension file is extracted while
the zero-config path indexes nothing). Worker path smoke-tested via the
built CLI.
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
ba209d9489
commit
d1121e46f0
@@ -121,13 +121,18 @@ export const EXTENSION_MAP: Record<string, Language> = {
|
||||
* Whether a file is one CodeGraph can parse, based purely on its extension.
|
||||
* This is the single source of truth for "should we index this file" — derived
|
||||
* from EXTENSION_MAP so parser support and indexing selection never drift.
|
||||
*
|
||||
* `overrides` is the project's validated custom extension → language map (from
|
||||
* `codegraph.json`); when present its extensions count as indexable in addition
|
||||
* to the built-ins. Omitting it is byte-identical to the zero-config behavior.
|
||||
*/
|
||||
export function isSourceFile(filePath: string): boolean {
|
||||
export function isSourceFile(filePath: string, overrides?: Record<string, Language>): boolean {
|
||||
if (isPlayRoutesFile(filePath)) return true; // Play `conf/routes` is extensionless
|
||||
if (isShopifyLiquidJson(filePath)) return true; // Shopify OS 2.0 JSON templates / section groups
|
||||
const dot = filePath.lastIndexOf('.');
|
||||
if (dot < 0) return false;
|
||||
return filePath.slice(dot).toLowerCase() in EXTENSION_MAP;
|
||||
const ext = filePath.slice(dot).toLowerCase();
|
||||
return ext in EXTENSION_MAP || (!!overrides && ext in overrides);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,9 +271,13 @@ export function getParser(language: Language): Parser | null {
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect language from file extension
|
||||
* Detect language from file extension.
|
||||
*
|
||||
* `overrides` is the project's validated custom extension → language map (from
|
||||
* `codegraph.json`); when present its mappings take precedence over the built-in
|
||||
* `EXTENSION_MAP`. Omitting it is byte-identical to the zero-config behavior.
|
||||
*/
|
||||
export function detectLanguage(filePath: string, source?: string): Language {
|
||||
export function detectLanguage(filePath: string, source?: string, overrides?: Record<string, Language>): Language {
|
||||
// Play `conf/routes` has no grammar — route through the no-symbol path; the
|
||||
// Play framework resolver extracts route nodes from it.
|
||||
if (isPlayRoutesFile(filePath)) return 'yaml';
|
||||
@@ -276,7 +285,7 @@ export function detectLanguage(filePath: string, source?: string): Language {
|
||||
// Shopify OS 2.0 JSON templates / section groups → the Liquid extractor (it
|
||||
// links each section `"type"` to its `sections/<type>.liquid`).
|
||||
if (isShopifyLiquidJson(filePath)) return 'liquid';
|
||||
const lang = EXTENSION_MAP[ext] || 'unknown';
|
||||
const lang = (overrides && overrides[ext]) || EXTENSION_MAP[ext] || 'unknown';
|
||||
|
||||
// .h files could be C, C++, or Objective-C — check source content
|
||||
if (lang === 'c' && ext === '.h' && source) {
|
||||
|
||||
Reference in New Issue
Block a user