UNPKG

@atomist/automation-client

Version:
162 lines • 7.26 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); const enrichment_1 = require("@atomist/tree-path/manipulation/enrichment"); const expressionEngine_1 = require("@atomist/tree-path/path/expressionEngine"); const pathExpression_1 = require("@atomist/tree-path/path/pathExpression"); const utils_1 = require("@atomist/tree-path/path/utils"); const _ = require("lodash"); const logger_1 = require("../../internal/util/logger"); const projectUtils_1 = require("../../project/util/projectUtils"); const sourceLocationUtils_1 = require("../../project/util/sourceLocationUtils"); const FileHits_1 = require("./FileHits"); const FileParser_1 = require("./FileParser"); /** * Integrate path expressions with project operations to find all matches * @param p project * @param globPatterns file glob patterns * @param parserOrRegistry parser for files * @param pathExpression path expression string or parsed * @param functionRegistry registry to look for path expression functions in * @return {Promise<MatchResult[]>} hit records for each matching file */ function findMatches(p, parserOrRegistry, globPatterns, pathExpression, functionRegistry) { return findFileMatches(p, parserOrRegistry, globPatterns, pathExpression, functionRegistry) .then(fileHits => _.flatten(fileHits.map(f => f.matches))); } exports.findMatches = findMatches; function findFileMatches(p, parserOrRegistry, globPatterns, pathExpression, functionRegistry) { return __awaiter(this, void 0, void 0, function* () { const parsed = utils_1.toPathExpression(pathExpression); const parser = findParser(parsed, parserOrRegistry); if (!parser) { throw new Error(`Cannot find parser for path expression [${pathExpression}]: Using ${parserOrRegistry}`); } const files = yield projectUtils_1.saveFromFiles(p, globPatterns, file => parseFile(parser, parsed, functionRegistry, p, file)); const all = yield Promise.all(files); return all.filter(x => !!x); }); } exports.findFileMatches = findFileMatches; function parseFile(parser, pex, functionRegistry, p, file) { return __awaiter(this, void 0, void 0, function* () { return parser.toAst(file) .then(topLevelProduction => { logger_1.logger.debug("Successfully parsed file '%s' to AST with root node named '%s'. Will execute '%s'", file.path, topLevelProduction.$name, pathExpression_1.stringify(pex)); enrichment_1.defineDynamicProperties(topLevelProduction); const fileNode = { path: file.path, name: file.name, $name: file.name, $children: [topLevelProduction], }; const r = expressionEngine_1.evaluateExpression(fileNode, pex, functionRegistry); if (pathExpression_1.isSuccessResult(r)) { logger_1.logger.debug("%d matches in file '%s'", r.length, file.path); return fillInSourceLocations(file, r) .then(locatedNodes => new FileHits_1.FileHit(p, file, fileNode, locatedNodes)); } else { logger_1.logger.debug("No matches in file '%s'", file.path); return undefined; } }) .catch(err => { logger_1.logger.info("Failed to parse file '%s': %s", file.path, err); return undefined; }); }); } /** * Use file content to fill in LocatedTreeNode.sourceLocation * @param {File} f * @param {TreeNode[]} nodes * @return {Promise<LocatedTreeNode[]>} */ function fillInSourceLocations(f, nodes) { if (nodes.length === 0) { // Optimization. // In this case, let's not read the file content and leave source locations undefined return Promise.resolve(nodes); } return f.getContent() .then(content => { nodes.forEach(n => { n.sourceLocation = sourceLocationUtils_1.toSourceLocation(f, content, n.$offset); }); return nodes; }); } /** * Convenient method to find all values of matching nodes-- * typically, terminals such as identifiers * @param p project * @param globPatterns file glob pattern * @param parserOrRegistry parser for files * @param pathExpression path expression string or parsed * @param functionRegistry registry to look for path expression functions in * @return {Promise<TreeNode[]>} hit record for each matching file */ function findValues(p, parserOrRegistry, globPatterns, pathExpression, functionRegistry) { return findFileMatches(p, parserOrRegistry, globPatterns, pathExpression, functionRegistry) .then(fileHits => _.flatten(fileHits.map(f => f.matches)) .map(m => m.$value)); } exports.findValues = findValues; /** * Integrate path expressions with project operations to find all matches * of a path expression and zap them. Use with care! * @param p project * @param globPatterns file glob pattern * @param parserOrRegistry parser for files * @param pathExpression path expression string or parsed * @param opts options for handling whitespace * @return {Promise<TreeNode[]>} hit record for each matching file */ function zapAllMatches(p, parserOrRegistry, globPatterns, pathExpression, opts = {}) { return doWithAllMatches(p, parserOrRegistry, globPatterns, pathExpression, m => m.zap(opts)); } exports.zapAllMatches = zapAllMatches; /** * Integrate path expressions with project operations to find all matches * of a path expression and perform a mutation on them them. Use with care! * @param p project * @param globPatterns file glob pattern * @param parserOrRegistry parser for files * @param pathExpression path expression string or parsed * @param todo what to do with matches * @return {Promise<TreeNode[]>} hit record for each matching file */ function doWithAllMatches(p, parserOrRegistry, globPatterns, pathExpression, todo) { return findFileMatches(p, parserOrRegistry, globPatterns, pathExpression) .then(fileHits => { fileHits.forEach(fh => { const sorted = fh.matches.sort((m1, m2) => m1.$offset - m2.$offset); sorted.forEach(m => { todo(m); }); }); return p.flush(); }); } exports.doWithAllMatches = doWithAllMatches; function findParser(pathExpression, fp) { if (FileParser_1.isFileParser(fp)) { if (!!fp.validate) { fp.validate(pathExpression); } return fp; } else { return fp.parserFor(pathExpression); } } exports.findParser = findParser; //# sourceMappingURL=astUtils.js.map