UNPKG

7.38 kBJavaScriptView Raw
1"use strict";
2var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3 return new (P || (P = Promise))(function (resolve, reject) {
4 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6 function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
7 step((generator = generator.apply(thisArg, _arguments || [])).next());
8 });
9};
10Object.defineProperty(exports, "__esModule", { value: true });
11const microgrammar_1 = require("@atomist/microgrammar");
12const logger_1 = require("../../util/logger");
13const projectUtils_1 = require("./projectUtils");
14exports.DefaultOpts = {
15 makeUpdatable: true,
16};
17/**
18 * Integrate microgrammars with project operations to find all matches
19 * @param p project
20 * @param globPatterns file glob patterns
21 * @param microgrammar microgrammar to run against each eligible file
22 * @param opts options
23 */
24function findMatches(p, globPatterns, microgrammar, opts = exports.DefaultOpts) {
25 return findFileMatches(p, globPatterns, microgrammar, opts)
26 .then(fileHits => {
27 let matches = [];
28 fileHits.forEach(fh => matches = matches.concat(fh.matches));
29 return matches;
30 });
31}
32exports.findMatches = findMatches;
33/**
34 * Integrate microgrammars with project operations to find all matches
35 * @param p project
36 * @param globPatterns file glob patterns
37 * @param microgrammar microgrammar to run against each eligible file
38 * @param opts options
39 */
40function findFileMatches(p, globPatterns, microgrammar, opts = exports.DefaultOpts) {
41 return projectUtils_1.gatherFromFiles(p, globPatterns, file => {
42 return file.getContent()
43 .then((content) => __awaiter(this, void 0, void 0, function* () {
44 const matches = yield microgrammar.findMatchesAsync(transformIfNecessary(content, opts));
45 if (matches.length > 0) {
46 logger_1.logger.debug(`${matches.length} matches in '${file.path}'`);
47 return new UpdatingFileHits(p, file, matches, content);
48 }
49 else {
50 logger_1.logger.debug(`No matches in '${file.path}'`);
51 return undefined;
52 }
53 }));
54 });
55}
56exports.findFileMatches = findFileMatches;
57/**
58 * Manipulate each file match containing an actual match. Will automatically match if necessary.
59 * @param p project
60 * @param {string} globPatterns
61 * @param {Microgrammar<M>} microgrammar
62 * @param {(fh: FileWithMatches<M>) => void} action
63 * @param opts options
64 */
65function doWithFileMatches(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) {
66 return projectUtils_1.doWithFiles(p, globPatterns, file => {
67 return file.getContent()
68 .then((content) => __awaiter(this, void 0, void 0, function* () {
69 const matches = yield microgrammar.findMatchesAsync(transformIfNecessary(content, opts));
70 if (matches && matches.length > 0) {
71 logger_1.logger.debug(`${matches.length} matches in '${file.path}'`);
72 const fh = new UpdatingFileHits(p, file, matches, content);
73 if (opts.makeUpdatable === true) {
74 fh.makeUpdatable();
75 }
76 action(fh);
77 }
78 else {
79 logger_1.logger.debug(`No matches in '${file.path}'`);
80 return undefined;
81 }
82 }));
83 });
84}
85exports.doWithFileMatches = doWithFileMatches;
86/**
87 * Convenience function to operate on matches in the project.
88 * Works regardless of the number of matches
89 * @param p project
90 * @param {string} globPatterns
91 * @param {Microgrammar<M>} microgrammar
92 * @param {(m: M) => void} action
93 * @param {{makeUpdatable: boolean}} opts
94 */
95function doWithMatches(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) {
96 const fileAction = (fh) => {
97 fh.matches.forEach(action);
98 };
99 return doWithFileMatches(p, globPatterns, microgrammar, fileAction, opts);
100}
101exports.doWithMatches = doWithMatches;
102/**
103 * Convenience function to operate on the sole match in the project.
104 * Fail if zero or more than one.
105 * @param p project
106 * @param {string} globPatterns
107 * @param {Microgrammar<M>} microgrammar
108 * @param {(m: M) => void} action
109 * @param {{makeUpdatable: boolean}} opts
110 */
111function doWithUniqueMatch(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) {
112 let count = 0;
113 const guardedAction = (fh) => {
114 if (fh.matches.length !== 1) {
115 throw new Error(`Expected 1 match, not ${fh.matches.length}`);
116 }
117 if (count++ !== 0) {
118 throw new Error("More than one match found in project");
119 }
120 const m0 = fh.matches[0];
121 action(m0);
122 };
123 return doWithFileMatches(p, globPatterns, microgrammar, guardedAction, opts)
124 .then(files => {
125 if (count++ === 0) {
126 throw new Error("No unique match found in project");
127 }
128 return files;
129 });
130}
131exports.doWithUniqueMatch = doWithUniqueMatch;
132/**
133 * Similar to doWithUniqueMatch, but accepts zero matches without error
134 * @param p project
135 * @param {string} globPatterns
136 * @param {Microgrammar<M>} microgrammar
137 * @param {(m: M) => void} action
138 * @param {{makeUpdatable: boolean}} opts
139 */
140function doWithAtMostOneMatch(p, globPatterns, microgrammar, action, opts = exports.DefaultOpts) {
141 let count = 0;
142 const guardedAction = (fh) => {
143 if (fh.matches.length !== 1) {
144 throw new Error(`Expected at most 1 match, not ${fh.matches.length}`);
145 }
146 if (count++ !== 0) {
147 throw new Error("More than one match found in project");
148 }
149 const m0 = fh.matches[0];
150 action(m0);
151 };
152 return doWithFileMatches(p, globPatterns, microgrammar, guardedAction, opts);
153}
154exports.doWithAtMostOneMatch = doWithAtMostOneMatch;
155/**
156 * Hits within a file
157 */
158class UpdatingFileHits {
159 constructor(project, file, matches, content) {
160 this.project = project;
161 this.file = file;
162 this.matches = matches;
163 this.content = content;
164 this.updatable = false;
165 }
166 makeUpdatable() {
167 if (!this.updatable) {
168 const um = microgrammar_1.Microgrammar.updatable(this.matches, this.content);
169 // TODO this cast is ugly
170 this.matches = um.matches;
171 this.file.recordAction(f => {
172 return f.getContent().then(content => {
173 if (content !== um.updated()) {
174 return f.setContent(um.updated());
175 }
176 return f;
177 });
178 });
179 // Track the file
180 this.project.recordAction(p => this.file.flush());
181 this.updatable = true;
182 }
183 }
184}
185/**
186 * Transform content before processing if necessary
187 * @param {string} rawContent
188 * @param {Opts} opts
189 * @return {string}
190 */
191function transformIfNecessary(rawContent, opts) {
192 return !!opts && !!opts.contentTransformer ?
193 opts.contentTransformer(rawContent) :
194 rawContent;
195}
196//# sourceMappingURL=parseUtils.js.map
\No newline at end of file