1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
/**
* @license
* Copyright Google Inc. All Rights Reserved.
*
* Use of this source code is governed by an MIT-style license that can be
* found in the LICENSE file at https://angular.io/license
*/
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
(function (factory) {
if (typeof module === "object" && typeof module.exports === "object") {
var v = factory(require, exports);
if (v !== undefined) module.exports = v;
}
else if (typeof define === "function" && define.amd) {
define("tsickle/src/rewriter", ["require", "exports", "tsickle/src/fileoverview_comment_transformer", "tsickle/src/source_map_utils", "tsickle/src/typescript"], factory);
}
})(function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var fileoverview_comment_transformer_1 = require("tsickle/src/fileoverview_comment_transformer");
var source_map_utils_1 = require("tsickle/src/source_map_utils");
var ts = require("tsickle/src/typescript");
/**
* A Rewriter manages iterating through a ts.SourceFile, copying input
* to output while letting the subclass potentially alter some nodes
* along the way by implementing maybeProcess().
*/
var Rewriter = /** @class */ (function () {
function Rewriter(file, sourceMapper) {
if (sourceMapper === void 0) { sourceMapper = source_map_utils_1.NOOP_SOURCE_MAPPER; }
this.file = file;
this.sourceMapper = sourceMapper;
this.output = [];
/** Errors found while examining the code. */
this.diagnostics = [];
/** Current position in the output. */
this.position = { line: 0, column: 0, position: 0 };
/**
* The current level of recursion through TypeScript Nodes. Used in formatting internal debug
* print statements.
*/
this.indent = 0;
/**
* Skip emitting any code before the given offset. E.g. used to avoid emitting @fileoverview
* comments twice.
*/
this.skipCommentsUpToOffset = -1;
}
Rewriter.prototype.getOutput = function (prefix) {
if (this.indent !== 0) {
throw new Error('visit() failed to track nesting');
}
var out = this.output.join('');
if (prefix) {
// Insert prefix after any leading @fileoverview comments, so they still come first in the
// file. This must not use file.getStart() (comment position in the input file), but rahter
// check comments in the new output, as those (in particular for comments) are unrelated.
var insertionIdx = 0;
try {
for (var _a = __values(ts.getLeadingCommentRanges(out, 0) || []), _b = _a.next(); !_b.done; _b = _a.next()) {
var cr = _b.value;
if (fileoverview_comment_transformer_1.isClosureFileoverviewComment(out.substring(cr.pos, cr.end))) {
insertionIdx = cr.end;
// Include space (in particular line breaks) after a @fileoverview comment; without the
// space seperating it, TypeScript might elide the emit.
while (insertionIdx < out.length && out[insertionIdx].match(/\s/))
insertionIdx++;
}
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a.return)) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
out = out.substring(0, insertionIdx) + prefix + out.substring(insertionIdx);
this.sourceMapper.shiftByOffset(prefix.length);
}
return {
output: out,
diagnostics: this.diagnostics,
};
var e_1, _c;
};
/**
* visit traverses a Node, recursively writing all nodes not handled by this.maybeProcess.
*/
Rewriter.prototype.visit = function (node) {
// this.logWithIndent('node: ' + ts.SyntaxKind[node.kind]);
this.indent++;
try {
if (!this.maybeProcess(node)) {
this.writeNode(node);
}
}
catch (e) {
if (!e.message)
e.message = 'Unhandled error in tsickle';
e.message += "\n at " + ts.SyntaxKind[node.kind] + " in " + this.file.fileName + ":";
var _a = this.file.getLineAndCharacterOfPosition(node.getStart()), line = _a.line, character = _a.character;
e.message += line + 1 + ":" + (character + 1);
throw e;
}
this.indent--;
};
/**
* maybeProcess lets subclasses optionally processes a node.
*
* @return True if the node has been handled and doesn't need to be traversed;
* false to have the node written and its children recursively visited.
*/
Rewriter.prototype.maybeProcess = function (node) {
return false;
};
/** writeNode writes a ts.Node, calling this.visit() on its children. */
Rewriter.prototype.writeNode = function (node, skipComments, newLineIfCommentsStripped) {
if (skipComments === void 0) { skipComments = false; }
if (newLineIfCommentsStripped === void 0) { newLineIfCommentsStripped = true; }
var pos = node.getFullStart();
if (skipComments) {
// To skip comments, we skip all whitespace/comments preceding
// the node. But if there was anything skipped we should emit
// a newline in its place so that the node remains separated
// from the previous node. TODO: don't skip anything here if
// there wasn't any comment.
if (newLineIfCommentsStripped && node.getFullStart() < node.getStart()) {
this.emit('\n');
}
pos = node.getStart();
}
this.writeNodeFrom(node, pos);
};
Rewriter.prototype.writeNodeFrom = function (node, pos, end) {
var _this = this;
if (end === void 0) { end = node.getEnd(); }
if (end <= this.skipCommentsUpToOffset) {
return;
}
var oldSkipCommentsUpToOffset = this.skipCommentsUpToOffset;
this.skipCommentsUpToOffset = Math.max(this.skipCommentsUpToOffset, pos);
ts.forEachChild(node, function (child) {
_this.writeRange(node, pos, child.getFullStart());
_this.visit(child);
pos = child.getEnd();
});
this.writeRange(node, pos, end);
this.skipCommentsUpToOffset = oldSkipCommentsUpToOffset;
};
/**
* Writes all leading trivia (whitespace or comments) on node, or all trivia up to the given
* position. Also marks those trivia as "already emitted" by shifting the skipCommentsUpTo marker.
*/
Rewriter.prototype.writeLeadingTrivia = function (node, upTo) {
if (upTo === void 0) { upTo = 0; }
var upToOffset = upTo || node.getStart();
this.writeRange(node, node.getFullStart(), upTo || node.getStart());
this.skipCommentsUpToOffset = upToOffset;
};
Rewriter.prototype.addSourceMapping = function (node) {
this.writeRange(node, node.getEnd(), node.getEnd());
};
/**
* Write a span of the input file as expressed by absolute offsets.
* These offsets are found in attributes like node.getFullStart() and
* node.getEnd().
*/
Rewriter.prototype.writeRange = function (node, from, to) {
var fullStart = node.getFullStart();
var textStart = node.getStart();
if (from >= fullStart && from < textStart) {
from = Math.max(from, this.skipCommentsUpToOffset);
}
// Add a source mapping. writeRange(from, to) always corresponds to
// original source code, so add a mapping at the current location that
// points back to the location at `from`. The additional code generated
// by tsickle will then be considered part of the last mapped code
// section preceding it. That's arguably incorrect (e.g. for the fake
// methods defining properties), but is good enough for stack traces.
var pos = this.file.getLineAndCharacterOfPosition(from);
this.sourceMapper.addMapping(node, { line: pos.line, column: pos.character, position: from }, this.position, to - from);
// getSourceFile().getText() is wrong here because it has the text of
// the SourceFile node of the AST, which doesn't contain the comments
// preceding that node. Semantically these ranges are just offsets
// into the original source file text, so slice from that.
var text = this.file.text.slice(from, to);
if (text) {
this.emit(text);
}
};
Rewriter.prototype.emit = function (str) {
this.output.push(str);
try {
for (var str_1 = __values(str), str_1_1 = str_1.next(); !str_1_1.done; str_1_1 = str_1.next()) {
var c = str_1_1.value;
this.position.column++;
if (c === '\n') {
this.position.line++;
this.position.column = 0;
}
}
}
catch (e_2_1) { e_2 = { error: e_2_1 }; }
finally {
try {
if (str_1_1 && !str_1_1.done && (_a = str_1.return)) _a.call(str_1);
}
finally { if (e_2) throw e_2.error; }
}
this.position.position += str.length;
var e_2, _a;
};
/** Removes comment metacharacters from a string, to make it safe to embed in a comment. */
Rewriter.prototype.escapeForComment = function (str) {
return str.replace(/\/\*/g, '__').replace(/\*\//g, '__');
};
/* tslint:disable: no-unused-variable */
Rewriter.prototype.logWithIndent = function (message) {
/* tslint:enable: no-unused-variable */
var prefix = new Array(this.indent + 1).join('| ');
console.log(prefix + message);
};
/**
* Produces a compiler error that references the Node's kind. This is useful for the "else"
* branch of code that is attempting to handle all possible input Node types, to ensure all cases
* covered.
*/
Rewriter.prototype.errorUnimplementedKind = function (node, where) {
this.error(node, ts.SyntaxKind[node.kind] + " not implemented in " + where);
};
Rewriter.prototype.error = function (node, messageText) {
this.diagnostics.push({
file: node.getSourceFile(),
start: node.getStart(),
length: node.getEnd() - node.getStart(),
messageText: messageText,
category: ts.DiagnosticCategory.Error,
code: 0,
});
};
return Rewriter;
}());
exports.Rewriter = Rewriter;
/** Returns the string contents of a ts.Identifier. */
function getIdentifierText(identifier) {
// NOTE: the 'text' property on an Identifier may be escaped if it starts
// with '__', so just use getText().
return identifier.getText();
}
exports.getIdentifierText = getIdentifierText;
/** Returns a dot-joined qualified name (foo.bar.Baz). */
function getEntityNameText(name) {
if (ts.isIdentifier(name)) {
return getIdentifierText(name);
}
return getEntityNameText(name.left) + '.' + getIdentifierText(name.right);
}
exports.getEntityNameText = getEntityNameText;
/**
* Converts an escaped TypeScript name into the original source name.
* Prefer getIdentifierText() instead if possible.
*/
function unescapeName(name) {
// See the private function unescapeIdentifier in TypeScript's utilities.ts.
if (name.match(/^___/))
return name.substr(1);
return name;
}
exports.unescapeName = unescapeName;
});
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicmV3cml0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvcmV3cml0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0lBRUgsaUdBQWdGO0lBQ2hGLGlFQUFvRjtJQUNwRiwyQ0FBbUM7SUFFbkM7Ozs7T0FJRztJQUNIO1FBaUJFLGtCQUFtQixJQUFtQixFQUFVLFlBQStDO1lBQS9DLDZCQUFBLEVBQUEsZUFBNkIscUNBQWtCO1lBQTVFLFNBQUksR0FBSixJQUFJLENBQWU7WUFBVSxpQkFBWSxHQUFaLFlBQVksQ0FBbUM7WUFoQnZGLFdBQU0sR0FBYSxFQUFFLENBQUM7WUFDOUIsNkNBQTZDO1lBQ25DLGdCQUFXLEdBQW9CLEVBQUUsQ0FBQztZQUM1QyxzQ0FBc0M7WUFDOUIsYUFBUSxHQUFtQixFQUFDLElBQUksRUFBRSxDQUFDLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxRQUFRLEVBQUUsQ0FBQyxFQUFDLENBQUM7WUFDckU7OztlQUdHO1lBQ0ssV0FBTSxHQUFHLENBQUMsQ0FBQztZQUNuQjs7O2VBR0c7WUFDSywyQkFBc0IsR0FBRyxDQUFDLENBQUMsQ0FBQztRQUdwQyxDQUFDO1FBRUQsNEJBQVMsR0FBVCxVQUFVLE1BQWU7WUFDdkIsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDO2dCQUN0QixNQUFNLElBQUksS0FBSyxDQUFDLGlDQUFpQyxDQUFDLENBQUM7WUFDckQsQ0FBQztZQUNELElBQUksR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO1lBQy9CLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUM7Z0JBQ1gsMEZBQTBGO2dCQUMxRiwyRkFBMkY7Z0JBQzNGLHlGQUF5RjtnQkFDekYsSUFBSSxZQUFZLEdBQUcsQ0FBQyxD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Q0FBQyxZQUFZLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDO1lBQzFCLE1BQU0sQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUNqQyxDQUFDO1FBQ0QsTUFBTSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxHQUFHLEdBQUcsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDO0lBQzVFLENBQUM7SUFMRCw4Q0FLQztJQUVEOzs7T0FHRztJQUNILHNCQUE2QixJQUFZO1FBQ3ZDLDRFQUE0RTtRQUM1RSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1lBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDOUMsTUFBTSxDQUFDLElBQUksQ0FBQztJQUNkLENBQUM7SUFKRCxvQ0FJQyIsInNvdXJjZXNDb250ZW50IjpbIi8qKlxuICogQGxpY2Vuc2VcbiAqIENvcHlyaWdodCBHb29nbGUgSW5jLiBBbGwgUmlnaHRzIFJlc2VydmVkLlxuICpcbiAqIFVzZSBvZiB0aGlzIHNvdXJjZSBjb2RlIGlzIGdvdmVybmVkIGJ5IGFuIE1JVC1zdHlsZSBsaWNlbnNlIHRoYXQgY2FuIGJlXG4gKiBmb3VuZCBpbiB0aGUgTElDRU5TRSBmaWxlIGF0IGh0dHBzOi8vYW5ndWxhci5pby9saWNlbnNlXG4gKi9cblxuaW1wb3J0IHtpc0Nsb3N1cmVGaWxlb3ZlcnZpZXdDb21tZW50fSBmcm9tICcuL2ZpbGVvdmVydmlld19jb21tZW50X3RyYW5zZm9ybWVyJztcbmltcG9ydCB7Tk9PUF9TT1VSQ0VfTUFQUEVSLCBTb3VyY2VNYXBwZXIsIFNvdXJjZVBvc2l0aW9ufSBmcm9tICcuL3NvdXJjZV9tYXBfdXRpbHMnO1xuaW1wb3J0ICogYXMgdHMgZnJvbSAnLi90eXBlc2NyaXB0JztcblxuLyoqXG4gKiBBIFJld3JpdGVyIG1hbmFnZXMgaXRlcmF0aW5nIHRocm91Z2ggYSB0cy5Tb3VyY2VGaWxlLCBjb3B5aW5nIGlucHV0XG4gKiB0byBvdXRwdXQgd2hpbGUgbGV0dGluZyB0aGUgc3ViY2xhc3MgcG90ZW50aWFsbHkgYWx0ZXIgc29tZSBub2Rlc1xuICogYWxvbmcgdGhlIHdheSBieSBpbXBsZW1lbnRpbmcgbWF5YmVQcm9jZXNzKCkuXG4gKi9cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBSZXdyaXRlciB7XG4gIHByaXZhdGUgb3V0cHV0OiBzdHJpbmdbXSA9IFtdO1xuICAvKiogRXJyb3JzIGZvdW5kIHdoaWxlIGV4YW1pbmluZyB0aGUgY29kZS4gKi9cbiAgcHJvdGVjdGVkIGRpYWdub3N0aWNzOiB0cy5EaWFnbm9zdGljW10gPSBbXTtcbiAgLyoqIEN1cnJlbnQgcG9zaXRpb24gaW4gdGhlIG91dHB1dC4gKi9cbiAgcHJpdmF0ZSBwb3NpdGlvbjogU291cmNlUG9zaXRpb24gPSB7bGluZTogMCwgY29sdW1uOiAwLCBwb3NpdGlvbjogMH07XG4gIC8qKlxuICAgKiBUaGUgY3VycmVudCBsZXZlbCBvZiByZWN1cnNpb24gdGhyb3VnaCBUeXBlU2NyaXB0IE5vZGVzLiAgVXNlZCBpbiBmb3JtYXR0aW5nIGludGVybmFsIGRlYnVnXG4gICAqIHByaW50IHN0YXRlbWVudHMuXG4gICAqL1xuICBwcml2YXRlIGluZGVudCA9IDA7XG4gIC8qKlxuICAgKiBTa2lwIGVtaXR0aW5nIGFueSBjb2RlIGJlZm9yZSB0aGUgZ2l2ZW4gb2Zmc2V0LiBFLmcuIHVzZWQgdG8gYXZvaWQgZW1pdHRpbmcgQGZpbGVvdmVydmlld1xuICAgKiBjb21tZW50cyB0d2ljZS5cbiAgICovXG4gIHByaXZhdGUgc2tpcENvbW1lbnRzVXBUb09mZnNldCA9IC0xO1xuXG4gIGNvbnN0cnVjdG9yKHB1YmxpYyBmaWxlOiB0cy5Tb3VyY2VGaWxlLCBwcml2YXRlIHNvdXJjZU1hcHBlcjogU291cmNlTWFwcGVyID0gTk9PUF9TT1VSQ0VfTUFQUEVSKSB7XG4gIH1cblxuICBnZXRPdXRwdXQocHJlZml4Pzogc3RyaW5nKToge291dHB1dDogc3RyaW5nLCBkaWFnbm9zdGljczogdHMuRGlhZ25vc3RpY1tdfSB7XG4gICAgaWYgKHRoaXMuaW5kZW50ICE9PSAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoJ3Zpc2l0KCkgZmFpbGVkIHRvIHRyYWNrIG5lc3RpbmcnKTtcbiAgICB9XG4gICAgbGV0IG91dCA9IHRoaXMub3V0cHV0LmpvaW4oJycpO1xuICAgIGlmIChwcmVmaXgpIHtcbiAgICAgIC8vIEluc2VydCBwcmVmaXggYWZ0ZXIgYW55IGxlYWRpbmcgQGZpbGVvdmVydmlldyBjb21tZW50cywgc28gdGhleSBzdGlsbCBjb21lIGZpcnN0IGluIHRoZVxuICAgICAgLy8gZmlsZS4gVGhpcyBtdXN0IG5vdCB1c2UgZmlsZS5nZXRTdGFydCgpIChjb21tZW50IHBvc2l0aW9uIGluIHRoZSBpbnB1dCBmaWxlKSwgYnV0IHJhaHRlclxuICAgICAgLy8gY2hlY2sgY29tbWVudHMgaW4gdGhlIG5ldyBvdXRwdXQsIGFzIHRob3NlIChpbiBwYXJ0aWN1bGFyIGZvciBjb21tZW50cykgYXJlIHVucmVsYXRlZC5cbiAgICAgIGxldCBpbnNlcnRpb25JZHggPSAwO1xuICAgICAgZm9yIChjb25zdCBjciBvZiB0cy5nZXRMZWFkaW5nQ29tbWVudFJhbmdlcyhvdXQsIDApIHx8IFtdKSB7XG4gICAgICAgIGlmIChpc0Nsb3N1cmVGaWxlb3ZlcnZpZXdDb21tZW50KG91dC5zdWJzdHJpbmcoY3IucG9zLCBjci5lbmQpKSkge1xuICAgICAgICAgIGluc2VydGlvbklkeCA9IGNyLmVuZDtcbiAgICAgICAgICAvLyBJbmNsdWRlIHNwYWNlIChpbiBwYXJ0aWN1bGFyIGxpbmUgYnJlYWtzKSBhZnRlciBhIEBmaWxlb3ZlcnZpZXcgY29tbWVudDsgd2l0aG91dCB0aGVcbiAgICAgICAgICAvLyBzcGFjZSBzZXBlcmF0aW5nIGl0LCBUeXBlU2NyaXB0IG1pZ2h0IGVsaWRlIHRoZSBlbWl0LlxuICAgICAgICAgIHdoaWxlIChpbnNlcnRpb25JZHggPCBvdXQubGVuZ3RoICYmIG91dFtpbnNlcnRpb25JZHhdLm1hdGNoKC9cXHMvKSkgaW5zZXJ0aW9uSWR4Kys7XG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIG91dCA9IG91dC5zdWJzdHJpbmcoMCwgaW5zZXJ0aW9uSWR4KSArIHByZWZpeCArIG91dC5zdWJzdHJpbmcoaW5zZXJ0aW9uSWR4KTtcbiAgICAgIHRoaXMuc291cmNlTWFwcGVyLnNoaWZ0QnlPZmZzZXQocHJlZml4Lmxlbmd0aCk7XG4gICAgfVxuICAgIHJldHVybiB7XG4gICAgICBvdXRwdXQ6IG91dCxcbiAgICAgIGRpYWdub3N0aWNzOiB0aGlzLmRpYWdub3N0aWNzLFxuICAgIH07XG4gIH1cblxuICAvKipcbiAgICogdmlzaXQgdHJhdmVyc2VzIGEgTm9kZSwgcmVjdXJzaXZlbHkgd3JpdGluZyBhbGwgbm9kZXMgbm90IGhhbmRsZWQgYnkgdGhpcy5tYXliZVByb2Nlc3MuXG4gICAqL1xuICB2aXNpdChub2RlOiB0cy5Ob2RlKSB7XG4gICAgLy8gdGhpcy5sb2dXaXRoSW5kZW50KCdub2RlOiAnICsgdHMuU3ludGF4S2luZFtub2RlLmtpbmRdKTtcbiAgICB0aGlzLmluZGVudCsrO1xuICAgIHRyeSB7XG4gICAgICBpZiAoIXRoaXMubWF5YmVQcm9jZXNzKG5vZGUpKSB7XG4gICAgICAgIHRoaXMud3JpdGVOb2RlKG5vZGUpO1xuICAgICAgfVxuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgIGlmICghZS5tZXNzYWdlKSBlLm1lc3NhZ2UgPSAnVW5oYW5kbGVkIGVycm9yIGluIHRzaWNrbGUnO1xuICAgICAgZS5tZXNzYWdlICs9IGBcXG4gYXQgJHt0cy5TeW50YXhLaW5kW25vZGUua2luZF19IGluICR7dGhpcy5maWxlLmZpbGVOYW1lfTpgO1xuICAgICAgY29uc3Qge2xpbmUsIGNoYXJhY3Rlcn0gPSB0aGlzLmZpbGUuZ2V0TGluZUFuZENoYXJhY3Rlck9mUG9zaXRpb24obm9kZS5nZXRTdGFydCgpKTtcbiAgICAgIGUubWVzc2FnZSArPSBgJHtsaW5lICsgMX06JHtjaGFyYWN0ZXIgKyAxfWA7XG4gICAgICB0aHJvdyBlO1xuICAgIH1cbiAgICB0aGlzLmluZGVudC0tO1xuICB9XG5cbiAgLyoqXG4gICAqIG1heWJlUHJvY2VzcyBsZXRzIHN1YmNsYXNzZXMgb3B0aW9uYWxseSBwcm9jZXNzZXMgYSBub2RlLlxuICAgKlxuICAgKiBAcmV0dXJuIFRydWUgaWYgdGhlIG5vZGUgaGFzIGJlZW4gaGFuZGxlZCBhbmQgZG9lc24ndCBuZWVkIHRvIGJlIHRyYXZlcnNlZDtcbiAgICogICAgZmFsc2UgdG8gaGF2ZSB0aGUgbm9kZSB3cml0dGVuIGFuZCBpdHMgY2hpbGRyZW4gcmVjdXJzaXZlbHkgdmlzaXRlZC5cbiAgICovXG4gIHByb3RlY3RlZCBtYXliZVByb2Nlc3Mobm9kZTogdHMuTm9kZSk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBmYWxzZTtcbiAgfVxuXG4gIC8qKiB3cml0ZU5vZGUgd3JpdGVzIGEgdHMuTm9kZSwgY2FsbGluZyB0aGlzLnZpc2l0KCkgb24gaXRzIGNoaWxkcmVuLiAqL1xuICB3cml0ZU5vZGUobm9kZTogdHMuTm9kZSwgc2tpcENvbW1lbnRzID0gZmFsc2UsIG5ld0xpbmVJZkNvbW1lbnRzU3RyaXBwZWQgPSB0cnVlKSB7XG4gICAgbGV0IHBvcyA9IG5vZGUuZ2V0RnVsbFN0YXJ0KCk7XG4gICAgaWYgKHNraXBDb21tZW50cykge1xuICAgICAgLy8gVG8gc2tpcCBjb21tZW50cywgd2Ugc2tpcCBhbGwgd2hpdGVzcGFjZS9jb21tZW50cyBwcmVjZWRpbmdcbiAgICAgIC8vIHRoZSBub2RlLiAgQnV0IGlmIHRoZXJlIHdhcyBhbnl0aGluZyBza2lwcGVkIHdlIHNob3VsZCBlbWl0XG4gICAgICAvLyBhIG5ld2xpbmUgaW4gaXRzIHBsYWNlIHNvIHRoYXQgdGhlIG5vZGUgcmVtYWlucyBzZXBhcmF0ZWRcbiAgICAgIC8vIGZyb20gdGhlIHByZXZpb3VzIG5vZGUuICBUT0RPOiBkb24ndCBza2lwIGFueXRoaW5nIGhlcmUgaWZcbiAgICAgIC8vIHRoZXJlIHdhc24ndCBhbnkgY29tbWVudC5cbiAgICAgIGlmIChuZXdMaW5lSWZDb21tZW50c1N0cmlwcGVkICYmIG5vZGUuZ2V0RnVsbFN0YXJ0KCkgPCBub2RlLmdldFN0YXJ0KCkpIHtcbiAgICAgICAgdGhpcy5lbWl0KCdcXG4nKTtcbiAgICAgIH1cbiAgICAgIHBvcyA9IG5vZGUuZ2V0U3RhcnQoKTtcbiAgICB9XG4gICAgdGhpcy53cml0ZU5vZGVGcm9tKG5vZGUsIHBvcyk7XG4gIH1cblxuICB3cml0ZU5vZGVGcm9tKG5vZGU6IHRzLk5vZGUsIHBvczogbnVtYmVyLCBlbmQgPSBub2RlLmdldEVuZCgpKSB7XG4gICAgaWYgKGVuZCA8PSB0aGlzLnNraXBDb21tZW50c1VwVG9PZmZzZXQpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG4gICAgY29uc3Qgb2xkU2tpcENvbW1lbnRzVXBUb09mZnNldCA9IHRoaXMuc2tpcENvbW1lbnRzVXBUb09mZnNldDtcbiAgICB0aGlzLnNraXBDb21tZW50c1VwVG9PZmZzZXQgPSBNYXRoLm1heCh0aGlzLnNraXBDb21tZW50c1VwVG9PZmZzZXQsIHBvcyk7XG4gICAgdHMuZm9yRWFjaENoaWxkKG5vZGUsIGNoaWxkID0+IHtcbiAgICAgIHRoaXMud3JpdGVSYW5nZShub2RlLCBwb3MsIGNoaWxkLmdldEZ1bGxTdGFydCgpKTtcbiAgICAgIHRoaXMudmlzaXQoY2hpbGQpO1xuICAgICAgcG9zID0gY2hpbGQuZ2V0RW5kKCk7XG4gICAgfSk7XG4gICAgdGhpcy53cml0ZVJhbmdlKG5vZGUsIHBvcywgZW5kKTtcbiAgICB0aGlzLnNraXBDb21tZW50c1VwVG9PZmZzZXQgPSBvbGRTa2lwQ29tbWVudHNVcFRvT2Zmc2V0O1xuICB9XG5cbiAgLyoqXG4gICAqIFdyaXRlcyBhbGwgbGVhZGluZyB0cml2aWEgKHdoaXRlc3BhY2Ugb3IgY29tbWVudHMpIG9uIG5vZGUsIG9yIGFsbCB0cml2aWEgdXAgdG8gdGhlIGdpdmVuXG4gICAqIHBvc2l0aW9uLiBBbHNvIG1hcmtzIHRob3NlIHRyaXZpYSBhcyBcImFscmVhZHkgZW1pdHRlZFwiIGJ5IHNoaWZ0aW5nIHRoZSBza2lwQ29tbWVudHNVcFRvIG1hcmtlci5cbiAgICovXG4gIHdyaXRlTGVhZGluZ1RyaXZpYShub2RlOiB0cy5Ob2RlLCB1cFRvID0gMCkge1xuICAgIGNvbnN0IHVwVG9PZmZzZXQgPSB1cFRvIHx8IG5vZGUuZ2V0U3RhcnQoKTtcbiAgICB0aGlzLndyaXRlUmFuZ2Uobm9kZSwgbm9kZS5nZXRGdWxsU3RhcnQoKSwgdXBUbyB8fCBub2RlLmdldFN0YXJ0KCkpO1xuICAgIHRoaXMuc2tpcENvbW1lbnRzVXBUb09mZnNldCA9IHVwVG9PZmZzZXQ7XG4gIH1cblxuICBhZGRTb3VyY2VNYXBwaW5nKG5vZGU6IHRzLk5vZGUpIHtcbiAgICB0aGlzLndyaXRlUmFuZ2Uobm9kZSwgbm9kZS5nZXRFbmQoKSwgbm9kZS5nZXRFbmQoKSk7XG4gIH1cblxuICAvKipcbiAgICogV3JpdGUgYSBzcGFuIG9mIHRoZSBpbnB1dCBmaWxlIGFzIGV4cHJlc3NlZCBieSBhYnNvbHV0ZSBvZmZzZXRzLlxuICAgKiBUaGVzZSBvZmZzZXRzIGFyZSBmb3VuZCBpbiBhdHRyaWJ1dGVzIGxpa2Ugbm9kZS5nZXRGdWxsU3RhcnQoKSBhbmRcbiAgICogbm9kZS5nZXRFbmQoKS5cbiAgICovXG4gIHdyaXRlUmFuZ2Uobm9kZTogdHMuTm9kZSwgZnJvbTogbnVtYmVyLCB0bzogbnVtYmVyKSB7XG4gICAgY29uc3QgZnVsbFN0YXJ0ID0gbm9kZS5nZXRGdWxsU3RhcnQoKTtcbiAgICBjb25zdCB0ZXh0U3RhcnQgPSBub2RlLmdldFN0YXJ0KCk7XG4gICAgaWYgKGZyb20gPj0gZnVsbFN0YXJ0ICYmIGZyb20gPCB0ZXh0U3RhcnQpIHtcbiAgICAgIGZyb20gPSBNYXRoLm1heChmcm9tLCB0aGlzLnNraXBDb21tZW50c1VwVG9PZmZzZXQpO1xuICAgIH1cbiAgICAvLyBBZGQgYSBzb3VyY2UgbWFwcGluZy4gd3JpdGVSYW5nZShmcm9tLCB0bykgYWx3YXlzIGNvcnJlc3BvbmRzIHRvXG4gICAgLy8gb3JpZ2luYWwgc291cmNlIGNvZGUsIHNvIGFkZCBhIG1hcHBpbmcgYXQgdGhlIGN1cnJlbnQgbG9jYXRpb24gdGhhdFxuICAgIC8vIHBvaW50cyBiYWNrIHRvIHRoZSBsb2NhdGlvbiBhdCBgZnJvbWAuIFRoZSBhZGRpdGlvbmFsIGNvZGUgZ2VuZXJhdGVkXG4gICAgLy8gYnkgdHNpY2tsZSB3aWxsIHRoZW4gYmUgY29uc2lkZXJlZCBwYXJ0IG9mIHRoZSBsYXN0IG1hcHBlZCBjb2RlXG4gICAgLy8gc2VjdGlvbiBwcmVjZWRpbmcgaXQuIFRoYXQncyBhcmd1YWJseSBpbmNvcnJlY3QgKGUuZy4gZm9yIHRoZSBmYWtlXG4gICAgLy8gbWV0aG9kcyBkZWZpbmluZyBwcm9wZXJ0aWVzKSwgYnV0IGlzIGdvb2QgZW5vdWdoIGZvciBzdGFjayB0cmFjZXMuXG4gICAgY29uc3QgcG9zID0gdGhpcy5maWxlLmdldExpbmVBbmRDaGFyYWN0ZXJPZlBvc2l0aW9uKGZyb20pO1xuICAgIHRoaXMuc291cmNlTWFwcGVyLmFkZE1hcHBpbmcoXG4gICAgICAgIG5vZGUsIHtsaW5lOiBwb3MubGluZSwgY29sdW1uOiBwb3MuY2hhcmFjdGVyLCBwb3NpdGlvbjogZnJvbX0sIHRoaXMucG9zaXRpb24sIHRvIC0gZnJvbSk7XG4gICAgLy8gZ2V0U291cmNlRmlsZSgpLmdldFRleHQoKSBpcyB3cm9uZyBoZXJlIGJlY2F1c2UgaXQgaGFzIHRoZSB0ZXh0IG9mXG4gICAgLy8gdGhlIFNvdXJjZUZpbGUgbm9kZSBvZiB0aGUgQVNULCB3aGljaCBkb2Vzbid0IGNvbnRhaW4gdGhlIGNvbW1lbnRzXG4gICAgLy8gcHJlY2VkaW5nIHRoYXQgbm9kZS4gIFNlbWFudGljYWxseSB0aGVzZSByYW5nZXMgYXJlIGp1c3Qgb2Zmc2V0c1xuICAgIC8vIGludG8gdGhlIG9yaWdpbmFsIHNvdXJjZSBmaWxlIHRleHQsIHNvIHNsaWNlIGZyb20gdGhhdC5cbiAgICBjb25zdCB0ZXh0ID0gdGhpcy5maWxlLnRleHQuc2xpY2UoZnJvbSwgdG8pO1xuICAgIGlmICh0ZXh0KSB7XG4gICAgICB0aGlzLmVtaXQodGV4dCk7XG4gICAgfVxuICB9XG5cbiAgZW1pdChzdHI6IHN0cmluZykge1xuICAgIHRoaXMub3V0cHV0LnB1c2goc3RyKTtcbiAgICBmb3IgKGNvbnN0IGMgb2Ygc3RyKSB7XG4gICAgICB0aGlzLnBvc2l0aW9uLmNvbHVtbisrO1xuICAgICAgaWYgKGMgPT09ICdcXG4nKSB7XG4gICAgICAgIHRoaXMucG9zaXRpb24ubGluZSsrO1xuICAgICAgICB0aGlzLnBvc2l0aW9uLmNvbHVtbiA9IDA7XG4gICAgICB9XG4gICAgfVxuICAgIHRoaXMucG9zaXRpb24ucG9zaXRpb24gKz0gc3RyLmxlbmd0aDtcbiAgfVxuXG4gIC8qKiBSZW1vdmVzIGNvbW1lbnQgbWV0YWNoYXJhY3RlcnMgZnJvbSBhIHN0cmluZywgdG8gbWFrZSBpdCBzYWZlIHRvIGVtYmVkIGluIGEgY29tbWVudC4gKi9cbiAgZXNjYXBlRm9yQ29tbWVudChzdHI6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgcmV0dXJuIHN0ci5yZXBsYWNlKC9cXC9cXCovZywgJ19fJykucmVwbGFjZSgvXFwqXFwvL2csICdfXycpO1xuICB9XG5cbiAgLyogdHNsaW50OmRpc2FibGU6IG5vLXVudXNlZC12YXJpYWJsZSAqL1xuICBsb2dXaXRoSW5kZW50KG1lc3NhZ2U6IHN0cmluZykge1xuICAgIC8qIHRzbGludDplbmFibGU6IG5vLXVudXNlZC12YXJpYWJsZSAqL1xuICAgIGNvbnN0IHByZWZpeCA9IG5ldyBBcnJheSh0aGlzLmluZGVudCArIDEpLmpvaW4oJ3wgJyk7XG4gICAgY29uc29sZS5sb2cocHJlZml4ICsgbWVzc2FnZSk7XG4gIH1cblxuICAvKipcbiAgICogUHJvZHVjZXMgYSBjb21waWxlciBlcnJvciB0aGF0IHJlZmVyZW5jZXMgdGhlIE5vZGUncyBraW5kLiAgVGhpcyBpcyB1c2VmdWwgZm9yIHRoZSBcImVsc2VcIlxuICAgKiBicmFuY2ggb2YgY29kZSB0aGF0IGlzIGF0dGVtcHRpbmcgdG8gaGFuZGxlIGFsbCBwb3NzaWJsZSBpbnB1dCBOb2RlIHR5cGVzLCB0byBlbnN1cmUgYWxsIGNhc2VzXG4gICAqIGNvdmVyZWQuXG4gICAqL1xuICBlcnJvclVuaW1wbGVtZW50ZWRLaW5kKG5vZGU6IHRzLk5vZGUsIHdoZXJlOiBzdHJpbmcpIHtcbiAgICB0aGlzLmVycm9yKG5vZGUsIGAke3RzLlN5bnRheEtpbmRbbm9kZS5raW5kXX0gbm90IGltcGxlbWVudGVkIGluICR7d2hlcmV9YCk7XG4gIH1cblxuICBlcnJvcihub2RlOiB0cy5Ob2RlLCBtZXNzYWdlVGV4dDogc3RyaW5nKSB7XG4gICAgdGhpcy5kaWFnbm9zdGljcy5wdXNoKHtcbiAgICAgIGZpbGU6IG5vZGUuZ2V0U291cmNlRmlsZSgpLFxuICAgICAgc3RhcnQ6IG5vZGUuZ2V0U3RhcnQoKSxcbiAgICAgIGxlbmd0aDogbm9kZS5nZXRFbmQoKSAtIG5vZGUuZ2V0U3RhcnQoKSxcbiAgICAgIG1lc3NhZ2VUZXh0LFxuICAgICAgY2F0ZWdvcnk6IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5FcnJvcixcbiAgICAgIGNvZGU6IDAsXG4gICAgfSk7XG4gIH1cbn1cblxuLyoqIFJldHVybnMgdGhlIHN0cmluZyBjb250ZW50cyBvZiBhIHRzLklkZW50aWZpZXIuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0SWRlbnRpZmllclRleHQoaWRlbnRpZmllcjogdHMuSWRlbnRpZmllcik6IHN0cmluZyB7XG4gIC8vIE5PVEU6IHRoZSAndGV4dCcgcHJvcGVydHkgb24gYW4gSWRlbnRpZmllciBtYXkgYmUgZXNjYXBlZCBpZiBpdCBzdGFydHNcbiAgLy8gd2l0aCAnX18nLCBzbyBqdXN0IHVzZSBnZXRUZXh0KCkuXG4gIHJldHVybiBpZGVudGlmaWVyLmdldFRleHQoKTtcbn1cblxuLyoqIFJldHVybnMgYSBkb3Qtam9pbmVkIHF1YWxpZmllZCBuYW1lIChmb28uYmFyLkJheikuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0RW50aXR5TmFtZVRleHQobmFtZTogdHMuRW50aXR5TmFtZSk6IHN0cmluZyB7XG4gIGlmICh0cy5pc0lkZW50aWZpZXIobmFtZSkpIHtcbiAgICByZXR1cm4gZ2V0SWRlbnRpZmllclRleHQobmFtZSk7XG4gIH1cbiAgcmV0dXJuIGdldEVudGl0eU5hbWVUZXh0KG5hbWUubGVmdCkgKyAnLicgKyBnZXRJZGVudGlmaWVyVGV4dChuYW1lLnJpZ2h0KTtcbn1cblxuLyoqXG4gKiBDb252ZXJ0cyBhbiBlc2NhcGVkIFR5cGVTY3JpcHQgbmFtZSBpbnRvIHRoZSBvcmlnaW5hbCBzb3VyY2UgbmFtZS5cbiAqIFByZWZlciBnZXRJZGVudGlmaWVyVGV4dCgpIGluc3RlYWQgaWYgcG9zc2libGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiB1bmVzY2FwZU5hbWUobmFtZTogc3RyaW5nKTogc3RyaW5nIHtcbiAgLy8gU2VlIHRoZSBwcml2YXRlIGZ1bmN0aW9uIHVuZXNjYXBlSWRlbnRpZmllciBpbiBUeXBlU2NyaXB0J3MgdXRpbGl0aWVzLnRzLlxuICBpZiAobmFtZS5tYXRjaCgvXl9fXy8pKSByZXR1cm4gbmFtZS5zdWJzdHIoMSk7XG4gIHJldHVybiBuYW1lO1xufVxuIl19