UNPKG

16.1 kBJavaScriptView Raw
1"use strict";
2var __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};
11Object.defineProperty(exports, "__esModule", { value: true });
12const convert_1 = require("../convert");
13const Utils = require("../utils");
14const languageclient_1 = require("../languageclient");
15const atom_1 = require("atom");
16/**
17 * Public: Adapts the language server definition provider to the Atom IDE UI Definitions package for 'Go To Definition'
18 * functionality.
19 */
20class DefinitionAdapter {
21 /**
22 * Public: Determine whether this adapter can be used to adapt a language server based on the serverCapabilities
23 * matrix containing a definitionProvider.
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.definitionProvider === true;
30 }
31 /**
32 * Public: Get the definitions for a symbol at a given {Point} within a {TextEditor} including optionally highlighting
33 * all other references within the document if the langauge server also supports highlighting.
34 *
35 * @param connection A {LanguageClientConnection} to the language server that will provide definitions and highlights.
36 * @param serverCapabilities The {ServerCapabilities} of the language server that will be used.
37 * @param languageName The name of the programming language.
38 * @param editor The Atom {TextEditor} containing the symbol and potential highlights.
39 * @param point The Atom {Point} containing the position of the text that represents the symbol for which the
40 * definition and highlights should be provided.
41 * @returns A {Promise} indicating adapter can adapt the server based on the given serverCapabilities.
42 */
43 getDefinition(connection, serverCapabilities, languageName, editor, point) {
44 return __awaiter(this, void 0, void 0, function* () {
45 const documentPositionParams = convert_1.default.editorToTextDocumentPositionParams(editor, point);
46 const definitionLocations = DefinitionAdapter.normalizeLocations(yield connection.gotoDefinition(documentPositionParams));
47 if (definitionLocations == null || definitionLocations.length === 0) {
48 return null;
49 }
50 let queryRange;
51 if (serverCapabilities.documentHighlightProvider) {
52 const highlights = yield connection.documentHighlight(documentPositionParams);
53 if (highlights != null && highlights.length > 0) {
54 queryRange = highlights.map((h) => convert_1.default.lsRangeToAtomRange(h.range));
55 }
56 }
57 return {
58 queryRange: queryRange || [Utils.getWordAtPosition(editor, point)],
59 definitions: DefinitionAdapter.convertLocationsToDefinitions(definitionLocations, languageName),
60 };
61 });
62 }
63 /**
64 * Public: Normalize the locations so a single {Location} becomes an {Array} of just one. The language server protocol
65 * return either as the protocol evolved between v1 and v2.
66 *
67 * @param locationResult Either a single {Location} object or an {Array} of {Locations}.
68 * @returns An {Array} of {Location}s or {null} if the locationResult was null.
69 */
70 static normalizeLocations(locationResult) {
71 if (locationResult == null) {
72 // TODO use ===
73 return null;
74 }
75 // TODO `d.targetRange.start` never becomes `null` according to the types
76 if (isLocationLinkArray(locationResult)) {
77 return locationResult.filter((d) => d.targetRange.start != null);
78 }
79 return (Array.isArray(locationResult) ? locationResult : [locationResult]).filter((d) => d.range.start != null);
80 }
81 /**
82 * Public: Convert an {Array} of {Location} objects into an Array of {Definition}s.
83 *
84 * @param locations An {Array} of {Location} objects to be converted.
85 * @param languageName The name of the language these objects are written in.
86 * @returns An {Array} of {Definition}s that represented the converted {Location}s.
87 */
88 static convertLocationsToDefinitions(locations, languageName) {
89 if (isLocationLinkArray(locations)) {
90 return locations.map((d) => ({
91 path: convert_1.default.uriToPath(d.targetUri),
92 position: convert_1.default.positionToPoint(d.targetRange.start),
93 range: atom_1.Range.fromObject(convert_1.default.lsRangeToAtomRange(d.targetRange)),
94 language: languageName,
95 }));
96 }
97 return locations.map((d) => ({
98 path: convert_1.default.uriToPath(d.uri),
99 position: convert_1.default.positionToPoint(d.range.start),
100 range: atom_1.Range.fromObject(convert_1.default.lsRangeToAtomRange(d.range)),
101 language: languageName,
102 }));
103 }
104}
105exports.default = DefinitionAdapter;
106function isLocationLinkArray(value) {
107 return Array.isArray(value) && languageclient_1.LocationLink.is(value[0]);
108}
109//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZGVmaW5pdGlvbi1hZGFwdGVyLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vbGliL2FkYXB0ZXJzL2RlZmluaXRpb24tYWRhcHRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7Ozs7Ozs7OztBQUNBLHdDQUFnQztBQUNoQyxrQ0FBaUM7QUFDakMsc0RBQXdHO0FBQ3hHLCtCQUErQztBQUUvQzs7O0dBR0c7QUFDSCxNQUFxQixpQkFBaUI7SUFDcEM7Ozs7OztPQU1HO0lBQ0ksTUFBTSxDQUFDLFFBQVEsQ0FBQyxrQkFBc0M7UUFDM0QsT0FBTyxrQkFBa0IsQ0FBQyxrQkFBa0IsS0FBSyxJQUFJLENBQUE7SUFDdkQsQ0FBQztJQUVEOzs7Ozs7Ozs7OztPQVdHO0lBQ1UsYUFBYSxDQUN4QixVQUFvQyxFQUNwQyxrQkFBc0MsRUFDdEMsWUFBb0IsRUFDcEIsTUFBa0IsRUFDbEIsS0FBWTs7WUFFWixNQUFNLHNCQUFzQixHQUFHLGlCQUFPLENBQUMsa0NBQWtDLENBQUMsTUFBTSxFQUFFLEtBQUssQ0FBQyxDQUFBO1lBQ3hGLE1BQU0sbUJBQW1CLEdBQUcsaUJBQWlCLENBQUMsa0JBQWtCLENBQzlELE1BQU0sVUFBVSxDQUFDLGNBQWMsQ0FBQyxzQkFBc0IsQ0FBQyxDQUN4RCxDQUFBO1lBQ0QsSUFBSSxtQkFBbUIsSUFBSSxJQUFJLElBQUksbUJBQW1CLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDbkUsT0FBTyxJQUFJLENBQUE7YUFDWjtZQUVELElBQUksVUFBVSxDQUFBO1lBQ2QsSUFBSSxrQkFBa0IsQ0FBQyx5QkFBeUIsRUFBRTtnQkFDaEQsTUFBTSxVQUFVLEdBQUcsTUFBTSxVQUFVLENBQUMsaUJBQWlCLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtnQkFDN0UsSUFBSSxVQUFVLElBQUksSUFBSSxJQUFJLFVBQVUsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO29CQUMvQyxVQUFVLEdBQUcsVUFBVSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtpQkFDeEU7YUFDRjtZQUVELE9BQU87Z0JBQ0wsVUFBVSxFQUFFLFVBQVUsSUFBSSxDQUFDLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUM7Z0JBQ2xFLFdBQVcsRUFBRSxpQkFBaUIsQ0FBQyw2QkFBNkIsQ0FBQyxtQkFBbUIsRUFBRSxZQUFZLENBQUM7YUFDaEcsQ0FBQTtRQUNILENBQUM7S0FBQTtJQUVEOzs7Ozs7T0FNRztJQUNJLE1BQU0sQ0FBQyxrQkFBa0IsQ0FDOUIsY0FBNkQ7UUFFN0QsSUFBSSxjQUFjLElBQUksSUFBSSxFQUFFO1lBQzFCLGVBQWU7WUFDZixPQUFPLElBQUksQ0FBQTtTQUNaO1FBQ0QseUVBQXlFO1FBQ3pFLElBQUksbUJBQW1CLENBQUMsY0FBYyxDQUFDLEVBQUU7WUFDdkMsT0FBTyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFDLEtBQUssSUFBSSxJQUFJLENBQUMsQ0FBQTtTQUNqRTtRQUNELE9BQU8sQ0FBQyxLQUFLLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxjQUFjLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxDQUFBO0lBQ2pILENBQUM7SUFFRDs7Ozs7O09BTUc7SUFDSSxNQUFNLENBQUMsNkJBQTZCLENBQ3pDLFNBQXNDLEVBQ3RDLFlBQW9CO1FBRXBCLElBQUksbUJBQW1CLENBQUMsU0FBUyxDQUFDLEVBQUU7WUFDbEMsT0FBTyxTQUFTLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUMzQixJQUFJLEVBQUUsaUJBQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQztnQkFDcEMsUUFBUSxFQUFFLGlCQUFPLENBQUMsZUFBZSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsS0FBSyxDQUFDO2dCQUN0RCxLQUFLLEVBQUUsWUFBSyxDQUFDLFVBQVUsQ0FBQyxpQkFBTyxDQUFDLGtCQUFrQixDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQztnQkFDbEUsUUFBUSxFQUFFLFlBQVk7YUFDdkIsQ0FBQyxDQUFDLENBQUE7U0FDSjtRQUNELE9BQU8sU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUMzQixJQUFJLEVBQUUsaUJBQU8sQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQztZQUM5QixRQUFRLEVBQUUsaUJBQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLEtBQUssQ0FBQyxLQUFLLENBQUM7WUFDaEQsS0FBSyxFQUFFLFlBQUssQ0FBQyxVQUFVLENBQUMsaUJBQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUM7WUFDNUQsUUFBUSxFQUFFLFlBQVk7U0FDdkIsQ0FBQyxDQUFDLENBQUE7SUFDTCxDQUFDO0NBQ0Y7QUFwR0Qsb0NBb0dDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxLQUFVO0lBQ3JDLE9BQU8sS0FBSyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSw2QkFBWSxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtBQUMxRCxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgKiBhcyBhdG9tSWRlIGZyb20gXCJhdG9tLWlkZS1iYXNlXCJcbmltcG9ydCBDb252ZXJ0IGZyb20gXCIuLi9jb252ZXJ0XCJcbmltcG9ydCAqIGFzIFV0aWxzIGZyb20gXCIuLi91dGlsc1wiXG5pbXBvcnQgeyBMYW5ndWFnZUNsaWVudENvbm5lY3Rpb24sIExvY2F0aW9uLCBMb2NhdGlvbkxpbmssIFNlcnZlckNhcGFiaWxpdGllcyB9IGZyb20gXCIuLi9sYW5ndWFnZWNsaWVudFwiXG5pbXBvcnQgeyBQb2ludCwgVGV4dEVkaXRvciwgUmFuZ2UgfSBmcm9tIFwiYXRvbVwiXG5cbi8qKlxuICogUHVibGljOiBBZGFwdHMgdGhlIGxhbmd1YWdlIHNlcnZlciBkZWZpbml0aW9uIHByb3ZpZGVyIHRvIHRoZSBBdG9tIElERSBVSSBEZWZpbml0aW9ucyBwYWNrYWdlIGZvciAnR28gVG8gRGVmaW5pdGlvbidcbiAqIGZ1bmN0aW9uYWxpdHkuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIERlZmluaXRpb25BZGFwdGVyIHtcbiAgLyoqXG4gICAqIFB1YmxpYzogRGV0ZXJtaW5lIHdoZXRoZXIgdGhpcyBhZGFwdGVyIGNhbiBiZSB1c2VkIHRvIGFkYXB0IGEgbGFuZ3VhZ2Ugc2VydmVyIGJhc2VkIG9uIHRoZSBzZXJ2ZXJDYXBhYmlsaXRpZXNcbiAgICogbWF0cml4IGNvbnRhaW5pbmcgYSBkZWZpbml0aW9uUHJvdmlkZXIuXG4gICAqXG4gICAqIEBwYXJhbSBzZXJ2ZXJDYXBhYmlsaXRpZXMgVGhlIHtTZXJ2ZXJDYXBhYmlsaXRpZXN9IG9mIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgdG8gY29uc2lkZXIuXG4gICAqIEByZXR1cm5zIEEge0Jvb2xlYW59IGluZGljYXRpbmcgYWRhcHRlciBjYW4gYWRhcHQgdGhlIHNlcnZlciBiYXNlZCBvbiB0aGUgZ2l2ZW4gc2VydmVyQ2FwYWJpbGl0aWVzLlxuICAgKi9cbiAgcHVibGljIHN0YXRpYyBjYW5BZGFwdChzZXJ2ZXJDYXBhYmlsaXRpZXM6IFNlcnZlckNhcGFiaWxpdGllcyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzZXJ2ZXJDYXBhYmlsaXRpZXMuZGVmaW5pdGlvblByb3ZpZGVyID09PSB0cnVlXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBHZXQgdGhlIGRlZmluaXRpb25zIGZvciBhIHN5bWJvbCBhdCBhIGdpdmVuIHtQb2ludH0gd2l0aGluIGEge1RleHRFZGl0b3J9IGluY2x1ZGluZyBvcHRpb25hbGx5IGhpZ2hsaWdodGluZ1xuICAgKiBhbGwgb3RoZXIgcmVmZXJlbmNlcyB3aXRoaW4gdGhlIGRvY3VtZW50IGlmIHRoZSBsYW5nYXVnZSBzZXJ2ZXIgYWxzbyBzdXBwb3J0cyBoaWdobGlnaHRpbmcuXG4gICAqXG4gICAqIEBwYXJhbSBjb25uZWN0aW9uIEEge0xhbmd1YWdlQ2xpZW50Q29ubmVjdGlvbn0gdG8gdGhlIGxhbmd1YWdlIHNlcnZlciB0aGF0IHdpbGwgcHJvdmlkZSBkZWZpbml0aW9ucyBhbmQgaGlnaGxpZ2h0cy5cbiAgICogQHBhcmFtIHNlcnZlckNhcGFiaWxpdGllcyBUaGUge1NlcnZlckNhcGFiaWxpdGllc30gb2YgdGhlIGxhbmd1YWdlIHNlcnZlciB0aGF0IHdpbGwgYmUgdXNlZC5cbiAgICogQHBhcmFtIGxhbmd1YWdlTmFtZSBUaGUgbmFtZSBvZiB0aGUgcHJvZ3JhbW1pbmcgbGFuZ3VhZ2UuXG4gICAqIEBwYXJhbSBlZGl0b3IgVGhlIEF0b20ge1RleHRFZGl0b3J9IGNvbnRhaW5pbmcgdGhlIHN5bWJvbCBhbmQgcG90ZW50aWFsIGhpZ2hsaWdodHMuXG4gICAqIEBwYXJhbSBwb2ludCBUaGUgQXRvbSB7UG9pbnR9IGNvbnRhaW5pbmcgdGhlIHBvc2l0aW9uIG9mIHRoZSB0ZXh0IHRoYXQgcmVwcmVzZW50cyB0aGUgc3ltYm9sIGZvciB3aGljaCB0aGVcbiAgICogICBkZWZpbml0aW9uIGFuZCBoaWdobGlnaHRzIHNob3VsZCBiZSBwcm92aWRlZC5cbiAgICogQHJldHVybnMgQSB7UHJvbWlzZX0gaW5kaWNhdGluZyBhZGFwdGVyIGNhbiBhZGFwdCB0aGUgc2VydmVyIGJhc2VkIG9uIHRoZSBnaXZlbiBzZXJ2ZXJDYXBhYmlsaXRpZXMuXG4gICAqL1xuICBwdWJsaWMgYXN5bmMgZ2V0RGVmaW5pdGlvbihcbiAgICBjb25uZWN0aW9uOiBMYW5ndWFnZUNsaWVudENvbm5lY3Rpb24sXG4gICAgc2VydmVyQ2FwYWJpbGl0aWVzOiBTZXJ2ZXJDYXBhYmlsaXRpZXMsXG4gICAgbGFuZ3VhZ2VOYW1lOiBzdHJpbmcsXG4gICAgZWRpdG9yOiBUZXh0RWRpdG9yLFxuICAgIHBvaW50OiBQb2ludFxuICApOiBQcm9taXNlPGF0b21JZGUuRGVmaW5pdGlvblF1ZXJ5UmVzdWx0IHwgbnVsbD4ge1xuICAgIGNvbnN0IGRvY3VtZW50UG9zaXRpb25QYXJhbXMgPSBDb252ZXJ0LmVkaXRvclRvVGV4dERvY3VtZW50UG9zaXRpb25QYXJhbXMoZWRpdG9yLCBwb2ludClcbiAgICBjb25zdCBkZWZpbml0aW9uTG9jYXRpb25zID0gRGVmaW5pdGlvbkFkYXB0ZXIubm9ybWFsaXplTG9jYXRpb25zKFxuICAgICAgYXdhaXQgY29ubmVjdGlvbi5nb3RvRGVmaW5pdGlvbihkb2N1bWVudFBvc2l0aW9uUGFyYW1zKVxuICAgIClcbiAgICBpZiAoZGVmaW5pdGlvbkxvY2F0aW9ucyA9PSBudWxsIHx8IGRlZmluaXRpb25Mb2NhdGlvbnMubGVuZ3RoID09PSAwKSB7XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH1cblxuICAgIGxldCBxdWVyeVJhbmdlXG4gICAgaWYgKHNlcnZlckNhcGFiaWxpdGllcy5kb2N1bWVudEhpZ2hsaWdodFByb3ZpZGVyKSB7XG4gICAgICBjb25zdCBoaWdobGlnaHRzID0gYXdhaXQgY29ubmVjdGlvbi5kb2N1bWVudEhpZ2hsaWdodChkb2N1bWVudFBvc2l0aW9uUGFyYW1zKVxuICAgICAgaWYgKGhpZ2hsaWdodHMgIT0gbnVsbCAmJiBoaWdobGlnaHRzLmxlbmd0aCA+IDApIHtcbiAgICAgICAgcXVlcnlSYW5nZSA9IGhpZ2hsaWdodHMubWFwKChoKSA9PiBDb252ZXJ0LmxzUmFuZ2VUb0F0b21SYW5nZShoLnJhbmdlKSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgcXVlcnlSYW5nZTogcXVlcnlSYW5nZSB8fCBbVXRpbHMuZ2V0V29yZEF0UG9zaXRpb24oZWRpdG9yLCBwb2ludCldLFxuICAgICAgZGVmaW5pdGlvbnM6IERlZmluaXRpb25BZGFwdGVyLmNvbnZlcnRMb2NhdGlvbnNUb0RlZmluaXRpb25zKGRlZmluaXRpb25Mb2NhdGlvbnMsIGxhbmd1YWdlTmFtZSksXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogTm9ybWFsaXplIHRoZSBsb2NhdGlvbnMgc28gYSBzaW5nbGUge0xvY2F0aW9ufSBiZWNvbWVzIGFuIHtBcnJheX0gb2YganVzdCBvbmUuIFRoZSBsYW5ndWFnZSBzZXJ2ZXIgcHJvdG9jb2xcbiAgICogcmV0dXJuIGVpdGhlciBhcyB0aGUgcHJvdG9jb2wgZXZvbHZlZCBiZXR3ZWVuIHYxIGFuZCB2Mi5cbiAgICpcbiAgICogQHBhcmFtIGxvY2F0aW9uUmVzdWx0IEVpdGhlciBhIHNpbmdsZSB7TG9jYXRpb259IG9iamVjdCBvciBhbiB7QXJyYXl9IG9mIHtMb2NhdGlvbnN9LlxuICAgKiBAcmV0dXJucyBBbiB7QXJyYXl9IG9mIHtMb2NhdGlvbn1zIG9yIHtudWxsfSBpZiB0aGUgbG9jYXRpb25SZXN1bHQgd2FzIG51bGwuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIG5vcm1hbGl6ZUxvY2F0aW9ucyhcbiAgICBsb2NhdGlvblJlc3VsdDogTG9jYXRpb24gfCBMb2NhdGlvbltdIHwgTG9jYXRpb25MaW5rW10gfCBudWxsXG4gICk6IExvY2F0aW9uW10gfCBMb2NhdGlvbkxpbmtbXSB8IG51bGwge1xuICAgIGlmIChsb2NhdGlvblJlc3VsdCA9PSBudWxsKSB7XG4gICAgICAvLyBUT0RPIHVzZSA9PT1cbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuICAgIC8vIFRPRE8gYGQudGFyZ2V0UmFuZ2Uuc3RhcnRgIG5ldmVyIGJlY29tZXMgYG51bGxgIGFjY29yZGluZyB0byB0aGUgdHlwZXNcbiAgICBpZiAoaXNMb2NhdGlvbkxpbmtBcnJheShsb2NhdGlvblJlc3VsdCkpIHtcbiAgICAgIHJldHVybiBsb2NhdGlvblJlc3VsdC5maWx0ZXIoKGQpID0+IGQudGFyZ2V0UmFuZ2Uuc3RhcnQgIT0gbnVsbClcbiAgICB9XG4gICAgcmV0dXJuIChBcnJheS5pc0FycmF5KGxvY2F0aW9uUmVzdWx0KSA/IGxvY2F0aW9uUmVzdWx0IDogW2xvY2F0aW9uUmVzdWx0XSkuZmlsdGVyKChkKSA9PiBkLnJhbmdlLnN0YXJ0ICE9IG51bGwpXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBDb252ZXJ0IGFuIHtBcnJheX0gb2Yge0xvY2F0aW9ufSBvYmplY3RzIGludG8gYW4gQXJyYXkgb2Yge0RlZmluaXRpb259cy5cbiAgICpcbiAgICogQHBhcmFtIGxvY2F0aW9ucyBBbiB7QXJyYXl9IG9mIHtMb2NhdGlvbn0gb2JqZWN0cyB0byBiZSBjb252ZXJ0ZWQuXG4gICAqIEBwYXJhbSBsYW5ndWFnZU5hbWUgVGhlIG5hbWUgb2YgdGhlIGxhbmd1YWdlIHRoZXNlIG9iamVjdHMgYXJlIHdyaXR0ZW4gaW4uXG4gICAqIEByZXR1cm5zIEFuIHtBcnJheX0gb2Yge0RlZmluaXRpb259cyB0aGF0IHJlcHJlc2VudGVkIHRoZSBjb252ZXJ0ZWQge0xvY2F0aW9ufXMuXG4gICAqL1xuICBwdWJsaWMgc3RhdGljIGNvbnZlcnRMb2NhdGlvbnNUb0RlZmluaXRpb25zKFxuICAgIGxvY2F0aW9uczogTG9jYXRpb25bXSB8IExvY2F0aW9uTGlua1tdLFxuICAgIGxhbmd1YWdlTmFtZTogc3RyaW5nXG4gICk6IGF0b21JZGUuRGVmaW5pdGlvbltdIHtcbiAgICBpZiAoaXNMb2NhdGlvbkxpbmtBcnJheShsb2NhdGlvbnMpKSB7XG4gICAgICByZXR1cm4gbG9jYXRpb25zLm1hcCgoZCkgPT4gKHtcbiAgICAgICAgcGF0aDogQ29udmVydC51cmlUb1BhdGgoZC50YXJnZXRVcmkpLFxuICAgICAgICBwb3NpdGlvbjogQ29udmVydC5wb3NpdGlvblRvUG9pbnQoZC50YXJnZXRSYW5nZS5zdGFydCksXG4gICAgICAgIHJhbmdlOiBSYW5nZS5mcm9tT2JqZWN0KENvbnZlcnQubHNSYW5nZVRvQXRvbVJhbmdlKGQudGFyZ2V0UmFuZ2UpKSxcbiAgICAgICAgbGFuZ3VhZ2U6IGxhbmd1YWdlTmFtZSxcbiAgICAgIH0pKVxuICAgIH1cbiAgICByZXR1cm4gbG9jYXRpb25zLm1hcCgoZCkgPT4gKHtcbiAgICAgIHBhdGg6IENvbnZlcnQudXJpVG9QYXRoKGQudXJpKSxcbiAgICAgIHBvc2l0aW9uOiBDb252ZXJ0LnBvc2l0aW9uVG9Qb2ludChkLnJhbmdlLnN0YXJ0KSxcbiAgICAgIHJhbmdlOiBSYW5nZS5mcm9tT2JqZWN0KENvbnZlcnQubHNSYW5nZVRvQXRvbVJhbmdlKGQucmFuZ2UpKSxcbiAgICAgIGxhbmd1YWdlOiBsYW5ndWFnZU5hbWUsXG4gICAgfSkpXG4gIH1cbn1cblxuZnVuY3Rpb24gaXNMb2NhdGlvbkxpbmtBcnJheSh2YWx1ZTogYW55KTogdmFsdWUgaXMgTG9jYXRpb25MaW5rW10ge1xuICByZXR1cm4gQXJyYXkuaXNBcnJheSh2YWx1ZSkgJiYgTG9jYXRpb25MaW5rLmlzKHZhbHVlWzBdKVxufVxuIl19
\No newline at end of file