UNPKG

@atomist/automation-client

Version:
196 lines • 7.41 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 Microgrammar_1 = require("@atomist/microgrammar/Microgrammar"); const logger_1 = require("../../internal/util/logger"); const projectUtils_1 = require("./projectUtils"); exports.DefaultOpts = { makeUpdatable: true, }; /** * Integrate microgrammars with project operations to find all matches * @param p project * @param globPatterns file glob patterns * @param microgrammar microgrammar to run against each eligible file * @param opts options */ function findMatches(p, globPatterns, microgrammar, opts = exports.DefaultOpts) { return findFileMatches(p, globPatterns, microgrammar, opts) .then(fileHits => { let matches = []; fileHits.forEach(fh => matches = matches.concat(fh.matches)); return matches; }); } exports.findMatches = findMatches; /** * Integrate microgrammars with project operations to find all matches * @param p project * @param globPatterns file glob patterns * @param microgrammar microgrammar to run against each eligible file * @param opts options */ function findFileMatches(p, globPatterns, microgrammar, opts = exports.DefaultOpts) { return projectUtils_1.saveFromFilesAsync(p, globPatterns, file => { return file.getContent() .then((content) => __awaiter(this, void 0, void 0, function* () { const matches = yield microgrammar.findMatchesAsync(transformIfNecessary(content, opts)); if (matches.length > 0) { logger_1.logger.debug(`${matches.length} matches in '${file.path}'`); return new UpdatingFileHits(p, file, matches, content); } else { logger_1.logger.debug(`No matches in '${file.path}'`); return undefined; } })); }); } exports.findFileMatches = findFileMatches; /** * Manipulate each file match containing an actual match. Will automatically match if necessary. * @param p project * @param {string} globPatterns * @param {Microgrammar<M>} microgrammar * @param {(fh: FileWithMatches<M>) => void} action * @param opts options */ function doWithFileMatches(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) { return projectUtils_1.doWithFiles(p, globPatterns, file => { return file.getContent() .then((content) => __awaiter(this, void 0, void 0, function* () { const matches = yield microgrammar.findMatchesAsync(transformIfNecessary(content, opts)); if (matches && matches.length > 0) { logger_1.logger.debug(`${matches.length} matches in '${file.path}'`); const fh = new UpdatingFileHits(p, file, matches, content); if (opts.makeUpdatable === true) { fh.makeUpdatable(); } action(fh); } else { logger_1.logger.debug(`No matches in '${file.path}'`); return undefined; } })); }); } exports.doWithFileMatches = doWithFileMatches; /** * Convenience function to operate on matches in the project. * Works regardless of the number of matches * @param p project * @param {string} globPatterns * @param {Microgrammar<M>} microgrammar * @param {(m: M) => void} action * @param {{makeUpdatable: boolean}} opts */ function doWithMatches(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) { const fileAction = (fh) => { fh.matches.forEach(action); }; return doWithFileMatches(p, globPatterns, microgrammar, fileAction, opts); } exports.doWithMatches = doWithMatches; /** * Convenience function to operate on the sole match in the project. * Fail if zero or more than one. * @param p project * @param {string} globPatterns * @param {Microgrammar<M>} microgrammar * @param {(m: M) => void} action * @param {{makeUpdatable: boolean}} opts */ function doWithUniqueMatch(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) { let count = 0; const guardedAction = (fh) => { if (fh.matches.length !== 1) { throw new Error(`Expected 1 match, not ${fh.matches.length}`); } if (count++ !== 0) { throw new Error("More than one match found in project"); } const m0 = fh.matches[0]; action(m0); }; return doWithFileMatches(p, globPatterns, microgrammar, guardedAction, opts) .then(files => { if (count++ === 0) { throw new Error("No unique match found in project"); } return files; }); } exports.doWithUniqueMatch = doWithUniqueMatch; /** * Similar to doWithUniqueMatch, but accepts zero matches without error * @param p project * @param {string} globPatterns * @param {Microgrammar<M>} microgrammar * @param {(m: M) => void} action * @param {{makeUpdatable: boolean}} opts */ function doWithAtMostOneMatch(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) { let count = 0; const guardedAction = (fh) => { if (fh.matches.length !== 1) { throw new Error(`Expected at most 1 match, not ${fh.matches.length}`); } if (count++ !== 0) { throw new Error("More than one match found in project"); } const m0 = fh.matches[0]; action(m0); }; return doWithFileMatches(p, globPatterns, microgrammar, guardedAction, opts); } exports.doWithAtMostOneMatch = doWithAtMostOneMatch; /** * Hits within a file */ class UpdatingFileHits { constructor(project, file, matches, content) { this.project = project; this.file = file; this.matches = matches; this.content = content; this.updatable = false; } makeUpdatable() { if (!this.updatable) { const um = Microgrammar_1.Microgrammar.updatable(this.matches, this.content); // TODO this cast is ugly this.matches = um.matches; this.file.recordAction(f => { return f.getContent().then(content => { if (content !== um.updated()) { return f.setContent(um.updated()); } return f; }); }); // Track the file this.project.recordAction(p => this.file.flush()); this.updatable = true; } } } /** * Transform content before processing if necessary * @param {string} rawContent * @param {Opts} opts * @return {string} */ function transformIfNecessary(rawContent, opts) { return !!opts && !!opts.contentTransformer ? opts.contentTransformer(rawContent) : rawContent; } //# sourceMappingURL=parseUtils.js.map