feat(impact): cross-language blast-radius coverage (22 languages + 14 frameworks) (#708)
Completes the cross-file dependency graph behind impact / affected / explore across all 22 supported languages and 14 web frameworks, validated on real-world repos (measured fair-coverage table added to the README). Per-language resolution + framework resolvers/synthesizers (Lua/Luau require, Shopify OS 2.0 Liquid sections, Delphi forms, Rust cross-module + Rocket macros, Swift Fluent, SvelteKit/Nuxt loader/component conventions, RN/Expo bridges). 0 cross-family false edges, full suite green (1187 passed). See #708. 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
bfa84d32b8
commit
07af3db6c7
@@ -33,17 +33,25 @@ export class LiquidExtractor {
|
||||
// Create file node
|
||||
const fileNode = this.createFileNode();
|
||||
|
||||
// Extract render/include statements (snippet references)
|
||||
this.extractSnippetReferences(fileNode.id);
|
||||
// Shopify OS 2.0 JSON template / section group: link each section `type`
|
||||
// to its `sections/<type>.liquid` file. (No symbol nodes are emitted — the
|
||||
// JSON file just carries the references — so it stays out of any
|
||||
// symbol-bearing-file metric while its sections still get their dependents.)
|
||||
if (this.filePath.endsWith('.json')) {
|
||||
this.extractShopifyJsonSections(fileNode.id);
|
||||
} else {
|
||||
// Extract render/include statements (snippet references)
|
||||
this.extractSnippetReferences(fileNode.id);
|
||||
|
||||
// Extract section references
|
||||
this.extractSectionReferences(fileNode.id);
|
||||
// Extract section references
|
||||
this.extractSectionReferences(fileNode.id);
|
||||
|
||||
// Extract schema block
|
||||
this.extractSchema(fileNode.id);
|
||||
// Extract schema block
|
||||
this.extractSchema(fileNode.id);
|
||||
|
||||
// Extract assign statements as variables
|
||||
this.extractAssignments(fileNode.id);
|
||||
// Extract assign statements as variables
|
||||
this.extractAssignments(fileNode.id);
|
||||
}
|
||||
} catch (error) {
|
||||
this.errors.push({
|
||||
message: `Liquid extraction error: ${error instanceof Error ? error.message : String(error)}`,
|
||||
@@ -86,6 +94,36 @@ export class LiquidExtractor {
|
||||
return fileNode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shopify OS 2.0 JSON template / section group. Both have a `sections` object
|
||||
* mapping an id → `{ "type": "<section-name>", ... }`; the `type` names a
|
||||
* `sections/<type>.liquid` file. Emit a `references` edge to each, so a section
|
||||
* used only from a JSON template (the OS 2.0 norm) is no longer orphaned.
|
||||
*/
|
||||
private extractShopifyJsonSections(fromNodeId: string): void {
|
||||
let parsed: unknown;
|
||||
try {
|
||||
parsed = JSON.parse(this.source);
|
||||
} catch {
|
||||
return; // not valid JSON (or a partial) — nothing to link
|
||||
}
|
||||
const sections = (parsed as { sections?: Record<string, { type?: unknown }> })?.sections;
|
||||
if (!sections || typeof sections !== 'object') return;
|
||||
const seen = new Set<string>();
|
||||
for (const key of Object.keys(sections)) {
|
||||
const type = sections[key]?.type;
|
||||
if (typeof type !== 'string' || seen.has(type)) continue;
|
||||
seen.add(type);
|
||||
this.unresolvedReferences.push({
|
||||
fromNodeId,
|
||||
referenceName: `sections/${type}.liquid`,
|
||||
referenceKind: 'references',
|
||||
line: 1,
|
||||
column: 0,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract {% render 'snippet' %} and {% include 'snippet' %} references
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user