UNPKG

32 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3const convert_1 = require("../convert");
4const languageclient_1 = require("../languageclient");
5/**
6 * Public: Listen to diagnostics messages from the language server and publish them to the user by way of the Linter
7 * Push (Indie) v2 API provided by the Base Linter package.
8 */
9class LinterPushV2Adapter {
10 /**
11 * Public: Create a new {LinterPushV2Adapter} that will listen for diagnostics via the supplied {LanguageClientConnection}.
12 *
13 * @param connection A {LanguageClientConnection} to the language server that will provide diagnostics.
14 */
15 constructor(connection) {
16 /*
17 * A map from file path calculated using the LS diagnostic uri to an array of linter messages {linter.Message[]}
18 */
19 this._diagnosticMap = new Map();
20 /**
21 * A map from file path {linter.Message["location"]["file"]} to a Map of all Message keys to Diagnostics
22 * ${Map<linter.Message["key"], Diagnostic>} It has to be stored separately because a {Message} object cannot hold all
23 * of the information that a {Diagnostic} provides, thus we store the original {Diagnostic} object.
24 */
25 this._lsDiagnosticMap = new Map();
26 this._indies = new Set();
27 connection.onPublishDiagnostics(this.captureDiagnostics.bind(this));
28 }
29 /** Dispose this adapter ensuring any resources are freed and events unhooked. */
30 dispose() {
31 this.detachAll();
32 }
33 /**
34 * Public: Attach this {LinterPushV2Adapter} to a given {V2IndieDelegate} registry.
35 *
36 * @param indie A {V2IndieDelegate} that wants to receive messages.
37 */
38 attach(indie) {
39 this._indies.add(indie);
40 this._diagnosticMap.forEach((value, key) => indie.setMessages(key, value));
41 indie.onDidDestroy(() => {
42 this._indies.delete(indie);
43 });
44 }
45 /** Public: Remove all {V2IndieDelegate} registries attached to this adapter and clear them. */
46 detachAll() {
47 this._indies.forEach((i) => i.clearMessages());
48 this._indies.clear();
49 }
50 /**
51 * Public: Capture the diagnostics sent from a langguage server, convert them to the Linter V2 format and forward them
52 * on to any attached {V2IndieDelegate}s.
53 *
54 * @param params The {PublishDiagnosticsParams} received from the language server that should be captured and
55 * forwarded on to any attached {V2IndieDelegate}s.
56 */
57 captureDiagnostics(params) {
58 const path = convert_1.default.uriToPath(params.uri);
59 const codeMap = new Map();
60 const messages = params.diagnostics.map((d) => {
61 const linterMessage = lsDiagnosticToV2Message(path, d);
62 codeMap.set(getMessageKey(linterMessage), d);
63 return linterMessage;
64 });
65 this._diagnosticMap.set(path, messages);
66 this._lsDiagnosticMap.set(path, codeMap);
67 this._indies.forEach((i) => i.setMessages(path, messages));
68 }
69 /**
70 * Public: Convert a single {Diagnostic} received from a language server into a single {V2Message} expected by the
71 * Linter V2 API.
72 *
73 * @param path A string representing the path of the file the diagnostic belongs to.
74 * @param diagnostics A {Diagnostic} object received from the language server.
75 * @returns A {V2Message} equivalent to the {Diagnostic} object supplied by the language server.
76 */
77 diagnosticToV2Message(path, diagnostic) {
78 return {
79 location: {
80 file: path,
81 position: convert_1.default.lsRangeToAtomRange(diagnostic.range),
82 },
83 excerpt: diagnostic.message,
84 linterName: diagnostic.source,
85 severity: LinterPushV2Adapter.diagnosticSeverityToSeverity(diagnostic.severity || -1),
86 };
87 }
88 /**
89 * Public: get diagnostics for the given linter messages
90 *
91 * @param linterMessages An array of linter {V2Message}
92 * @returns An array of LS {Diagnostic[]}
93 */
94 getLSDiagnosticsForMessages(linterMessages) {
95 return linterMessages
96 .map(this.getLSDiagnosticForMessage)
97 // filter out undefined
98 .filter((diagnostic) => diagnostic !== undefined);
99 }
100 /**
101 * Public: Get the {Diagnostic} that is associated with the given Base Linter v2 {Message}.
102 *
103 * @param message The {Message} object to fetch the {Diagnostic} for.
104 * @returns The associated {Diagnostic}.
105 */
106 getLSDiagnosticForMessage(message) {
107 var _a;
108 return (_a = this._lsDiagnosticMap.get(message.location.file)) === null || _a === void 0 ? void 0 : _a.get(getMessageKey(message));
109 }
110 /**
111 * Public: Convert a diagnostic severity number obtained from the language server into the textual equivalent for a
112 * Linter {V2Message}.
113 *
114 * @param severity A number representing the severity of the diagnostic.
115 * @returns A string of 'error', 'warning' or 'info' depending on the severity.
116 */
117 static diagnosticSeverityToSeverity(severity) {
118 switch (severity) {
119 case languageclient_1.DiagnosticSeverity.Error:
120 return "error";
121 case languageclient_1.DiagnosticSeverity.Warning:
122 return "warning";
123 case languageclient_1.DiagnosticSeverity.Information:
124 case languageclient_1.DiagnosticSeverity.Hint:
125 default:
126 return "info";
127 }
128 }
129}
130exports.default = LinterPushV2Adapter;
131/**
132 * Public: Convert a single {Diagnostic} received from a language server into a single {Message} expected by the Linter V2 API.
133 *
134 * @param path A string representing the path of the file the diagnostic belongs to.
135 * @param diagnostics A {Diagnostic} object received from the language server.
136 * @returns A {Message} equivalent to the {Diagnostic} object supplied by the language server.
137 */
138function lsDiagnosticToV2Message(path, diagnostic) {
139 var _a, _b, _c;
140 return {
141 location: {
142 file: path,
143 position: convert_1.default.lsRangeToAtomRange(diagnostic.range),
144 },
145 reference: relatedInformationToReference(diagnostic.relatedInformation),
146 url: (_a = diagnostic.codeDescription) === null || _a === void 0 ? void 0 : _a.href,
147 icon: iconForLSSeverity((_b = diagnostic.severity) !== null && _b !== void 0 ? _b : languageclient_1.DiagnosticSeverity.Error),
148 excerpt: diagnostic.message,
149 linterName: diagnostic.source,
150 severity: lsSeverityToV2MessageSeverity((_c = diagnostic.severity) !== null && _c !== void 0 ? _c : languageclient_1.DiagnosticSeverity.Error),
151 // BLOCKED: on steelbrain/linter#1722
152 solutions: undefined,
153 };
154}
155/**
156 * Convert a severity level of an LSP {Diagnostic} to that of a Base Linter v2 {Message}. Note: this conversion is lossy
157 * due to the v2 Message not being able to represent hints.
158 *
159 * @param severity A severity level of of an LSP {Diagnostic} to be converted.
160 * @returns A severity level a Base Linter v2 {Message}.
161 */
162function lsSeverityToV2MessageSeverity(severity) {
163 switch (severity) {
164 case languageclient_1.DiagnosticSeverity.Error:
165 return "error";
166 case languageclient_1.DiagnosticSeverity.Warning:
167 return "warning";
168 case languageclient_1.DiagnosticSeverity.Information:
169 case languageclient_1.DiagnosticSeverity.Hint:
170 return "info";
171 default:
172 throw Error(`Unexpected diagnostic severity '${severity}'`);
173 }
174}
175/**
176 * Convert a diagnostic severity number obtained from the language server into an Octicon icon.
177 *
178 * @param severity A number representing the severity of the diagnostic.
179 * @returns An Octicon name.
180 */
181function iconForLSSeverity(severity) {
182 switch (severity) {
183 case languageclient_1.DiagnosticSeverity.Error:
184 return "stop";
185 case languageclient_1.DiagnosticSeverity.Warning:
186 return "warning";
187 case languageclient_1.DiagnosticSeverity.Information:
188 return "info";
189 case languageclient_1.DiagnosticSeverity.Hint:
190 return "light-bulb";
191 default:
192 return undefined;
193 }
194}
195/**
196 * Convert the related information from a diagnostic into a reference point for a Linter {V2Message}.
197 *
198 * @param relatedInfo Several related information objects (only the first is used).
199 * @returns A value that is suitable for using as {V2Message}.reference.
200 */
201function relatedInformationToReference(relatedInfo) {
202 if (relatedInfo === undefined || relatedInfo.length === 0) {
203 return undefined;
204 }
205 const location = relatedInfo[0].location;
206 return {
207 file: convert_1.default.uriToPath(location.uri),
208 position: convert_1.default.lsRangeToAtomRange(location.range).start,
209 };
210}
211/**
212 * Get a unique key for a Linter v2 Message
213 *
214 * @param message A {Message} object
215 * @returns ${string} a unique key
216 */
217function getMessageKey(message) {
218 if (typeof message.key !== "string") {
219 updateMessageKey(message);
220 }
221 return message.key; // updateMessageKey adds message.key string
222}
223/**
224 * Construct an unique key for a Linter v2 Message and store it in `Message.key`
225 *
226 * @param message A {Message} object to serialize.
227 * @returns ${string} a unique key
228 */
229function updateMessageKey(message) {
230 // From https://github.com/steelbrain/linter/blob/fadd462914ef0a8ed5b73a489f662a9393bdbe9f/lib/helpers.ts#L50-L64
231 const { reference, location } = message;
232 const nameStr = `$LINTER:${message.linterName}`;
233 const locationStr = `$LOCATION:${location.file}$${location.position.start.row}$${location.position.start.column}$${location.position.end.row}$${location.position.end.column}`;
234 const referenceStr = reference
235 ? `$REFERENCE:${reference.file}$${reference.position ? `${reference.position.row}$${reference.position.column}` : ""}`
236 : "$REFERENCE:null";
237 const excerptStr = `$EXCERPT:${message.excerpt}`;
238 const severityStr = `$SEVERITY:${message.severity}`;
239 const iconStr = message.icon ? `$ICON:${message.icon}` : "$ICON:null";
240 const urlStr = message.url ? `$URL:${message.url}` : "$URL:null";
241 const descriptionStr = typeof message.description === "string" ? `$DESCRIPTION:${message.description}` : "$DESCRIPTION:null";
242 message.key = `${nameStr}${locationStr}${referenceStr}${excerptStr}${severityStr}${iconStr}${urlStr}${descriptionStr}`;
243}
244//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGludGVyLXB1c2gtdjItYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9hZGFwdGVycy9saW50ZXItcHVzaC12Mi1hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0Esd0NBQWdDO0FBQ2hDLHNEQU0wQjtBQUUxQjs7O0dBR0c7QUFDSCxNQUFxQixtQkFBbUI7SUFjdEM7Ozs7T0FJRztJQUNILFlBQVksVUFBb0M7UUFsQmhEOztXQUVHO1FBQ08sbUJBQWMsR0FBa0MsSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUNuRTs7OztXQUlHO1FBQ08scUJBQWdCLEdBQ3hCLElBQUksR0FBRyxFQUFFLENBQUE7UUFDRCxZQUFPLEdBQThCLElBQUksR0FBRyxFQUFFLENBQUE7UUFRdEQsVUFBVSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUNyRSxDQUFDO0lBRUQsaUZBQWlGO0lBQzFFLE9BQU87UUFDWixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUE7SUFDbEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsS0FBMkI7UUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQzFFLEtBQUssQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFO1lBQ3RCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzVCLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVELCtGQUErRjtJQUN4RixTQUFTO1FBQ2QsSUFBSSxDQUFDLE9BQU8sQ0FB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O0FBQ3hILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBsaW50ZXIgZnJvbSBcImF0b20vbGludGVyXCJcbmltcG9ydCBDb252ZXJ0IGZyb20gXCIuLi9jb252ZXJ0XCJcbmltcG9ydCB7XG4gIERpYWdub3N0aWMsXG4gIERpYWdub3N0aWNTZXZlcml0eSxcbiAgRGlhZ25vc3RpY1JlbGF0ZWRJbmZvcm1hdGlvbixcbiAgTGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9uLFxuICBQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXMsXG59IGZyb20gXCIuLi9sYW5ndWFnZWNsaWVudFwiXG5cbi8qKlxuICogUHVibGljOiBMaXN0ZW4gdG8gZGlhZ25vc3RpY3MgbWVzc2FnZXMgZnJvbSB0aGUgbGFuZ3VhZ2Ugc2VydmVyIGFuZCBwdWJsaXNoIHRoZW0gdG8gdGhlIHVzZXIgYnkgd2F5IG9mIHRoZSBMaW50ZXJcbiAqIFB1c2ggKEluZGllKSB2MiBBUEkgcHJvdmlkZWQgYnkgdGhlIEJhc2UgTGludGVyIHBhY2thZ2UuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpbnRlclB1c2hWMkFkYXB0ZXIge1xuICAvKlxuICAgKiBBIG1hcCBmcm9tIGZpbGUgcGF0aCBjYWxjdWxhdGVkIHVzaW5nIHRoZSBMUyBkaWFnbm9zdGljIHVyaSB0byBhbiBhcnJheSBvZiBsaW50ZXIgbWVzc2FnZXMge2xpbnRlci5NZXNzYWdlW119XG4gICAqL1xuICBwcm90ZWN0ZWQgX2RpYWdub3N0aWNNYXA6IE1hcDxzdHJpbmcsIGxpbnRlci5NZXNzYWdlW10+ID0gbmV3IE1hcCgpXG4gIC8qKlxuICAgKiBBIG1hcCBmcm9tIGZpbGUgcGF0aCB7bGludGVyLk1lc3NhZ2VbXCJsb2NhdGlvblwiXVtcImZpbGVcIl19IHRvIGEgTWFwIG9mIGFsbCBNZXNzYWdlIGtleXMgdG8gRGlhZ25vc3RpY3NcbiAgICogJHtNYXA8bGludGVyLk1lc3NhZ2VbXCJrZXlcIl0sIERpYWdub3N0aWM+fSBJdCBoYXMgdG8gYmUgc3RvcmVkIHNlcGFyYXRlbHkgYmVjYXVzZSBhIHtNZXNzYWdlfSBvYmplY3QgY2Fubm90IGhvbGQgYWxsXG4gICAqIG9mIHRoZSBpbmZvcm1hdGlvbiB0aGF0IGEge0RpYWdub3N0aWN9IHByb3ZpZGVzLCB0aHVzIHdlIHN0b3JlIHRoZSBvcmlnaW5hbCB7RGlhZ25vc3RpY30gb2JqZWN0LlxuICAgKi9cbiAgcHJvdGVjdGVkIF9sc0RpYWdub3N0aWNNYXA6IE1hcDxsaW50ZXIuTWVzc2FnZVtcImxvY2F0aW9uXCJdW1wiZmlsZVwiXSwgTWFwPGxpbnRlci5NZXNzYWdlW1wia2V5XCJdLCBEaWFnbm9zdGljPj4gPVxuICAgIG5ldyBNYXAoKVxuICBwcm90ZWN0ZWQgX2luZGllczogU2V0PGxpbnRlci5JbmRpZURlbGVnYXRlPiA9IG5ldyBTZXQoKVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENyZWF0ZSBhIG5ldyB7TGludGVyUHVzaFYyQWRhcHRlcn0gdGhhdCB3aWxsIGxpc3RlbiBmb3IgZGlhZ25vc3RpY3MgdmlhIHRoZSBzdXBwbGllZCB7TGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9ufS5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5lY3Rpb24gQSB7TGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9ufSB0byB0aGUgbGFuZ3VhZ2Ugc2VydmVyIHRoYXQgd2lsbCBwcm92aWRlIGRpYWdub3N0aWNzLlxuICAgKi9cbiAgY29uc3RydWN0b3IoY29ubmVjdGlvbjogTGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9uKSB7XG4gICAgY29ubmVjdGlvbi5vblB1Ymxpc2hEaWFnbm9zdGljcyh0aGlzLmNhcHR1cmVEaWFnbm9zdGljcy5iaW5kKHRoaXMpKVxuICB9XG5cbiAgLyoqIERpc3Bvc2UgdGhpcyBhZGFwdGVyIGVuc3VyaW5nIGFueSByZXNvdXJjZXMgYXJlIGZyZWVkIGFuZCBldmVudHMgdW5ob29rZWQuICovXG4gIHB1YmxpYyBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuZGV0YWNoQWxsKClcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IEF0dGFjaCB0aGlzIHtMaW50ZXJQdXNoVjJBZGFwdGVyfSB0byBhIGdpdmVuIHtWMkluZGllRGVsZWdhdGV9IHJlZ2lzdHJ5LlxuICAgKlxuICAgKiBAcGFyYW0gaW5kaWUgQSB7VjJJbmRpZURlbGVnYXRlfSB0aGF0IHdhbnRzIHRvIHJlY2VpdmUgbWVzc2FnZXMuXG4gICAqL1xuICBwdWJsaWMgYXR0YWNoKGluZGllOiBsaW50ZXIuSW5kaWVEZWxlZ2F0ZSk6IHZvaWQge1xuICAgIHRoaXMuX2luZGllcy5hZGQoaW5kaWUpXG4gICAgdGhpcy5fZGlhZ25vc3RpY01hcC5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiBpbmRpZS5zZXRNZXNzYWdlcyhrZXksIHZhbHVlKSlcbiAgICBpbmRpZS5vbkRpZERlc3Ryb3koKCkgPT4ge1xuICAgICAgdGhpcy5faW5kaWVzLmRlbGV0ZShpbmRpZSlcbiAgICB9KVxuICB9XG5cbiAgLyoqIFB1YmxpYzogUmVtb3ZlIGFsbCB7VjJJbmRpZURlbGVnYXRlfSByZWdpc3RyaWVzIGF0dGFjaGVkIHRvIHRoaXMgYWRhcHRlciBhbmQgY2xlYXIgdGhlbS4gKi9cbiAgcHVibGljIGRldGFjaEFsbCgpOiB2b2lkIHtcbiAgICB0aGlzLl9pbmRpZXMuZm9yRWFjaCgoaSkgPT4gaS5jbGVhck1lc3NhZ2VzKCkpXG4gICAgdGhpcy5faW5kaWVzLmNsZWFyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENhcHR1cmUgdGhlIGRpYWdub3N0aWNzIHNlbnQgZnJvbSBhIGxhbmdndWFnZSBzZXJ2ZXIsIGNvbnZlcnQgdGhlbSB0byB0aGUgTGludGVyIFYyIGZvcm1hdCBhbmQgZm9yd2FyZCB0aGVtXG4gICAqIG9uIHRvIGFueSBhdHRhY2hlZCB7VjJJbmRpZURlbGVnYXRlfXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgVGhlIHtQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXN9IHJlY2VpdmVkIGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlciB0aGF0IHNob3VsZCBiZSBjYXB0dXJlZCBhbmRcbiAgICogICBmb3J3YXJkZWQgb24gdG8gYW55IGF0dGFjaGVkIHtWMkluZGllRGVsZWdhdGV9cy5cbiAgICovXG4gIHB1YmxpYyBjYXB0dXJlRGlhZ25vc3RpY3MocGFyYW1zOiBQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXMpOiB2b2lkIHtcbiAgICBjb25zdCBwYXRoID0gQ29udmVydC51cmlUb1BhdGgocGFyYW1zLnVyaSlcbiAgICBjb25zdCBjb2RlTWFwID0gbmV3IE1hcDxzdHJpbmcsIERpYWdub3N0aWM+KClcbiAgICBjb25zdCBtZXNzYWdlcyA9IHBhcmFtcy5kaWFnbm9zdGljcy5tYXAoKGQpID0+IHtcbiAgICAgIGNvbnN0IGxpbnRlck1lc3NhZ2UgPSBsc0RpYWdub3N0aWNUb1YyTWVzc2FnZShwYXRoLCBkKVxuICAgICAgY29kZU1hcC5zZXQoZ2V0TWVzc2FnZUtleShsaW50ZXJNZXNzYWdlKSwgZClcbiAgICAgIHJldHVybiBsaW50ZXJNZXNzYWdlXG4gICAgfSlcbiAgICB0aGlzLl9kaWFnbm9zdGljTWFwLnNldChwYXRoLCBtZXNzYWdlcylcbiAgICB0aGlzLl9sc0RpYWdub3N0aWNNYXAuc2V0KHBhdGgsIGNvZGVNYXApXG4gICAgdGhpcy5faW5kaWVzLmZvckVhY2goKGkpID0+IGkuc2V0TWVzc2FnZXMocGF0aCwgbWVzc2FnZXMpKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogQ29udmVydCBhIHNpbmdsZSB7RGlhZ25vc3RpY30gcmVjZWl2ZWQgZnJvbSBhIGxhbmd1YWdlIHNlcnZlciBpbnRvIGEgc2luZ2xlIHtWMk1lc3NhZ2V9IGV4cGVjdGVkIGJ5IHRoZVxuICAgKiBMaW50ZXIgVjIgQVBJLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHBhdGggb2YgdGhlIGZpbGUgdGhlIGRpYWdub3N0aWMgYmVsb25ncyB0by5cbiAgICogQHBhcmFtIGRpYWdub3N0aWNzIEEge0RpYWdub3N0aWN9IG9iamVjdCByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gICAqIEByZXR1cm5zIEEge1YyTWVzc2FnZX0gZXF1aXZhbGVudCB0byB0aGUge0RpYWdub3N0aWN9IG9iamVjdCBzdXBwbGllZCBieSB0aGUgbGFuZ3VhZ2Ugc2VydmVyLlxuICAgKi9cbiAgcHVibGljIGRpYWdub3N0aWNUb1YyTWVzc2FnZShwYXRoOiBzdHJpbmcsIGRpYWdub3N0aWM6IERpYWdub3N0aWMpOiBsaW50ZXIuTWVzc2FnZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxvY2F0aW9uOiB7XG4gICAgICAgIGZpbGU6IHBhdGgsXG4gICAgICAgIHBvc2l0aW9uOiBDb252ZXJ0LmxzUmFuZ2VUb0F0b21SYW5nZShkaWFnbm9zdGljLnJhbmdlKSxcbiAgICAgIH0sXG4gICAgICBleGNlcnB0OiBkaWFnbm9zdGljLm1lc3NhZ2UsXG4gICAgICBsaW50ZXJOYW1lOiBkaWFnbm9zdGljLnNvdXJjZSxcbiAgICAgIHNldmVyaXR5OiBMaW50ZXJQdXNoVjJBZGFwdGVyLmRpYWdub3N0aWNTZXZlcml0eVRvU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSB8fCAtMSksXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogZ2V0IGRpYWdub3N0aWNzIGZvciB0aGUgZ2l2ZW4gbGludGVyIG1lc3NhZ2VzXG4gICAqXG4gICAqIEBwYXJhbSBsaW50ZXJNZXNzYWdlcyBBbiBhcnJheSBvZiBsaW50ZXIge1YyTWVzc2FnZX1cbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgTFMge0RpYWdub3N0aWNbXX1cbiAgICovXG4gIHB1YmxpYyBnZXRMU0RpYWdub3N0aWNzRm9yTWVzc2FnZXMobGludGVyTWVzc2FnZXM6IGxpbnRlci5NZXNzYWdlW10pOiBEaWFnbm9zdGljW10ge1xuICAgIHJldHVybiAoXG4gICAgICBsaW50ZXJNZXNzYWdlc1xuICAgICAgICAubWFwKHRoaXMuZ2V0TFNEaWFnbm9zdGljRm9yTWVzc2FnZSlcbiAgICAgICAgLy8gZmlsdGVyIG91dCB1bmRlZmluZWRcbiAgICAgICAgLmZpbHRlcigoZGlhZ25vc3RpYykgPT4gZGlhZ25vc3RpYyAhPT0gdW5kZWZpbmVkKSBhcyBEaWFnbm9zdGljW11cbiAgICApXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBHZXQgdGhlIHtEaWFnbm9zdGljfSB0aGF0IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gQmFzZSBMaW50ZXIgdjIge01lc3NhZ2V9LlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUge01lc3NhZ2V9IG9iamVjdCB0byBmZXRjaCB0aGUge0RpYWdub3N0aWN9IGZvci5cbiAgICogQHJldHVybnMgVGhlIGFzc29jaWF0ZWQge0RpYWdub3N0aWN9LlxuICAgKi9cbiAgcHVibGljIGdldExTRGlhZ25vc3RpY0Zvck1lc3NhZ2UobWVzc2FnZTogbGludGVyLk1lc3NhZ2UpOiBEaWFnbm9zdGljIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fbHNEaWFnbm9zdGljTWFwLmdldChtZXNzYWdlLmxvY2F0aW9uLmZpbGUpPy5nZXQoZ2V0TWVzc2FnZUtleShtZXNzYWdlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENvbnZlcnQgYSBkaWFnbm9zdGljIHNldmVyaXR5IG51bWJlciBvYnRhaW5lZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgaW50byB0aGUgdGV4dHVhbCBlcXVpdmFsZW50IGZvciBhXG4gICAqIExpbnRlciB7VjJNZXNzYWdlfS5cbiAgICpcbiAgICogQHBhcmFtIHNldmVyaXR5IEEgbnVtYmVyIHJlcHJlc2VudGluZyB0aGUgc2V2ZXJpdHkgb2YgdGhlIGRpYWdub3N0aWMuXG4gICAqIEByZXR1cm5zIEEgc3RyaW5nIG9mICdlcnJvcicsICd3YXJuaW5nJyBvciAnaW5mbycgZGVwZW5kaW5nIG9uIHRoZSBzZXZlcml0eS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZGlhZ25vc3RpY1NldmVyaXR5VG9TZXZlcml0eShzZXZlcml0eTogbnVtYmVyKTogXCJlcnJvclwiIHwgXCJ3YXJuaW5nXCIgfCBcImluZm9cIiB7XG4gICAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3I6XG4gICAgICAgIHJldHVybiBcImVycm9yXCJcbiAgICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5Lldhcm5pbmc6XG4gICAgICAgIHJldHVybiBcIndhcm5pbmdcIlxuICAgICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuSW5mb3JtYXRpb246XG4gICAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5IaW50OlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUHVibGljOiBDb252ZXJ0IGEgc2luZ2xlIHtEaWFnbm9zdGljfSByZWNlaXZlZCBmcm9tIGEgbGFuZ3VhZ2Ugc2VydmVyIGludG8gYSBzaW5nbGUge01lc3NhZ2V9IGV4cGVjdGVkIGJ5IHRoZSBMaW50ZXIgVjIgQVBJLlxuICpcbiAqIEBwYXJhbSBwYXRoIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgcGF0aCBvZiB0aGUgZmlsZSB0aGUgZGlhZ25vc3RpYyBiZWxvbmdzIHRvLlxuICogQHBhcmFtIGRpYWdub3N0aWNzIEEge0RpYWdub3N0aWN9IG9iamVjdCByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gKiBAcmV0dXJucyBBIHtNZXNzYWdlfSBlcXVpdmFsZW50IHRvIHRoZSB7RGlhZ25vc3RpY30gb2JqZWN0IHN1cHBsaWVkIGJ5IHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gKi9cbmZ1bmN0aW9uIGxzRGlhZ25vc3RpY1RvVjJNZXNzYWdlKHBhdGg6IHN0cmluZywgZGlhZ25vc3RpYzogRGlhZ25vc3RpYyk6IGxpbnRlci5NZXNzYWdlIHtcbiAgcmV0dXJuIHtcbiAgICBsb2NhdGlvbjoge1xuICAgICAgZmlsZTogcGF0aCxcbiAgICAgIHBvc2l0aW9uOiBDb252ZXJ0LmxzUmFuZ2VUb0F0b21SYW5nZShkaWFnbm9zdGljLnJhbmdlKSxcbiAgICB9LFxuICAgIHJlZmVyZW5jZTogcmVsYXRlZEluZm9ybWF0aW9uVG9SZWZlcmVuY2UoZGlhZ25vc3RpYy5yZWxhdGVkSW5mb3JtYXRpb24pLFxuICAgIHVybDogZGlhZ25vc3RpYy5jb2RlRGVzY3JpcHRpb24/LmhyZWYsXG4gICAgaWNvbjogaWNvbkZvckxTU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSA/PyBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3IpLFxuICAgIGV4Y2VycHQ6IGRpYWdub3N0aWMubWVzc2FnZSxcbiAgICBsaW50ZXJOYW1lOiBkaWFnbm9zdGljLnNvdXJjZSxcbiAgICBzZXZlcml0eTogbHNTZXZlcml0eVRvVjJNZXNzYWdlU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSA/PyBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3IpLFxuICAgIC8vIEJMT0NLRUQ6IG9uIHN0ZWVsYnJhaW4vbGludGVyIzE3MjJcbiAgICBzb2x1dGlvbnM6IHVuZGVmaW5lZCxcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnQgYSBzZXZlcml0eSBsZXZlbCBvZiBhbiBMU1Age0RpYWdub3N0aWN9IHRvIHRoYXQgb2YgYSBCYXNlIExpbnRlciB2MiB7TWVzc2FnZX0uIE5vdGU6IHRoaXMgY29udmVyc2lvbiBpcyBsb3NzeVxuICogZHVlIHRvIHRoZSB2MiBNZXNzYWdlIG5vdCBiZWluZyBhYmxlIHRvIHJlcHJlc2VudCBoaW50cy5cbiAqXG4gKiBAcGFyYW0gc2V2ZXJpdHkgQSBzZXZlcml0eSBsZXZlbCBvZiBvZiBhbiBMU1Age0RpYWdub3N0aWN9IHRvIGJlIGNvbnZlcnRlZC5cbiAqIEByZXR1cm5zIEEgc2V2ZXJpdHkgbGV2ZWwgYSBCYXNlIExpbnRlciB2MiB7TWVzc2FnZX0uXG4gKi9cbmZ1bmN0aW9uIGxzU2V2ZXJpdHlUb1YyTWVzc2FnZVNldmVyaXR5KHNldmVyaXR5OiBEaWFnbm9zdGljU2V2ZXJpdHkpOiBsaW50ZXIuTWVzc2FnZVtcInNldmVyaXR5XCJdIHtcbiAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkVycm9yOlxuICAgICAgcmV0dXJuIFwiZXJyb3JcIlxuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5Lldhcm5pbmc6XG4gICAgICByZXR1cm4gXCJ3YXJuaW5nXCJcbiAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5JbmZvcm1hdGlvbjpcbiAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5IaW50OlxuICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IEVycm9yKGBVbmV4cGVjdGVkIGRpYWdub3N0aWMgc2V2ZXJpdHkgJyR7c2V2ZXJpdHl9J2ApXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgZGlhZ25vc3RpYyBzZXZlcml0eSBudW1iZXIgb2J0YWluZWQgZnJvbSB0aGUgbGFuZ3VhZ2Ugc2VydmVyIGludG8gYW4gT2N0aWNvbiBpY29uLlxuICpcbiAqIEBwYXJhbSBzZXZlcml0eSBBIG51bWJlciByZXByZXNlbnRpbmcgdGhlIHNldmVyaXR5IG9mIHRoZSBkaWFnbm9zdGljLlxuICogQHJldHVybnMgQW4gT2N0aWNvbiBuYW1lLlxuICovXG5mdW5jdGlvbiBpY29uRm9yTFNTZXZlcml0eShzZXZlcml0eTogRGlhZ25vc3RpY1NldmVyaXR5KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkVycm9yOlxuICAgICAgcmV0dXJuIFwic3RvcFwiXG4gICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuV2FybmluZzpcbiAgICAgIHJldHVybiBcIndhcm5pbmdcIlxuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkluZm9ybWF0aW9uOlxuICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuSGludDpcbiAgICAgIHJldHVybiBcImxpZ2h0LWJ1bGJcIlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0IHRoZSByZWxhdGVkIGluZm9ybWF0aW9uIGZyb20gYSBkaWFnbm9zdGljIGludG8gYSByZWZlcmVuY2UgcG9pbnQgZm9yIGEgTGludGVyIHtWMk1lc3NhZ2V9LlxuICpcbiAqIEBwYXJhbSByZWxhdGVkSW5mbyBTZXZlcmFsIHJlbGF0ZWQgaW5mb3JtYXRpb24gb2JqZWN0cyAob25seSB0aGUgZmlyc3QgaXMgdXNlZCkuXG4gKiBAcmV0dXJucyBBIHZhbHVlIHRoYXQgaXMgc3VpdGFibGUgZm9yIHVzaW5nIGFzIHtWMk1lc3NhZ2V9LnJlZmVyZW5jZS5cbiAqL1xuZnVuY3Rpb24gcmVsYXRlZEluZm9ybWF0aW9uVG9SZWZlcmVuY2UoXG4gIHJlbGF0ZWRJbmZvOiBEaWFnbm9zdGljUmVsYXRlZEluZm9ybWF0aW9uW10gfCB1bmRlZmluZWRcbik6IGxpbnRlci5NZXNzYWdlW1wicmVmZXJlbmNlXCJdIHtcbiAgaWYgKHJlbGF0ZWRJbmZvID09PSB1bmRlZmluZWQgfHwgcmVsYXRlZEluZm8ubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgY29uc3QgbG9jYXRpb24gPSByZWxhdGVkSW5mb1swXS5sb2NhdGlvblxuICByZXR1cm4ge1xuICAgIGZpbGU6IENvbnZlcnQudXJpVG9QYXRoKGxvY2F0aW9uLnVyaSksXG4gICAgcG9zaXRpb246IENvbnZlcnQubHNSYW5nZVRvQXRvbVJhbmdlKGxvY2F0aW9uLnJhbmdlKS5zdGFydCxcbiAgfVxufVxuXG4vKipcbiAqIEdldCBhIHVuaXF1ZSBrZXkgZm9yIGEgTGludGVyIHYyIE1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBBIHtNZXNzYWdlfSBvYmplY3RcbiAqIEByZXR1cm5zICR7c3RyaW5nfSBhIHVuaXF1ZSBrZXlcbiAqL1xuZnVuY3Rpb24gZ2V0TWVzc2FnZUtleShtZXNzYWdlOiBsaW50ZXIuTWVzc2FnZSk6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgbWVzc2FnZS5rZXkgIT09IFwic3RyaW5nXCIpIHtcbiAgICB1cGRhdGVNZXNzYWdlS2V5KG1lc3NhZ2UpXG4gIH1cbiAgcmV0dXJuIG1lc3NhZ2Uua2V5IGFzIHN0cmluZyAvLyB1cGRhdGVNZXNzYWdlS2V5IGFkZHMgbWVzc2FnZS5rZXkgc3RyaW5nXG59XG5cbi8qKlxuICogQ29uc3RydWN0IGFuIHVuaXF1ZSBrZXkgZm9yIGEgTGludGVyIHYyIE1lc3NhZ2UgYW5kIHN0b3JlIGl0IGluIGBNZXNzYWdlLmtleWBcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBBIHtNZXNzYWdlfSBvYmplY3QgdG8gc2VyaWFsaXplLlxuICogQHJldHVybnMgJHtzdHJpbmd9IGEgdW5pcXVlIGtleVxuICovXG5mdW5jdGlvbiB1cGRhdGVNZXNzYWdlS2V5KG1lc3NhZ2U6IGxpbnRlci5NZXNzYWdlKTogdm9pZCB7XG4gIC8vIEZyb20gaHR0cHM6Ly9naXRodWIuY29tL3N0ZWVsYnJhaW4vbGludGVyL2Jsb2IvZmFkZDQ2MjkxNGVmMGE4ZWQ1YjczYTQ4OWY2NjJhOTM5M2JkYmU5Zi9saWIvaGVscGVycy50cyNMNTAtTDY0XG4gIGNvbnN0IHsgcmVmZXJlbmNlLCBsb2NhdGlvbiB9ID0gbWVzc2FnZVxuICBjb25zdCBuYW1lU3RyID0gYCRMSU5URVI6JHttZXNzYWdlLmxpbnRlck5hbWV9YFxuICBjb25zdCBsb2NhdGlvblN0ciA9IGAkTE9DQVRJT046JHtsb2NhdGlvbi5maWxlfSQke2xvY2F0aW9uLnBvc2l0aW9uLnN0YXJ0LnJvd30kJHtsb2NhdGlvbi5wb3NpdGlvbi5zdGFydC5jb2x1bW59JCR7bG9jYXRpb24ucG9zaXRpb24uZW5kLnJvd30kJHtsb2NhdGlvbi5wb3NpdGlvbi5lbmQuY29sdW1ufWBcbiAgY29uc3QgcmVmZXJlbmNlU3RyID0gcmVmZXJlbmNlXG4gICAgPyBgJFJFRkVSRU5DRToke3JlZmVyZW5jZS5maWxlfSQke1xuICAgICAgICByZWZlcmVuY2UucG9zaXRpb24gPyBgJHtyZWZlcmVuY2UucG9zaXRpb24ucm93fSQke3JlZmVyZW5jZS5wb3NpdGlvbi5jb2x1bW59YCA6IFwiXCJcbiAgICAgIH1gXG4gICAgOiBcIiRSRUZFUkVOQ0U6bnVsbFwiXG4gIGNvbnN0IGV4Y2VycHRTdHIgPSBgJEVYQ0VSUFQ6JHttZXNzYWdlLmV4Y2VycHR9YFxuICBjb25zdCBzZXZlcml0eVN0ciA9IGAkU0VWRVJJVFk6JHttZXNzYWdlLnNldmVyaXR5fWBcbiAgY29uc3QgaWNvblN0ciA9IG1lc3NhZ2UuaWNvbiA/IGAkSUNPTjoke21lc3NhZ2UuaWNvbn1gIDogXCIkSUNPTjpudWxsXCJcbiAgY29uc3QgdXJsU3RyID0gbWVzc2FnZS51cmwgPyBgJFVSTDoke21lc3NhZ2UudXJsfWAgOiBcIiRVUkw6bnVsbFwiXG4gIGNvbnN0IGRlc2NyaXB0aW9uU3RyID1cbiAgICB0eXBlb2YgbWVzc2FnZS5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGAkREVTQ1JJUFRJT046JHttZXNzYWdlLmRlc2NyaXB0aW9ufWAgOiBcIiRERVNDUklQVElPTjpudWxsXCJcbiAgbWVzc2FnZS5rZXkgPSBgJHtuYW1lU3RyfSR7bG9jYXRpb25TdHJ9JHtyZWZlcmVuY2VTdHJ9JHtleGNlcnB0U3RyfSR7c2V2ZXJpdHlTdHJ9JHtpY29uU3RyfSR7dXJsU3RyfSR7ZGVzY3JpcHRpb25TdHJ9YFxufVxuIl19
\No newline at end of file