UNPKG

@eagleoutice/flowr

Version:

Static Dataflow Analyzer and Program Slicer for the R Programming Language

86 lines 3.61 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.makeMagicCommentHandler = makeMagicCommentHandler; const visitor_1 = require("../../r-bridge/lang-4.x/ast/model/processing/visitor"); const type_1 = require("../../r-bridge/lang-4.x/ast/model/type"); const assert_1 = require("../../util/assert"); function getLoc({ location, info: { fullRange } }) { const loc = location ?? fullRange; (0, assert_1.guard)(loc !== undefined, 'TODO: support location-less nodes!'); return loc; } const magicCommentIdMapper = { 'include_next_line': (n) => { return [getLoc(n)[0] + 1]; }, 'include_this_line': (n) => { return [getLoc(n)[0]]; }, 'include_start': (n, stack) => { stack.push(getLoc(n)[0] + 1); return undefined; }, 'include_end': (n, stack) => { const to = getLoc(n)[0]; (0, assert_1.guard)(stack.length >= 1, `mismatched magic start and end at ${to}`); const from = stack.pop(); const ret = new Array(to - from - 1); for (let i = from; i < to; i++) { ret[i - from] = i; } return ret; } }; const commentTriggerRegex = / flowr@(\w+)/; /** * This takes an {@link NormalizedAst} and returns an auto-select predicate for {@link reconstructToCode}, * which will automatically include lines marked by these special comments! * Please make sure to create one per source as it will use it to cache. * * We support two formats: * - Line comments in the form of `# flowr@include_next_line` or `# flowr@include_this_line`. * - Block comments which start with `# flowr@include_start` and end with `# flowr@include_end`. * This supports nesting, but they have to appear on a single line. * * Please note that these comments have to start exactly with this content to work. * * @param and - Predicate to composite this one with, If you do not pass a predicate, you may assume composition with * {@link doNotAutoSelect}. */ function makeMagicCommentHandler(and) { let lines = undefined; return (node, normalizedAst) => { if (!lines) { lines = new Set(); const startLineStack = []; (0, visitor_1.visitAst)(normalizedAst.ast, n => { const comments = n.info.additionalTokens; if (!comments) { return; } for (const c of comments) { if (c.type !== type_1.RType.Comment || !c.content.startsWith(' flowr@')) { continue; } const match = commentTriggerRegex.exec(c.content); (0, assert_1.guard)(match !== null, `invalid magic comment: ${c.content}`); const idMapper = magicCommentIdMapper[match[1]]; (0, assert_1.guard)(idMapper !== undefined, `unknown magic comment: ${match[1]}`); const ls = idMapper(c, startLineStack); if (ls !== undefined) { for (const l of ls) { lines.add(l); } } } }); (0, assert_1.guard)(startLineStack.length === 0, `mismatched magic start and end at end of file (${JSON.stringify(startLineStack)})`); } const loc = node.location ?? node.info.fullRange; if (loc && lines.has(loc[0])) { return true; } return and?.(node, normalizedAst) ?? false; }; } //# sourceMappingURL=magic-comments.js.map