* Delegate each `@code`/`@functions`/`@{` block's C# to the tree-sitter C# * extractor and attribute the block's external references (service/DTO calls, * `new X()`, type uses) to the component. The block is wrapped in a synthetic * class so tree-sitter parses the component's fields/methods
(componentId: string)
| 250 | * types, not per-member nodes. Degrades gracefully if the C# grammar isn't loaded. |
| 251 | */ |
| 252 | private processCodeBlocks(componentId: string): void { |
| 253 | if (!isLanguageSupported('csharp')) return; |
| 254 | for (const block of this.extractCodeBlocks()) { |
| 255 | if (!block.content.trim()) continue; |
| 256 | let result: ExtractionResult; |
| 257 | try { |
| 258 | result = new TreeSitterExtractor( |
| 259 | this.filePath, |
| 260 | `class __RazorCode__ {\n${block.content}\n}`, |
| 261 | 'csharp' |
| 262 | ).extract(); |
| 263 | } catch { |
| 264 | continue; // grammar not loaded / parse failure — skip this block |
| 265 | } |
| 266 | // The synthetic wrapper adds one line before the block content; map ref |
| 267 | // lines back to the .razor file (display only — coverage is line-agnostic). |
| 268 | for (const ref of result.unresolvedReferences) { |
| 269 | this.unresolvedReferences.push({ |
| 270 | ...ref, |
| 271 | fromNodeId: componentId, |
| 272 | line: ref.line + block.lineOffset - 1, |
| 273 | column: ref.column, |
| 274 | filePath: this.filePath, |
| 275 | language: 'razor', |
| 276 | }); |
| 277 | } |
| 278 | } |
| 279 | } |
| 280 | } |
no test coverage detected