* Delegate a ` ... ` tag's SQL body to the `cfquery` grammar. * `#hash#` expressions inside the SQL (e.g. `#getCurrentUser().getId()#` in a * WHERE clause) are real CFML calls/references — tree-sitter-cfml's `cfquery` * grammar parses them structurally (same `call_expressio
(queryTag: SyntaxNode, parentId: string | undefined)
| 405 | * or contains-edges to merge. |
| 406 | */ |
| 407 | private delegateQueryTag(queryTag: SyntaxNode, parentId: string | undefined): void { |
| 408 | const content = queryTag.namedChildren.find((c: SyntaxNode) => c.type === 'cf_query_content'); |
| 409 | if (!content) return; |
| 410 | |
| 411 | const sql = this.source.substring(content.startIndex, content.endIndex); |
| 412 | const startLine = content.startPosition.row; |
| 413 | |
| 414 | const extractor = new TreeSitterExtractor(this.filePath, sql, 'cfquery'); |
| 415 | const result = extractor.extract(); |
| 416 | |
| 417 | const innerFileNodeId = result.nodes.find((n) => n.kind === 'file')?.id; |
| 418 | for (const ref of result.unresolvedReferences) { |
| 419 | ref.line += startLine; |
| 420 | ref.filePath = this.filePath; |
| 421 | ref.language = this.language; |
| 422 | if ((!ref.fromNodeId || ref.fromNodeId === innerFileNodeId) && parentId) ref.fromNodeId = parentId; |
| 423 | this.unresolvedReferences.push(ref); |
| 424 | } |
| 425 | for (const error of result.errors) { |
| 426 | if (error.line) error.line += startLine; |
| 427 | this.errors.push(error); |
| 428 | } |
| 429 | } |
| 430 | |
| 431 | /** Read a `cf_attribute`'s value by name from a tag node's direct `cf_attribute`/`cf_tag_attributes` children. */ |
| 432 | private tagAttr(tag: SyntaxNode, attrName: string): string | undefined { |
no test coverage detected