* Check for variables used but never defined.
(dag: BlockDependencyDag, blockMap: Map<string, BlockInfo>)
| 283 | * Check for variables used but never defined. |
| 284 | */ |
| 285 | function checkUndefinedVariables(dag: BlockDependencyDag, blockMap: Map<string, BlockInfo>): LintIssue[] { |
| 286 | const issues: LintIssue[] = [] |
| 287 | |
| 288 | // Collect all defined variables |
| 289 | const definedVars = new Set<string>() |
| 290 | for (const node of dag.nodes) { |
| 291 | for (const v of node.outputVariables) { |
| 292 | definedVars.add(v) |
| 293 | } |
| 294 | } |
| 295 | |
| 296 | // Check each block's input variables |
| 297 | for (const node of dag.nodes) { |
| 298 | const info = blockMap.get(node.id) |
| 299 | if (!info) continue |
| 300 | |
| 301 | for (const inputVar of node.inputVariables) { |
| 302 | // Skip built-in variables and common globals |
| 303 | if (isBuiltinOrGlobal(inputVar)) continue |
| 304 | |
| 305 | if (!definedVars.has(inputVar)) { |
| 306 | issues.push({ |
| 307 | severity: 'error', |
| 308 | code: 'undefined-variable', |
| 309 | message: `Variable "${inputVar}" is used but never defined`, |
| 310 | blockId: node.id, |
| 311 | blockLabel: info.label, |
| 312 | notebookName: info.notebookName, |
| 313 | details: { variable: inputVar }, |
| 314 | }) |
| 315 | } |
| 316 | } |
| 317 | } |
| 318 | |
| 319 | return issues |
| 320 | } |
| 321 | |
| 322 | /** |
| 323 | * Check for circular dependencies between blocks. |
no test coverage detected