diff --git a/CHANGELOG.md b/CHANGELOG.md
index a192d8e28..70cfa4bb6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -11,7 +11,7 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
### New Features
-- ASP.NET Razor (`.cshtml`) and Blazor (`.razor`) markup are now parsed for code relationships. A `@model` / `@inherits` / `@inject` directive links the view to the C# view-model, base type, or service it names; a Blazor `` tag (plus `@typeof(...)` and generic `TItem="..."` arguments) links to the component class. So a view-model, component, or service referenced only from markup is no longer reported as having no dependents, and editing it surfaces the views that use it. (ASP.NET, Blazor)
+- ASP.NET Razor (`.cshtml`) and Blazor (`.razor`) markup are now parsed for code relationships. A `@model` / `@inherits` / `@inject` directive links the view to the C# view-model, base type, or service it names; a Blazor `` tag (plus `@typeof(...)` and generic `TItem="..."` arguments) links to the component class; and the C# inside `@code { }` / `@functions { }` / `@{ }` blocks is analyzed too, so services and types used in component logic are linked. A view-model, component, or service referenced only from markup is no longer reported as having no dependents, and editing it surfaces the views that use it. (ASP.NET, Blazor)
- `codegraph status --json` now also reports the running CLI `version`, the index directory (`indexPath`), and a `lastIndexed` timestamp (ISO-8601, or null when nothing's indexed yet), so CI and scripts can pin the CLI version and check index freshness from a single command. A matching `CodeGraph.getLastIndexedAt()` library method exposes the same freshness check without shelling out. Thanks @12122J and @eddieran. (#329)
### Fixes
diff --git a/__tests__/extraction.test.ts b/__tests__/extraction.test.ts
index 1636797d6..a80cf69d5 100644
--- a/__tests__/extraction.test.ts
+++ b/__tests__/extraction.test.ts
@@ -4005,6 +4005,26 @@ describe('Razor / Blazor markup extraction', () => {
const htmlNodes = cg.getNodesByKind('class').filter((n) => n.name === 'div' || n.name === 'input');
expect(htmlNodes.length, 'no node for HTML elements').toBe(0);
});
+
+ it('delegates Blazor @code block C# to cover types used in component logic', async () => {
+ fs.writeFileSync(
+ path.join(tempDir, 'CatalogService.cs'),
+ `namespace App { public class CatalogService { public void Load() { } } }`
+ );
+ fs.writeFileSync(
+ path.join(tempDir, 'List.razor'),
+ `
Catalog
\n\n@code {\n private CatalogService _svc = new CatalogService();\n void Refresh() { _svc.Load(); }\n}\n`
+ );
+
+ cg = CodeGraph.initSync(tempDir);
+ await cg.indexAll();
+ cg.resolveReferences();
+
+ const svc = cg.getNodesByKind('class').find((n) => n.name === 'CatalogService');
+ expect(svc, 'CatalogService class').toBeDefined();
+ const deps = [...cg.getImpactRadius(svc!.id, 2).nodes.values()].map((n) => n.filePath ?? '');
+ expect(deps.some((p) => p.endsWith('List.razor')), '@code usage links the component to the service').toBe(true);
+ });
});
describe('Default import resolution (renamed default export)', () => {
diff --git a/src/extraction/razor-extractor.ts b/src/extraction/razor-extractor.ts
index ffa11f8b0..5f89b5ceb 100644
--- a/src/extraction/razor-extractor.ts
+++ b/src/extraction/razor-extractor.ts
@@ -1,5 +1,7 @@
-import { Node, ExtractionResult, ExtractionError, UnresolvedReference } from '../types';
+import { Node, Edge, ExtractionResult, ExtractionError, UnresolvedReference } from '../types';
import { generateNodeId } from './tree-sitter-helpers';
+import { TreeSitterExtractor } from './tree-sitter';
+import { isLanguageSupported } from './grammars';
/**
* RazorExtractor — extracts code relationships from ASP.NET Razor (`.cshtml`)
@@ -49,6 +51,7 @@ export class RazorExtractor {
private filePath: string;
private source: string;
private nodes: Node[] = [];
+ private edges: Edge[] = [];
private unresolvedReferences: UnresolvedReference[] = [];
private errors: ExtractionError[] = [];
@@ -67,6 +70,11 @@ export class RazorExtractor {
if (this.filePath.toLowerCase().endsWith('.razor')) {
this.extractComponentTags(componentId);
}
+ // Delegate the C# in `@code { }` / `@functions { }` / `@{ }` blocks to the
+ // C# tree-sitter extractor (the Blazor analog of Svelte's