1 | ;
|
2 | var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
3 | function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
4 | return new (P || (P = Promise))(function (resolve, reject) {
|
5 | function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
6 | function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
7 | function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
8 | step((generator = generator.apply(thisArg, _arguments || [])).next());
|
9 | });
|
10 | };
|
11 | Object.defineProperty(exports, "__esModule", { value: true });
|
12 | const convert_1 = require("../convert");
|
13 | const Utils = require("../utils");
|
14 | const languageclient_1 = require("../languageclient");
|
15 | const atom_1 = require("atom");
|
16 | /** Public: Adapts the documentSymbolProvider of the language server to the Outline View supplied by Atom IDE UI. */
|
17 | class OutlineViewAdapter {
|
18 | constructor() {
|
19 | this._cancellationTokens = new WeakMap();
|
20 | }
|
21 | /**
|
22 | * Public: Determine whether this adapter can be used to adapt a language server based on the serverCapabilities
|
23 | * matrix containing a documentSymbolProvider.
|
24 | *
|
25 | * @param serverCapabilities The {ServerCapabilities} of the language server to consider.
|
26 | * @returns A {Boolean} indicating adapter can adapt the server based on the given serverCapabilities.
|
27 | */
|
28 | static canAdapt(serverCapabilities) {
|
29 | return serverCapabilities.documentSymbolProvider === true;
|
30 | }
|
31 | /**
|
32 | * Public: Obtain the Outline for document via the {LanguageClientConnection} as identified by the {TextEditor}.
|
33 | *
|
34 | * @param connection A {LanguageClientConnection} to the language server that will be queried for the outline.
|
35 | * @param editor The Atom {TextEditor} containing the text the Outline should represent.
|
36 | * @returns A {Promise} containing the {Outline} of this document.
|
37 | */
|
38 | getOutline(connection, editor) {
|
39 | return __awaiter(this, void 0, void 0, function* () {
|
40 | const results = yield Utils.doWithCancellationToken(connection, this._cancellationTokens, (cancellationToken) => connection.documentSymbol({ textDocument: convert_1.default.editorToTextDocumentIdentifier(editor) }, cancellationToken));
|
41 | if (results === null || results.length === 0) {
|
42 | return {
|
43 | outlineTrees: [],
|
44 | };
|
45 | }
|
46 | if (results[0].selectionRange !== undefined) {
|
47 | // If the server is giving back the newer DocumentSymbol format.
|
48 | return {
|
49 | outlineTrees: OutlineViewAdapter.createHierarchicalOutlineTrees(results),
|
50 | };
|
51 | }
|
52 | else {
|
53 | // If the server is giving back the original SymbolInformation format.
|
54 | return {
|
55 | outlineTrees: OutlineViewAdapter.createOutlineTrees(results),
|
56 | };
|
57 | }
|
58 | });
|
59 | }
|
60 | /**
|
61 | * Public: Create an {Array} of {OutlineTree}s from the Array of {DocumentSymbol} recieved from the language server.
|
62 | * This includes converting all the children nodes in the entire hierarchy.
|
63 | *
|
64 | * @param symbols An {Array} of {DocumentSymbol}s received from the language server that should be converted to an
|
65 | * {Array} of {OutlineTree}.
|
66 | * @returns An {Array} of {OutlineTree} containing the given symbols that the Outline View can display.
|
67 | */
|
68 | static createHierarchicalOutlineTrees(symbols) {
|
69 | // Sort all the incoming symbols
|
70 | symbols.sort((a, b) => {
|
71 | if (a.range.start.line !== b.range.start.line) {
|
72 | return a.range.start.line - b.range.start.line;
|
73 | }
|
74 | if (a.range.start.character !== b.range.start.character) {
|
75 | return a.range.start.character - b.range.start.character;
|
76 | }
|
77 | if (a.range.end.line !== b.range.end.line) {
|
78 | return a.range.end.line - b.range.end.line;
|
79 | }
|
80 | return a.range.end.character - b.range.end.character;
|
81 | });
|
82 | return symbols.map((symbol) => {
|
83 | const tree = OutlineViewAdapter.hierarchicalSymbolToOutline(symbol);
|
84 | if (symbol.children != null) {
|
85 | tree.children = OutlineViewAdapter.createHierarchicalOutlineTrees(symbol.children);
|
86 | }
|
87 | return tree;
|
88 | });
|
89 | }
|
90 | /**
|
91 | * Public: Create an {Array} of {OutlineTree}s from the Array of {SymbolInformation} recieved from the language
|
92 | * server. This includes determining the appropriate child and parent relationships for the hierarchy.
|
93 | *
|
94 | * @param symbols An {Array} of {SymbolInformation}s received from the language server that should be converted to an
|
95 | * {OutlineTree}.
|
96 | * @returns An {OutlineTree} containing the given symbols that the Outline View can display.
|
97 | */
|
98 | static createOutlineTrees(symbols) {
|
99 | symbols.sort((a, b) => {
|
100 | if (a.location.range.start.line === b.location.range.start.line) {
|
101 | return a.location.range.start.character - b.location.range.start.character;
|
102 | }
|
103 | else {
|
104 | return a.location.range.start.line - b.location.range.start.line;
|
105 | }
|
106 | });
|
107 | // Temporarily keep containerName through the conversion process
|
108 | // Also filter out symbols without a name - it's part of the spec but some don't include it
|
109 | const allItems = symbols
|
110 | .filter((symbol) => symbol.name)
|
111 | .map((symbol) => ({
|
112 | containerName: symbol.containerName,
|
113 | outline: OutlineViewAdapter.symbolToOutline(symbol),
|
114 | }));
|
115 | // Create a map of containers by name with all items that have that name
|
116 | const containers = allItems.reduce((map, item) => {
|
117 | const name = item.outline.representativeName;
|
118 | if (name != null) {
|
119 | const container = map.get(name);
|
120 | if (container == null) {
|
121 | map.set(name, [item.outline]);
|
122 | }
|
123 | else {
|
124 | container.push(item.outline);
|
125 | }
|
126 | }
|
127 | return map;
|
128 | }, new Map());
|
129 | const roots = [];
|
130 | // Put each item within its parent and extract out the roots
|
131 | for (const item of allItems) {
|
132 | const containerName = item.containerName;
|
133 | const child = item.outline;
|
134 | if (containerName == null || containerName === "") {
|
135 | roots.push(item.outline);
|
136 | }
|
137 | else {
|
138 | const possibleParents = containers.get(containerName);
|
139 | let closestParent = OutlineViewAdapter._getClosestParent(possibleParents, child);
|
140 | if (closestParent == null) {
|
141 | closestParent = {
|
142 | plainText: containerName,
|
143 | representativeName: containerName,
|
144 | startPosition: new atom_1.Point(0, 0),
|
145 | children: [child],
|
146 | };
|
147 | roots.push(closestParent);
|
148 | if (possibleParents == null) {
|
149 | containers.set(containerName, [closestParent]);
|
150 | }
|
151 | else {
|
152 | possibleParents.push(closestParent);
|
153 | }
|
154 | }
|
155 | else {
|
156 | closestParent.children.push(child);
|
157 | }
|
158 | }
|
159 | }
|
160 | return roots;
|
161 | }
|
162 | static _getClosestParent(candidates, child) {
|
163 | if (candidates == null || candidates.length === 0) {
|
164 | return null;
|
165 | }
|
166 | let parent;
|
167 | for (const candidate of candidates) {
|
168 | if (candidate !== child &&
|
169 | candidate.startPosition.isLessThanOrEqual(child.startPosition) &&
|
170 | (candidate.endPosition === undefined ||
|
171 | (child.endPosition && candidate.endPosition.isGreaterThanOrEqual(child.endPosition)))) {
|
172 | if (parent === undefined ||
|
173 | parent.startPosition.isLessThanOrEqual(candidate.startPosition) ||
|
174 | (parent.endPosition != null &&
|
175 | candidate.endPosition &&
|
176 | parent.endPosition.isGreaterThanOrEqual(candidate.endPosition))) {
|
177 | parent = candidate;
|
178 | }
|
179 | }
|
180 | }
|
181 | return parent || null;
|
182 | }
|
183 | /**
|
184 | * Public: Convert an individual {DocumentSymbol} from the language server to an {OutlineTree} for use by the Outline
|
185 | * View. It does NOT recursively process the given symbol's children (if any).
|
186 | *
|
187 | * @param symbol The {DocumentSymbol} to convert to an {OutlineTree}.
|
188 | * @returns The {OutlineTree} corresponding to the given {DocumentSymbol}.
|
189 | */
|
190 | static hierarchicalSymbolToOutline(symbol) {
|
191 | const icon = OutlineViewAdapter.symbolKindToEntityKind(symbol.kind);
|
192 | return {
|
193 | tokenizedText: [
|
194 | {
|
195 | kind: OutlineViewAdapter.symbolKindToTokenKind(symbol.kind),
|
196 | value: symbol.name,
|
197 | },
|
198 | ],
|
199 | icon: icon != null ? icon : undefined,
|
200 | representativeName: symbol.name,
|
201 | startPosition: convert_1.default.positionToPoint(symbol.selectionRange.start),
|
202 | endPosition: convert_1.default.positionToPoint(symbol.selectionRange.end),
|
203 | children: [],
|
204 | };
|
205 | }
|
206 | /**
|
207 | * Public: Convert an individual {SymbolInformation} from the language server to an {OutlineTree} for use by the Outline View.
|
208 | *
|
209 | * @param symbol The {SymbolInformation} to convert to an {OutlineTree}.
|
210 | * @returns The {OutlineTree} equivalent to the given {SymbolInformation}.
|
211 | */
|
212 | static symbolToOutline(symbol) {
|
213 | const icon = OutlineViewAdapter.symbolKindToEntityKind(symbol.kind);
|
214 | return {
|
215 | tokenizedText: [
|
216 | {
|
217 | kind: OutlineViewAdapter.symbolKindToTokenKind(symbol.kind),
|
218 | value: symbol.name,
|
219 | },
|
220 | ],
|
221 | icon: icon != null ? icon : undefined,
|
222 | representativeName: symbol.name,
|
223 | startPosition: convert_1.default.positionToPoint(symbol.location.range.start),
|
224 | endPosition: convert_1.default.positionToPoint(symbol.location.range.end),
|
225 | children: [],
|
226 | };
|
227 | }
|
228 | /**
|
229 | * Public: Convert a symbol kind into an outline entity kind used to determine the styling such as the appropriate
|
230 | * icon in the Outline View.
|
231 | *
|
232 | * @param symbol The numeric symbol kind received from the language server.
|
233 | * @returns A string representing the equivalent OutlineView entity kind.
|
234 | */
|
235 | static symbolKindToEntityKind(symbol) {
|
236 | switch (symbol) {
|
237 | case languageclient_1.SymbolKind.Array:
|
238 | return "type-array";
|
239 | case languageclient_1.SymbolKind.Boolean:
|
240 | return "type-boolean";
|
241 | case languageclient_1.SymbolKind.Class:
|
242 | return "type-class";
|
243 | case languageclient_1.SymbolKind.Constant:
|
244 | return "type-constant";
|
245 | case languageclient_1.SymbolKind.Constructor:
|
246 | return "type-constructor";
|
247 | case languageclient_1.SymbolKind.Enum:
|
248 | return "type-enum";
|
249 | case languageclient_1.SymbolKind.Field:
|
250 | return "type-field";
|
251 | case languageclient_1.SymbolKind.File:
|
252 | return "type-file";
|
253 | case languageclient_1.SymbolKind.Function:
|
254 | return "type-function";
|
255 | case languageclient_1.SymbolKind.Interface:
|
256 | return "type-interface";
|
257 | case languageclient_1.SymbolKind.Method:
|
258 | return "type-method";
|
259 | case languageclient_1.SymbolKind.Module:
|
260 | return "type-module";
|
261 | case languageclient_1.SymbolKind.Namespace:
|
262 | return "type-namespace";
|
263 | case languageclient_1.SymbolKind.Number:
|
264 | return "type-number";
|
265 | case languageclient_1.SymbolKind.Package:
|
266 | return "type-package";
|
267 | case languageclient_1.SymbolKind.Property:
|
268 | return "type-property";
|
269 | case languageclient_1.SymbolKind.String:
|
270 | return "type-string";
|
271 | case languageclient_1.SymbolKind.Variable:
|
272 | return "type-variable";
|
273 | case languageclient_1.SymbolKind.Struct:
|
274 | return "type-class";
|
275 | case languageclient_1.SymbolKind.EnumMember:
|
276 | return "type-constant";
|
277 | default:
|
278 | return null;
|
279 | }
|
280 | }
|
281 | /**
|
282 | * Public: Convert a symbol kind to the appropriate token kind used to syntax highlight the symbol name in the Outline View.
|
283 | *
|
284 | * @param symbol The numeric symbol kind received from the language server.
|
285 | * @returns A string representing the equivalent syntax token kind.
|
286 | */
|
287 | static symbolKindToTokenKind(symbol) {
|
288 | switch (symbol) {
|
289 | case languageclient_1.SymbolKind.Class:
|
290 | return "type";
|
291 | case languageclient_1.SymbolKind.Constructor:
|
292 | return "constructor";
|
293 | case languageclient_1.SymbolKind.Method:
|
294 | case languageclient_1.SymbolKind.Function:
|
295 | return "method";
|
296 | case languageclient_1.SymbolKind.String:
|
297 | return "string";
|
298 | default:
|
299 | return "plain";
|
300 | }
|
301 | }
|
302 | }
|
303 | exports.default = OutlineViewAdapter;
|
304 | //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib3V0bGluZS12aWV3LWFkYXB0ZXIuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWIvYWRhcHRlcnMvb3V0bGluZS12aWV3LWFkYXB0ZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7QUFDQSx3Q0FBZ0M7QUFDaEMsa0NBQWlDO0FBRWpDLHNEQU0wQjtBQUMxQiwrQkFBd0M7QUFFeEMsb0hBQW9IO0FBQ3BILE1BQXFCLGtCQUFrQjtJQUF2QztRQUNVLHdCQUFtQixHQUErRCxJQUFJLE9BQU8sRUFBRSxDQUFBO0lBb1R6RyxDQUFDO0lBbFRDOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxRQUFRLENBQUMsa0JBQXNDO1FBQzNELE9BQU8sa0JBQWtCLENBQUMsc0JBQXNCLEtBQUssSUFBSSxDQUFBO0lBQzNELENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDVSxVQUFVLENBQUMsVUFBb0MsRUFBRSxNQUFrQjs7WUFDOUUsTUFBTSxPQUFPLEdBQUcsTUFBTSxLQUFLLENBQUMsdUJBQXVCLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQyxtQkFBbUIsRUFBRSxDQUFDLGlCQUFpQixFQUFFLEVBQUUsQ0FDOUcsVUFBVSxDQUFDLGNBQWMsQ0FBQyxFQUFFLFlBQVksRUFBRSxpQkFBTyxDQUFDLDhCQUE4QixDQUFDLE1BQU0sQ0FBQyxFQUFFLEVBQUUsaUJBQWlCLENBQUMsQ0FDL0csQ0FBQTtZQUVELElBQUksT0FBTyxLQUFLLElBQUksSUFBSSxPQUFPLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDNUMsT0FBTztvQkFDTCxZQUFZLEVBQUUsRUFBRTtpQkFDakIsQ0FBQTthQUNGO1lBRUQsSUFBSyxPQUFPLENBQUMsQ0FBQyxDQUFvQixDQUFDLGNBQWMsS0FBSyxTQUFTLEVBQUU7Z0JBQy9ELGdFQUFnRTtnQkFDaEUsT0FBTztvQkFDTCxZQUFZLEVBQUUsa0JBQWtCLENBQUMsOEJBQThCLENBQUMsT0FBMkIsQ0FBQztp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TSxDQUFBO1lBQ2YsS0FBSywyQkFBVSxDQUFDLFdBQVc7Z0JBQ3pCLE9BQU8sYUFBYSxDQUFBO1lBQ3RCLEtBQUssMkJBQVUsQ0FBQyxNQUFNLENBQUM7WUFDdkIsS0FBSywyQkFBVSxDQUFDLFFBQVE7Z0JBQ3RCLE9BQU8sUUFBUSxDQUFBO1lBQ2pCLEtBQUssMkJBQVUsQ0FBQyxNQUFNO2dCQUNwQixPQUFPLFFBQVEsQ0FBQTtZQUNqQjtnQkFDRSxPQUFPLE9BQU8sQ0FBQTtTQUNqQjtJQUNILENBQUM7Q0FDRjtBQXJURCxxQ0FxVEMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgdHlwZSAqIGFzIGF0b21JZGUgZnJvbSBcImF0b20taWRlLWJhc2VcIlxuaW1wb3J0IENvbnZlcnQgZnJvbSBcIi4uL2NvbnZlcnRcIlxuaW1wb3J0ICogYXMgVXRpbHMgZnJvbSBcIi4uL3V0aWxzXCJcbmltcG9ydCB7IENhbmNlbGxhdGlvblRva2VuU291cmNlIH0gZnJvbSBcInZzY29kZS1qc29ucnBjXCJcbmltcG9ydCB7XG4gIExhbmd1YWdlQ2xpZW50Q29ubmVjdGlvbixcbiAgU3ltYm9sS2luZCxcbiAgU2VydmVyQ2FwYWJpbGl0aWVzLFxuICBTeW1ib2xJbmZvcm1hdGlvbixcbiAgRG9jdW1lbnRTeW1ib2wsXG59IGZyb20gXCIuLi9sYW5ndWFnZWNsaWVudFwiXG5pbXBvcnQgeyBQb2ludCwgVGV4dEVkaXRvciB9IGZyb20gXCJhdG9tXCJcblxuLyoqIFB1YmxpYzogQWRhcHRzIHRoZSBkb2N1bWVudFN5bWJvbFByb3ZpZGVyIG9mIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgdG8gdGhlIE91dGxpbmUgVmlldyBzdXBwbGllZCBieSBBdG9tIElERSBVSS4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIE91dGxpbmVWaWV3QWRhcHRlciB7XG4gIHByaXZhdGUgX2NhbmNlbGxhdGlvblRva2VuczogV2Vha01hcDxMYW5ndWFnZUNsaWVudENvbm5lY3Rpb24sIENhbmNlbGxhdGlvblRva2VuU291cmNlPiA9IG5ldyBXZWFrTWFwKClcblxuICAvKipcbiAgICogUHVibGljOiBEZXRlcm1pbmUgd2hldGhlciB0aGlzIGFkYXB0ZXIgY2FuIGJlIHVzZWQgdG8gYWRhcHQgYSBsYW5ndWFnZSBzZXJ2ZXIgYmFzZWQgb24gdGhlIHNlcnZlckNhcGFiaWxpdGllc1xuICAgKiBtYXRyaXggY29udGFpbmluZyBhIGRvY3VtZW50U3ltYm9sUHJvdmlkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBzZXJ2ZXJDYXBhYmlsaXRpZXMgVGhlIHtTZXJ2ZXJDYXBhYmlsaXRpZXN9IG9mIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgdG8gY29uc2lkZXIuXG4gICAqIEByZXR1cm5zIEEge0Jvb2xlYW59IGluZGljYXRpbmcgYWRhcHRlciBjYW4gYWRhcHQgdGhlIHNlcnZlciBiYXNlZCBvbiB0aGUgZ2l2ZW4gc2VydmVyQ2FwYWJpbGl0aWVzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjYW5BZGFwdChzZXJ2ZXJDYXBhYmlsaXRpZXM6IFNlcnZlckNhcGFiaWxpdGllcyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzZXJ2ZXJDYXBhYmlsaXRpZXMuZG9jdW1lbnRTeW1ib2xQcm92aWRlciA9PT0gdHJ1ZVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogT2J0YWluIHRoZSBPdXRsaW5lIGZvciBkb2N1bWVudCB2aWEgdGhlIHtMYW5ndWFnZUNsaWVudENvbm5lY3Rpb259IGFzIGlkZW50aWZpZWQgYnkgdGhlIHtUZXh0RWRpdG9yfS5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5lY3Rpb24gQSB7TGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9ufSB0byB0aGUgbGFuZ3VhZ2Ugc2VydmVyIHRoYXQgd2lsbCBiZSBxdWVyaWVkIGZvciB0aGUgb3V0bGluZS5cbiAgICogQHBhcmFtIGVkaXRvciBUaGUgQXRvbSB7VGV4dEVkaXRvcn0gY29udGFpbmluZyB0aGUgdGV4dCB0aGUgT3V0bGluZSBzaG91bGQgcmVwcmVzZW50LlxuICAgKiBAcmV0dXJucyBBIHtQcm9taXNlfSBjb250YWluaW5nIHRoZSB7T3V0bGluZX0gb2YgdGhpcyBkb2N1bWVudC5cbiAgICovXG4gIHB1YmxpYyBhc3luYyBnZXRPdXRsaW5lKGNvbm5lY3Rpb246IExhbmd1YWdlQ2xpZW50Q29ubmVjdGlvbiwgZWRpdG9yOiBUZXh0RWRpdG9yKTogUHJvbWlzZTxhdG9tSWRlLk91dGxpbmUgfCBudWxsPiB7XG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IFV0aWxzLmRvV2l0aENhbmNlbGxhdGlvblRva2VuKGNvbm5lY3Rpb24sIHRoaXMuX2NhbmNlbGxhdGlvblRva2VucywgKGNhbmNlbGxhdGlvblRva2VuKSA9PlxuICAgICAgY29ubmVjdGlvbi5kb2N1bWVudFN5bWJvbCh7IHRleHREb2N1bWVudDogQ29udmVydC5lZGl0b3JUb1RleHREb2N1bWVudElkZW50aWZpZXIoZWRpdG9yKSB9LCBjYW5jZWxsYXRpb25Ub2tlbilcbiAgICApXG5cbiAgICBpZiAocmVzdWx0cyA9PT0gbnVsbCB8fCByZXN1bHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgb3V0bGluZVRyZWVzOiBbXSxcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoKHJlc3VsdHNbMF0gYXMgRG9jdW1lbnRTeW1ib2wpLnNlbGVjdGlvblJhbmdlICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIC8vIElmIHRoZSBzZXJ2ZXIgaXMgZ2l2aW5nIGJhY2sgdGhlIG5ld2VyIERvY3VtZW50U3ltYm9sIGZvcm1hdC5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG91dGxpbmVUcmVlczogT3V0bGluZVZpZXdBZGFwdGVyLmNyZWF0ZUhpZXJhcmNoaWNhbE91dGxpbmVUcmVlcyhyZXN1bHRzIGFzIERvY3VtZW50U3ltYm9sW10pLFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBJZiB0aGUgc2VydmVyIGlzIGdpdmluZyBiYWNrIHRoZSBvcmlnaW5hbCBTeW1ib2xJbmZvcm1hdGlvbiBmb3JtYXQuXG4gICAgICByZXR1cm4ge1xuICAgICAgICBvdXRsaW5lVHJlZXM6IE91dGxpbmVWaWV3QWRhcHRlci5jcmVhdGVPdXRsaW5lVHJlZXMocmVzdWx0cyBhcyBTeW1ib2xJbmZvcm1hdGlvbltdKSxcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBDcmVhdGUgYW4ge0FycmF5fSBvZiB7T3V0bGluZVRyZWV9cyBmcm9tIHRoZSBBcnJheSBvZiB7RG9jdW1lbnRTeW1ib2x9IHJlY2lldmVkIGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlci5cbiAgICogVGhpcyBpbmNsdWRlcyBjb252ZXJ0aW5nIGFsbCB0aGUgY2hpbGRyZW4gbm9kZXMgaW4gdGhlIGVudGlyZSBoaWVyYXJjaHkuXG4gICAqXG4gICAqIEBwYXJhbSBzeW1ib2xzIEFuIHtBcnJheX0gb2Yge0RvY3VtZW50U3ltYm9sfXMgcmVjZWl2ZWQgZnJvbSB0aGUgbGFuZ3VhZ2Ugc2VydmVyIHRoYXQgc2hvdWxkIGJlIGNvbnZlcnRlZCB0byBhblxuICAgKiAgIHtBcnJheX0gb2Yge091dGxpbmVUcmVlfS5cbiAgICogQHJldHVybnMgQW4ge0FycmF5fSBvZiB7T3V0bGluZVRyZWV9IGNvbnRhaW5pbmcgdGhlIGdpdmVuIHN5bWJvbHMgdGhhdCB0aGUgT3V0bGluZSBWaWV3IGNhbiBkaXNwbGF5LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjcmVhdGVIaWVyYXJjaGljYWxPdXRsaW5lVHJlZXMoc3ltYm9sczogRG9jdW1lbnRTeW1ib2xbXSk6IGF0b21JZGUuT3V0bGluZVRyZWVbXSB7XG4gICAgLy8gU29ydCBhbGwgdGhlIGluY29taW5nIHN5bWJvbHNcbiAgICBzeW1ib2xzLnNvcnQoKGEsIGIpID0+IHtcbiAgICAgIGlmIChhLnJhbmdlLnN0YXJ0LmxpbmUgIT09IGIucmFuZ2Uuc3RhcnQubGluZSkge1xuICAgICAgICByZXR1cm4gYS5yYW5nZS5zdGFydC5saW5lIC0gYi5yYW5nZS5zdGFydC5saW5lXG4gICAgICB9XG5cbiAgICAgIGlmIChhLnJhbmdlLnN0YXJ0LmNoYXJhY3RlciAhPT0gYi5yYW5nZS5zdGFydC5jaGFyYWN0ZXIpIHtcbiAgICAgICAgcmV0dXJuIGEucmFuZ2Uuc3RhcnQuY2hhcmFjdGVyIC0gYi5yYW5nZS5zdGFydC5jaGFyYWN0ZXJcbiAgICAgIH1cblxuICAgICAgaWYgKGEucmFuZ2UuZW5kLmxpbmUgIT09IGIucmFuZ2UuZW5kLmxpbmUpIHtcbiAgICAgICAgcmV0dXJuIGEucmFuZ2UuZW5kLmxpbmUgLSBiLnJhbmdlLmVuZC5saW5lXG4gICAgICB9XG5cbiAgICAgIHJldHVybiBhLnJhbmdlLmVuZC5jaGFyYWN0ZXIgLSBiLnJhbmdlLmVuZC5jaGFyYWN0ZXJcbiAgICB9KVxuXG4gICAgcmV0dXJuIHN5bWJvbHMubWFwKChzeW1ib2wpID0+IHtcbiAgICAgIGNvbnN0IHRyZWUgPSBPdXRsaW5lVmlld0FkYXB0ZXIuaGllcmFyY2hpY2FsU3ltYm9sVG9PdXRsaW5lKHN5bWJvbClcblxuICAgICAgaWYgKHN5bWJvbC5jaGlsZHJlbiAhPSBudWxsKSB7XG4gICAgICAgIHRyZWUuY2hpbGRyZW4gPSBPdXRsaW5lVmlld0FkYXB0ZXIuY3JlYXRlSGllcmFyY2hpY2FsT3V0bGluZVRyZWVzKHN5bWJvbC5jaGlsZHJlbilcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIHRyZWVcbiAgICB9KVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogQ3JlYXRlIGFuIHtBcnJheX0gb2Yge091dGxpbmVUcmVlfXMgZnJvbSB0aGUgQXJyYXkgb2Yge1N5bWJvbEluZm9ybWF0aW9ufSByZWNpZXZlZCBmcm9tIHRoZSBsYW5ndWFnZVxuICAgKiBzZXJ2ZXIuIFRoaXMgaW5jbHVkZXMgZGV0ZXJtaW5pbmcgdGhlIGFwcHJvcHJpYXRlIGNoaWxkIGFuZCBwYXJlbnQgcmVsYXRpb25zaGlwcyBmb3IgdGhlIGhpZXJhcmNoeS5cbiAgICpcbiAgICogQHBhcmFtIHN5bWJvbHMgQW4ge0FycmF5fSBvZiB7U3ltYm9sSW5mb3JtYXRpb259cyByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgdGhhdCBzaG91bGQgYmUgY29udmVydGVkIHRvIGFuXG4gICAqICAge091dGxpbmVUcmVlfS5cbiAgICogQHJldHVybnMgQW4ge091dGxpbmVUcmVlfSBjb250YWluaW5nIHRoZSBnaXZlbiBzeW1ib2xzIHRoYXQgdGhlIE91dGxpbmUgVmlldyBjYW4gZGlzcGxheS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgY3JlYXRlT3V0bGluZVRyZWVzKHN5bWJvbHM6IFN5bWJvbEluZm9ybWF0aW9uW10pOiBhdG9tSWRlLk91dGxpbmVUcmVlW10ge1xuICAgIHN5bWJvbHMuc29ydCgoYSwgYikgPT4ge1xuICAgICAgaWYgKGEubG9jYXRpb24ucmFuZ2Uuc3RhcnQubGluZSA9PT0gYi5sb2NhdGlvbi5yYW5nZS5zdGFydC5saW5lKSB7XG4gICAgICAgIHJldHVybiBhLmxvY2F0aW9uLnJhbmdlLnN0YXJ0LmNoYXJhY3RlciAtIGIubG9jYXRpb24ucmFuZ2Uuc3RhcnQuY2hhcmFjdGVyXG4gICAgICB9IGVsc2Uge1xuICAgICAgICByZXR1cm4gYS5sb2NhdGlvbi5yYW5nZS5zdGFydC5saW5lIC0gYi5sb2NhdGlvbi5yYW5nZS5zdGFydC5saW5lXG4gICAgICB9XG4gICAgfSlcblxuICAgIC8vIFRlbXBvcmFyaWx5IGtlZXAgY29udGFpbmVyTmFtZSB0aHJvdWdoIHRoZSBjb252ZXJzaW9uIHByb2Nlc3NcbiAgICAvLyBBbHNvIGZpbHRlciBvdXQgc3ltYm9scyB3aXRob3V0IGEgbmFtZSAtIGl0J3MgcGFydCBvZiB0aGUgc3BlYyBidXQgc29tZSBkb24ndCBpbmNsdWRlIGl0XG4gICAgY29uc3QgYWxsSXRlbXMgPSBzeW1ib2xzXG4gICAgICAuZmlsdGVyKChzeW1ib2wpID0+IHN5bWJvbC5uYW1lKVxuICAgICAgLm1hcCgoc3ltYm9sKSA9PiAoe1xuICAgICAgICBjb250YWluZXJOYW1lOiBzeW1ib2wuY29udGFpbmVyTmFtZSxcbiAgICAgICAgb3V0bGluZTogT3V0bGluZVZpZXdBZGFwdGVyLnN5bWJvbFRvT3V0bGluZShzeW1ib2wpLFxuICAgICAgfSkpXG5cbiAgICAvLyBDcmVhdGUgYSBtYXAgb2YgY29udGFpbmVycyBieSBuYW1lIHdpdGggYWxsIGl0ZW1zIHRoYXQgaGF2ZSB0aGF0IG5hbWVcbiAgICBjb25zdCBjb250YWluZXJzID0gYWxsSXRlbXMucmVkdWNlKChtYXAsIGl0ZW0pID0+IHtcbiAgICAgIGNvbnN0IG5hbWUgPSBpdGVtLm91dGxpbmUucmVwcmVzZW50YXRpdmVOYW1lXG4gICAgICBpZiAobmFtZSAhPSBudWxsKSB7XG4gICAgICAgIGNvbnN0IGNvbnRhaW5lciA9IG1hcC5nZXQobmFtZSlcbiAgICAgICAgaWYgKGNvbnRhaW5lciA9PSBudWxsKSB7XG4gICAgICAgICAgbWFwLnNldChuYW1lLCBbaXRlbS5vdXRsaW5lXSlcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBjb250YWluZXIucHVzaChpdGVtLm91dGxpbmUpXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICAgIHJldHVybiBtYXBcbiAgICB9LCBuZXcgTWFwKCkpXG5cbiAgICBjb25zdCByb290czogYXRvbUlkZS5PdXRsaW5lVHJlZVtdID0gW11cblxuICAgIC8vIFB1dCBlYWNoIGl0ZW0gd2l0aGluIGl0cyBwYXJlbnQgYW5kIGV4dHJhY3Qgb3V0IHRoZSByb290c1xuICAgIGZvciAoY29uc3QgaXRlbSBvZiBhbGxJdGVtcykge1xuICAgICAgY29uc3QgY29udGFpbmVyTmFtZSA9IGl0ZW0uY29udGFpbmVyTmFtZVxuICAgICAgY29uc3QgY2hpbGQgPSBpdGVtLm91dGxpbmVcbiAgICAgIGlmIChjb250YWluZXJOYW1lID09IG51bGwgfHwgY29udGFpbmVyTmFtZSA9PT0gXCJcIikge1xuICAgICAgICByb290cy5wdXNoKGl0ZW0ub3V0bGluZSlcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIGNvbnN0IHBvc3NpYmxlUGFyZW50cyA9IGNvbnRhaW5lcnMuZ2V0KGNvbnRhaW5lck5hbWUpXG4gICAgICAgIGxldCBjbG9zZXN0UGFyZW50ID0gT3V0bGluZVZpZXdBZGFwdGVyLl9nZXRDbG9zZXN0UGFyZW50KHBvc3NpYmxlUGFyZW50cywgY2hpbGQpXG4gICAgICAgIGlmIChjbG9zZXN0UGFyZW50ID09IG51bGwpIHtcbiAgICAgICAgICBjbG9zZXN0UGFyZW50ID0ge1xuICAgICAgICAgICAgcGxhaW5UZXh0OiBjb250YWluZXJOYW1lLFxuICAgICAgICAgICAgcmVwcmVzZW50YXRpdmVOYW1lOiBjb250YWluZXJOYW1lLFxuICAgICAgICAgICAgc3RhcnRQb3NpdGlvbjogbmV3IFBvaW50KDAsIDApLFxuICAgICAgICAgICAgY2hpbGRyZW46IFtjaGlsZF0sXG4gICAgICAgICAgfVxuICAgICAgICAgIHJvb3RzLnB1c2goY2xvc2VzdFBhcmVudClcbiAgICAgICAgICBpZiAocG9zc2libGVQYXJlbnRzID09IG51bGwpIHtcbiAgICAgICAgICAgIGNvbnRhaW5lcnMuc2V0KGNvbnRhaW5lck5hbWUsIFtjbG9zZXN0UGFyZW50XSlcbiAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgcG9zc2libGVQYXJlbnRzLnB1c2goY2xvc2VzdFBhcmVudClcbiAgICAgICAgICB9XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY2xvc2VzdFBhcmVudC5jaGlsZHJlbi5wdXNoKGNoaWxkKVxuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHJvb3RzXG4gIH1cblxuICBwcml2YXRlIHN0YXRpYyBfZ2V0Q2xvc2VzdFBhcmVudChcbiAgICBjYW5kaWRhdGVzOiBhdG9tSWRlLk91dGxpbmVUcmVlW10gfCBudWxsLFxuICAgIGNoaWxkOiBhdG9tSWRlLk91dGxpbmVUcmVlXG4gICk6IGF0b21JZGUuT3V0bGluZVRyZWUgfCBudWxsIHtcbiAgICBpZiAoY2FuZGlkYXRlcyA9PSBudWxsIHx8IGNhbmRpZGF0ZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cblxuICAgIGxldCBwYXJlbnQ6IGF0b21JZGUuT3V0bGluZVRyZWUgfCB1bmRlZmluZWRcbiAgICBmb3IgKGNvbnN0IGNhbmRpZGF0ZSBvZiBjYW5kaWRhdGVzKSB7XG4gICAgICBpZiAoXG4gICAgICAgIGNhbmRpZGF0ZSAhPT0gY2hpbGQgJiZcbiAgICAgICAgY2FuZGlkYXRlLnN0YXJ0UG9zaXRpb24uaXNMZXNzVGhhbk9yRXF1YWwoY2hpbGQuc3RhcnRQb3NpdGlvbikgJiZcbiAgICAgICAgKGNhbmRpZGF0ZS5lbmRQb3NpdGlvbiA9PT0gdW5kZWZpbmVkIHx8XG4gICAgICAgICAgKGNoaWxkLmVuZFBvc2l0aW9uICYmIGNhbmRpZGF0ZS5lbmRQb3NpdGlvbi5pc0dyZWF0ZXJUaGFuT3JFcXVhbChjaGlsZC5lbmRQb3NpdGlvbikpKVxuICAgICAgKSB7XG4gICAgICAgIGlmIChcbiAgICAgICAgICBwYXJlbnQgPT09IHVuZGVmaW5lZCB8fFxuICAgICAgICAgIHBhcmVudC5zdGFydFBvc2l0aW9uLmlzTGVzc1RoYW5PckVxdWFsKGNhbmRpZGF0ZS5zdGFydFBvc2l0aW9uKSB8fFxuICAgICAgICAgIChwYXJlbnQuZW5kUG9zaXRpb24gIT0gbnVsbCAmJlxuICAgICAgICAgICAgY2FuZGlkYXRlLmVuZFBvc2l0aW9uICYmXG4gICAgICAgICAgICBwYXJlbnQuZW5kUG9zaXRpb24uaXNHcmVhdGVyVGhhbk9yRXF1YWwoY2FuZGlkYXRlLmVuZFBvc2l0aW9uKSlcbiAgICAgICAgKSB7XG4gICAgICAgICAgcGFyZW50ID0gY2FuZGlkYXRlXG4gICAgICAgIH1cbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4gcGFyZW50IHx8IG51bGxcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENvbnZlcnQgYW4gaW5kaXZpZHVhbCB7RG9jdW1lbnRTeW1ib2x9IGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlciB0byBhbiB7T3V0bGluZVRyZWV9IGZvciB1c2UgYnkgdGhlIE91dGxpbmVcbiAgICogVmlldy4gSXQgZG9lcyBOT1QgcmVjdXJzaXZlbHkgcHJvY2VzcyB0aGUgZ2l2ZW4gc3ltYm9sJ3MgY2hpbGRyZW4gKGlmIGFueSkuXG4gICAqXG4gICAqIEBwYXJhbSBzeW1ib2wgVGhlIHtEb2N1bWVudFN5bWJvbH0gdG8gY29udmVydCB0byBhbiB7T3V0bGluZVRyZWV9LlxuICAgKiBAcmV0dXJucyBUaGUge091dGxpbmVUcmVlfSBjb3JyZXNwb25kaW5nIHRvIHRoZSBnaXZlbiB7RG9jdW1lbnRTeW1ib2x9LlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBoaWVyYXJjaGljYWxTeW1ib2xUb091dGxpbmUoc3ltYm9sOiBEb2N1bWVudFN5bWJvbCk6IGF0b21JZGUuT3V0bGluZVRyZWUge1xuICAgIGNvbnN0IGljb24gPSBPdXRsaW5lVmlld0FkYXB0ZXIuc3ltYm9sS2luZFRvRW50aXR5S2luZChzeW1ib2wua2luZClcblxuICAgIHJldHVybiB7XG4gICAgICB0b2tlbml6ZWRUZXh0OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBraW5kOiBPdXRsaW5lVmlld0FkYXB0ZXIuc3ltYm9sS2luZFRvVG9rZW5LaW5kKHN5bWJvbC5raW5kKSxcbiAgICAgICAgICB2YWx1ZTogc3ltYm9sLm5hbWUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgaWNvbjogaWNvbiAhPSBudWxsID8gaWNvbiA6IHVuZGVmaW5lZCxcbiAgICAgIHJlcHJlc2VudGF0aXZlTmFtZTogc3ltYm9sLm5hbWUsXG4gICAgICBzdGFydFBvc2l0aW9uOiBDb252ZXJ0LnBvc2l0aW9uVG9Qb2ludChzeW1ib2wuc2VsZWN0aW9uUmFuZ2Uuc3RhcnQpLFxuICAgICAgZW5kUG9zaXRpb246IENvbnZlcnQucG9zaXRpb25Ub1BvaW50KHN5bWJvbC5zZWxlY3Rpb25SYW5nZS5lbmQpLFxuICAgICAgY2hpbGRyZW46IFtdLFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENvbnZlcnQgYW4gaW5kaXZpZHVhbCB7U3ltYm9sSW5mb3JtYXRpb259IGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlciB0byBhbiB7T3V0bGluZVRyZWV9IGZvciB1c2UgYnkgdGhlIE91dGxpbmUgVmlldy5cbiAgICpcbiAgICogQHBhcmFtIHN5bWJvbCBUaGUge1N5bWJvbEluZm9ybWF0aW9ufSB0byBjb252ZXJ0IHRvIGFuIHtPdXRsaW5lVHJlZX0uXG4gICAqIEByZXR1cm5zIFRoZSB7T3V0bGluZVRyZWV9IGVxdWl2YWxlbnQgdG8gdGhlIGdpdmVuIHtTeW1ib2xJbmZvcm1hdGlvbn0uXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIHN5bWJvbFRvT3V0bGluZShzeW1ib2w6IFN5bWJvbEluZm9ybWF0aW9uKTogYXRvbUlkZS5PdXRsaW5lVHJlZSB7XG4gICAgY29uc3QgaWNvbiA9IE91dGxpbmVWaWV3QWRhcHRlci5zeW1ib2xLaW5kVG9FbnRpdHlLaW5kKHN5bWJvbC5raW5kKVxuICAgIHJldHVybiB7XG4gICAgICB0b2tlbml6ZWRUZXh0OiBbXG4gICAgICAgIHtcbiAgICAgICAgICBraW5kOiBPdXRsaW5lVmlld0FkYXB0ZXIuc3ltYm9sS2luZFRvVG9rZW5LaW5kKHN5bWJvbC5raW5kKSxcbiAgICAgICAgICB2YWx1ZTogc3ltYm9sLm5hbWUsXG4gICAgICAgIH0sXG4gICAgICBdLFxuICAgICAgaWNvbjogaWNvbiAhPSBudWxsID8gaWNvbiA6IHVuZGVmaW5lZCxcbiAgICAgIHJlcHJlc2VudGF0aXZlTmFtZTogc3ltYm9sLm5hbWUsXG4gICAgICBzdGFydFBvc2l0aW9uOiBDb252ZXJ0LnBvc2l0aW9uVG9Qb2ludChzeW1ib2wubG9jYXRpb24ucmFuZ2Uuc3RhcnQpLFxuICAgICAgZW5kUG9zaXRpb246IENvbnZlcnQucG9zaXRpb25Ub1BvaW50KHN5bWJvbC5sb2NhdGlvbi5yYW5nZS5lbmQpLFxuICAgICAgY2hpbGRyZW46IFtdLFxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENvbnZlcnQgYSBzeW1ib2wga2luZCBpbnRvIGFuIG91dGxpbmUgZW50aXR5IGtpbmQgdXNlZCB0byBkZXRlcm1pbmUgdGhlIHN0eWxpbmcgc3VjaCBhcyB0aGUgYXBwcm9wcmlhdGVcbiAgICogaWNvbiBpbiB0aGUgT3V0bGluZSBWaWV3LlxuICAgKlxuICAgKiBAcGFyYW0gc3ltYm9sIFRoZSBudW1lcmljIHN5bWJvbCBraW5kIHJlY2VpdmVkIGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlci5cbiAgICogQHJldHVybnMgQSBzdHJpbmcgcmVwcmVzZW50aW5nIHRoZSBlcXVpdmFsZW50IE91dGxpbmVWaWV3IGVudGl0eSBraW5kLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBzeW1ib2xLaW5kVG9FbnRpdHlLaW5kKHN5bWJvbDogbnVtYmVyKTogc3RyaW5nIHwgbnVsbCB7XG4gICAgc3dpdGNoIChzeW1ib2wpIHtcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5BcnJheTpcbiAgICAgICAgcmV0dXJuIFwidHlwZS1hcnJheVwiXG4gICAgICBjYXNlIFN5bWJvbEtpbmQuQm9vbGVhbjpcbiAgICAgICAgcmV0dXJuIFwidHlwZS1ib29sZWFuXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5DbGFzczpcbiAgICAgICAgcmV0dXJuIFwidHlwZS1jbGFzc1wiXG4gICAgICBjYXNlIFN5bWJvbEtpbmQuQ29uc3RhbnQ6XG4gICAgICAgIHJldHVybiBcInR5cGUtY29uc3RhbnRcIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLkNvbnN0cnVjdG9yOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWNvbnN0cnVjdG9yXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5FbnVtOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWVudW1cIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLkZpZWxkOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWZpZWxkXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5GaWxlOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWZpbGVcIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLkZ1bmN0aW9uOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWZ1bmN0aW9uXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5JbnRlcmZhY2U6XG4gICAgICAgIHJldHVybiBcInR5cGUtaW50ZXJmYWNlXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5NZXRob2Q6XG4gICAgICAgIHJldHVybiBcInR5cGUtbWV0aG9kXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5Nb2R1bGU6XG4gICAgICAgIHJldHVybiBcInR5cGUtbW9kdWxlXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5OYW1lc3BhY2U6XG4gICAgICAgIHJldHVybiBcInR5cGUtbmFtZXNwYWNlXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5OdW1iZXI6XG4gICAgICAgIHJldHVybiBcInR5cGUtbnVtYmVyXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5QYWNrYWdlOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLXBhY2thZ2VcIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLlByb3BlcnR5OlxuICAgICAgICByZXR1cm4gXCJ0eXBlLXByb3BlcnR5XCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5TdHJpbmc6XG4gICAgICAgIHJldHVybiBcInR5cGUtc3RyaW5nXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5WYXJpYWJsZTpcbiAgICAgICAgcmV0dXJuIFwidHlwZS12YXJpYWJsZVwiXG4gICAgICBjYXNlIFN5bWJvbEtpbmQuU3RydWN0OlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWNsYXNzXCJcbiAgICAgIGNhc2UgU3ltYm9sS2luZC5FbnVtTWVtYmVyOlxuICAgICAgICByZXR1cm4gXCJ0eXBlLWNvbnN0YW50XCJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogQ29udmVydCBhIHN5bWJvbCBraW5kIHRvIHRoZSBhcHByb3ByaWF0ZSB0b2tlbiBraW5kIHVzZWQgdG8gc3ludGF4IGhpZ2hsaWdodCB0aGUgc3ltYm9sIG5hbWUgaW4gdGhlIE91dGxpbmUgVmlldy5cbiAgICpcbiAgICogQHBhcmFtIHN5bWJvbCBUaGUgbnVtZXJpYyBzeW1ib2wga2luZCByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gICAqIEByZXR1cm5zIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgZXF1aXZhbGVudCBzeW50YXggdG9rZW4ga2luZC5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgc3ltYm9sS2luZFRvVG9rZW5LaW5kKHN5bWJvbDogbnVtYmVyKTogYXRvbUlkZS5Ub2tlbktpbmQge1xuICAgIHN3aXRjaCAoc3ltYm9sKSB7XG4gICAgICBjYXNlIFN5bWJvbEtpbmQuQ2xhc3M6XG4gICAgICAgIHJldHVybiBcInR5cGVcIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLkNvbnN0cnVjdG9yOlxuICAgICAgICByZXR1cm4gXCJjb25zdHJ1Y3RvclwiXG4gICAgICBjYXNlIFN5bWJvbEtpbmQuTWV0aG9kOlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLkZ1bmN0aW9uOlxuICAgICAgICByZXR1cm4gXCJtZXRob2RcIlxuICAgICAgY2FzZSBTeW1ib2xLaW5kLlN0cmluZzpcbiAgICAgICAgcmV0dXJuIFwic3RyaW5nXCJcbiAgICAgIGRlZmF1bHQ6XG4gICAgICAgIHJldHVybiBcInBsYWluXCJcbiAgICB9XG4gIH1cbn1cbiJdfQ== |
\ | No newline at end of file |