UNPKG

atom-languageclient

Version:
244 lines 32 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const convert_1 = require("../convert"); const languageclient_1 = require("../languageclient"); /** * Public: Listen to diagnostics messages from the language server and publish them to the user by way of the Linter * Push (Indie) v2 API provided by the Base Linter package. */ class LinterPushV2Adapter { /** * Public: Create a new {LinterPushV2Adapter} that will listen for diagnostics via the supplied {LanguageClientConnection}. * * @param connection A {LanguageClientConnection} to the language server that will provide diagnostics. */ constructor(connection) { /* * A map from file path calculated using the LS diagnostic uri to an array of linter messages {linter.Message[]} */ this._diagnosticMap = new Map(); /** * A map from file path {linter.Message["location"]["file"]} to a Map of all Message keys to Diagnostics * ${Map<linter.Message["key"], Diagnostic>} It has to be stored separately because a {Message} object cannot hold all * of the information that a {Diagnostic} provides, thus we store the original {Diagnostic} object. */ this._lsDiagnosticMap = new Map(); this._indies = new Set(); connection.onPublishDiagnostics(this.captureDiagnostics.bind(this)); } /** Dispose this adapter ensuring any resources are freed and events unhooked. */ dispose() { this.detachAll(); } /** * Public: Attach this {LinterPushV2Adapter} to a given {V2IndieDelegate} registry. * * @param indie A {V2IndieDelegate} that wants to receive messages. */ attach(indie) { this._indies.add(indie); this._diagnosticMap.forEach((value, key) => indie.setMessages(key, value)); indie.onDidDestroy(() => { this._indies.delete(indie); }); } /** Public: Remove all {V2IndieDelegate} registries attached to this adapter and clear them. */ detachAll() { this._indies.forEach((i) => i.clearMessages()); this._indies.clear(); } /** * Public: Capture the diagnostics sent from a langguage server, convert them to the Linter V2 format and forward them * on to any attached {V2IndieDelegate}s. * * @param params The {PublishDiagnosticsParams} received from the language server that should be captured and * forwarded on to any attached {V2IndieDelegate}s. */ captureDiagnostics(params) { const path = convert_1.default.uriToPath(params.uri); const codeMap = new Map(); const messages = params.diagnostics.map((d) => { const linterMessage = lsDiagnosticToV2Message(path, d); codeMap.set(getMessageKey(linterMessage), d); return linterMessage; }); this._diagnosticMap.set(path, messages); this._lsDiagnosticMap.set(path, codeMap); this._indies.forEach((i) => i.setMessages(path, messages)); } /** * Public: Convert a single {Diagnostic} received from a language server into a single {V2Message} expected by the * Linter V2 API. * * @param path A string representing the path of the file the diagnostic belongs to. * @param diagnostics A {Diagnostic} object received from the language server. * @returns A {V2Message} equivalent to the {Diagnostic} object supplied by the language server. */ diagnosticToV2Message(path, diagnostic) { return { location: { file: path, position: convert_1.default.lsRangeToAtomRange(diagnostic.range), }, excerpt: diagnostic.message, linterName: diagnostic.source, severity: LinterPushV2Adapter.diagnosticSeverityToSeverity(diagnostic.severity || -1), }; } /** * Public: get diagnostics for the given linter messages * * @param linterMessages An array of linter {V2Message} * @returns An array of LS {Diagnostic[]} */ getLSDiagnosticsForMessages(linterMessages) { return linterMessages .map(this.getLSDiagnosticForMessage) // filter out undefined .filter((diagnostic) => diagnostic !== undefined); } /** * Public: Get the {Diagnostic} that is associated with the given Base Linter v2 {Message}. * * @param message The {Message} object to fetch the {Diagnostic} for. * @returns The associated {Diagnostic}. */ getLSDiagnosticForMessage(message) { var _a; return (_a = this._lsDiagnosticMap.get(message.location.file)) === null || _a === void 0 ? void 0 : _a.get(getMessageKey(message)); } /** * Public: Convert a diagnostic severity number obtained from the language server into the textual equivalent for a * Linter {V2Message}. * * @param severity A number representing the severity of the diagnostic. * @returns A string of 'error', 'warning' or 'info' depending on the severity. */ static diagnosticSeverityToSeverity(severity) { switch (severity) { case languageclient_1.DiagnosticSeverity.Error: return "error"; case languageclient_1.DiagnosticSeverity.Warning: return "warning"; case languageclient_1.DiagnosticSeverity.Information: case languageclient_1.DiagnosticSeverity.Hint: default: return "info"; } } } exports.default = LinterPushV2Adapter; /** * Public: Convert a single {Diagnostic} received from a language server into a single {Message} expected by the Linter V2 API. * * @param path A string representing the path of the file the diagnostic belongs to. * @param diagnostics A {Diagnostic} object received from the language server. * @returns A {Message} equivalent to the {Diagnostic} object supplied by the language server. */ function lsDiagnosticToV2Message(path, diagnostic) { var _a, _b, _c; return { location: { file: path, position: convert_1.default.lsRangeToAtomRange(diagnostic.range), }, reference: relatedInformationToReference(diagnostic.relatedInformation), url: (_a = diagnostic.codeDescription) === null || _a === void 0 ? void 0 : _a.href, icon: iconForLSSeverity((_b = diagnostic.severity) !== null && _b !== void 0 ? _b : languageclient_1.DiagnosticSeverity.Error), excerpt: diagnostic.message, linterName: diagnostic.source, severity: lsSeverityToV2MessageSeverity((_c = diagnostic.severity) !== null && _c !== void 0 ? _c : languageclient_1.DiagnosticSeverity.Error), // BLOCKED: on steelbrain/linter#1722 solutions: undefined, }; } /** * Convert a severity level of an LSP {Diagnostic} to that of a Base Linter v2 {Message}. Note: this conversion is lossy * due to the v2 Message not being able to represent hints. * * @param severity A severity level of of an LSP {Diagnostic} to be converted. * @returns A severity level a Base Linter v2 {Message}. */ function lsSeverityToV2MessageSeverity(severity) { switch (severity) { case languageclient_1.DiagnosticSeverity.Error: return "error"; case languageclient_1.DiagnosticSeverity.Warning: return "warning"; case languageclient_1.DiagnosticSeverity.Information: case languageclient_1.DiagnosticSeverity.Hint: return "info"; default: throw Error(`Unexpected diagnostic severity '${severity}'`); } } /** * Convert a diagnostic severity number obtained from the language server into an Octicon icon. * * @param severity A number representing the severity of the diagnostic. * @returns An Octicon name. */ function iconForLSSeverity(severity) { switch (severity) { case languageclient_1.DiagnosticSeverity.Error: return "stop"; case languageclient_1.DiagnosticSeverity.Warning: return "warning"; case languageclient_1.DiagnosticSeverity.Information: return "info"; case languageclient_1.DiagnosticSeverity.Hint: return "light-bulb"; default: return undefined; } } /** * Convert the related information from a diagnostic into a reference point for a Linter {V2Message}. * * @param relatedInfo Several related information objects (only the first is used). * @returns A value that is suitable for using as {V2Message}.reference. */ function relatedInformationToReference(relatedInfo) { if (relatedInfo === undefined || relatedInfo.length === 0) { return undefined; } const location = relatedInfo[0].location; return { file: convert_1.default.uriToPath(location.uri), position: convert_1.default.lsRangeToAtomRange(location.range).start, }; } /** * Get a unique key for a Linter v2 Message * * @param message A {Message} object * @returns ${string} a unique key */ function getMessageKey(message) { if (typeof message.key !== "string") { updateMessageKey(message); } return message.key; // updateMessageKey adds message.key string } /** * Construct an unique key for a Linter v2 Message and store it in `Message.key` * * @param message A {Message} object to serialize. * @returns ${string} a unique key */ function updateMessageKey(message) { // From https://github.com/steelbrain/linter/blob/fadd462914ef0a8ed5b73a489f662a9393bdbe9f/lib/helpers.ts#L50-L64 const { reference, location } = message; const nameStr = `$LINTER:${message.linterName}`; const locationStr = `$LOCATION:${location.file}$${location.position.start.row}$${location.position.start.column}$${location.position.end.row}$${location.position.end.column}`; const referenceStr = reference ? `$REFERENCE:${reference.file}$${reference.position ? `${reference.position.row}$${reference.position.column}` : ""}` : "$REFERENCE:null"; const excerptStr = `$EXCERPT:${message.excerpt}`; const severityStr = `$SEVERITY:${message.severity}`; const iconStr = message.icon ? `$ICON:${message.icon}` : "$ICON:null"; const urlStr = message.url ? `$URL:${message.url}` : "$URL:null"; const descriptionStr = typeof message.description === "string" ? `$DESCRIPTION:${message.description}` : "$DESCRIPTION:null"; message.key = `${nameStr}${locationStr}${referenceStr}${excerptStr}${severityStr}${iconStr}${urlStr}${descriptionStr}`; } //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibGludGVyLXB1c2gtdjItYWRhcHRlci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL2xpYi9hZGFwdGVycy9saW50ZXItcHVzaC12Mi1hZGFwdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQ0Esd0NBQWdDO0FBQ2hDLHNEQU0wQjtBQUUxQjs7O0dBR0c7QUFDSCxNQUFxQixtQkFBbUI7SUFjdEM7Ozs7T0FJRztJQUNILFlBQVksVUFBb0M7UUFsQmhEOztXQUVHO1FBQ08sbUJBQWMsR0FBa0MsSUFBSSxHQUFHLEVBQUUsQ0FBQTtRQUNuRTs7OztXQUlHO1FBQ08scUJBQWdCLEdBQ3hCLElBQUksR0FBRyxFQUFFLENBQUE7UUFDRCxZQUFPLEdBQThCLElBQUksR0FBRyxFQUFFLENBQUE7UUFRdEQsVUFBVSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxrQkFBa0IsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUNyRSxDQUFDO0lBRUQsaUZBQWlGO0lBQzFFLE9BQU87UUFDWixJQUFJLENBQUMsU0FBUyxFQUFFLENBQUE7SUFDbEIsQ0FBQztJQUVEOzs7O09BSUc7SUFDSSxNQUFNLENBQUMsS0FBMkI7UUFDdkMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLEVBQUUsQ0FBQyxLQUFLLENBQUMsV0FBVyxDQUFDLEdBQUcsRUFBRSxLQUFLLENBQUMsQ0FBQyxDQUFBO1FBQzFFLEtBQUssQ0FBQyxZQUFZLENBQUMsR0FBRyxFQUFFO1lBQ3RCLElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzVCLENBQUMsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVELCtGQUErRjtJQUN4RixTQUFTO1FBQ2QsSUFBSSxDQUFDLE9BQU8sQ0FB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O0FBQ3hILENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBsaW50ZXIgZnJvbSBcImF0b20vbGludGVyXCJcbmltcG9ydCBDb252ZXJ0IGZyb20gXCIuLi9jb252ZXJ0XCJcbmltcG9ydCB7XG4gIERpYWdub3N0aWMsXG4gIERpYWdub3N0aWNTZXZlcml0eSxcbiAgRGlhZ25vc3RpY1JlbGF0ZWRJbmZvcm1hdGlvbixcbiAgTGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9uLFxuICBQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXMsXG59IGZyb20gXCIuLi9sYW5ndWFnZWNsaWVudFwiXG5cbi8qKlxuICogUHVibGljOiBMaXN0ZW4gdG8gZGlhZ25vc3RpY3MgbWVzc2FnZXMgZnJvbSB0aGUgbGFuZ3VhZ2Ugc2VydmVyIGFuZCBwdWJsaXNoIHRoZW0gdG8gdGhlIHVzZXIgYnkgd2F5IG9mIHRoZSBMaW50ZXJcbiAqIFB1c2ggKEluZGllKSB2MiBBUEkgcHJvdmlkZWQgYnkgdGhlIEJhc2UgTGludGVyIHBhY2thZ2UuXG4gKi9cbmV4cG9ydCBkZWZhdWx0IGNsYXNzIExpbnRlclB1c2hWMkFkYXB0ZXIge1xuICAvKlxuICAgKiBBIG1hcCBmcm9tIGZpbGUgcGF0aCBjYWxjdWxhdGVkIHVzaW5nIHRoZSBMUyBkaWFnbm9zdGljIHVyaSB0byBhbiBhcnJheSBvZiBsaW50ZXIgbWVzc2FnZXMge2xpbnRlci5NZXNzYWdlW119XG4gICAqL1xuICBwcm90ZWN0ZWQgX2RpYWdub3N0aWNNYXA6IE1hcDxzdHJpbmcsIGxpbnRlci5NZXNzYWdlW10+ID0gbmV3IE1hcCgpXG4gIC8qKlxuICAgKiBBIG1hcCBmcm9tIGZpbGUgcGF0aCB7bGludGVyLk1lc3NhZ2VbXCJsb2NhdGlvblwiXVtcImZpbGVcIl19IHRvIGEgTWFwIG9mIGFsbCBNZXNzYWdlIGtleXMgdG8gRGlhZ25vc3RpY3NcbiAgICogJHtNYXA8bGludGVyLk1lc3NhZ2VbXCJrZXlcIl0sIERpYWdub3N0aWM+fSBJdCBoYXMgdG8gYmUgc3RvcmVkIHNlcGFyYXRlbHkgYmVjYXVzZSBhIHtNZXNzYWdlfSBvYmplY3QgY2Fubm90IGhvbGQgYWxsXG4gICAqIG9mIHRoZSBpbmZvcm1hdGlvbiB0aGF0IGEge0RpYWdub3N0aWN9IHByb3ZpZGVzLCB0aHVzIHdlIHN0b3JlIHRoZSBvcmlnaW5hbCB7RGlhZ25vc3RpY30gb2JqZWN0LlxuICAgKi9cbiAgcHJvdGVjdGVkIF9sc0RpYWdub3N0aWNNYXA6IE1hcDxsaW50ZXIuTWVzc2FnZVtcImxvY2F0aW9uXCJdW1wiZmlsZVwiXSwgTWFwPGxpbnRlci5NZXNzYWdlW1wia2V5XCJdLCBEaWFnbm9zdGljPj4gPVxuICAgIG5ldyBNYXAoKVxuICBwcm90ZWN0ZWQgX2luZGllczogU2V0PGxpbnRlci5JbmRpZURlbGVnYXRlPiA9IG5ldyBTZXQoKVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENyZWF0ZSBhIG5ldyB7TGludGVyUHVzaFYyQWRhcHRlcn0gdGhhdCB3aWxsIGxpc3RlbiBmb3IgZGlhZ25vc3RpY3MgdmlhIHRoZSBzdXBwbGllZCB7TGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9ufS5cbiAgICpcbiAgICogQHBhcmFtIGNvbm5lY3Rpb24gQSB7TGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9ufSB0byB0aGUgbGFuZ3VhZ2Ugc2VydmVyIHRoYXQgd2lsbCBwcm92aWRlIGRpYWdub3N0aWNzLlxuICAgKi9cbiAgY29uc3RydWN0b3IoY29ubmVjdGlvbjogTGFuZ3VhZ2VDbGllbnRDb25uZWN0aW9uKSB7XG4gICAgY29ubmVjdGlvbi5vblB1Ymxpc2hEaWFnbm9zdGljcyh0aGlzLmNhcHR1cmVEaWFnbm9zdGljcy5iaW5kKHRoaXMpKVxuICB9XG5cbiAgLyoqIERpc3Bvc2UgdGhpcyBhZGFwdGVyIGVuc3VyaW5nIGFueSByZXNvdXJjZXMgYXJlIGZyZWVkIGFuZCBldmVudHMgdW5ob29rZWQuICovXG4gIHB1YmxpYyBkaXNwb3NlKCk6IHZvaWQge1xuICAgIHRoaXMuZGV0YWNoQWxsKClcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IEF0dGFjaCB0aGlzIHtMaW50ZXJQdXNoVjJBZGFwdGVyfSB0byBhIGdpdmVuIHtWMkluZGllRGVsZWdhdGV9IHJlZ2lzdHJ5LlxuICAgKlxuICAgKiBAcGFyYW0gaW5kaWUgQSB7VjJJbmRpZURlbGVnYXRlfSB0aGF0IHdhbnRzIHRvIHJlY2VpdmUgbWVzc2FnZXMuXG4gICAqL1xuICBwdWJsaWMgYXR0YWNoKGluZGllOiBsaW50ZXIuSW5kaWVEZWxlZ2F0ZSk6IHZvaWQge1xuICAgIHRoaXMuX2luZGllcy5hZGQoaW5kaWUpXG4gICAgdGhpcy5fZGlhZ25vc3RpY01hcC5mb3JFYWNoKCh2YWx1ZSwga2V5KSA9PiBpbmRpZS5zZXRNZXNzYWdlcyhrZXksIHZhbHVlKSlcbiAgICBpbmRpZS5vbkRpZERlc3Ryb3koKCkgPT4ge1xuICAgICAgdGhpcy5faW5kaWVzLmRlbGV0ZShpbmRpZSlcbiAgICB9KVxuICB9XG5cbiAgLyoqIFB1YmxpYzogUmVtb3ZlIGFsbCB7VjJJbmRpZURlbGVnYXRlfSByZWdpc3RyaWVzIGF0dGFjaGVkIHRvIHRoaXMgYWRhcHRlciBhbmQgY2xlYXIgdGhlbS4gKi9cbiAgcHVibGljIGRldGFjaEFsbCgpOiB2b2lkIHtcbiAgICB0aGlzLl9pbmRpZXMuZm9yRWFjaCgoaSkgPT4gaS5jbGVhck1lc3NhZ2VzKCkpXG4gICAgdGhpcy5faW5kaWVzLmNsZWFyKClcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENhcHR1cmUgdGhlIGRpYWdub3N0aWNzIHNlbnQgZnJvbSBhIGxhbmdndWFnZSBzZXJ2ZXIsIGNvbnZlcnQgdGhlbSB0byB0aGUgTGludGVyIFYyIGZvcm1hdCBhbmQgZm9yd2FyZCB0aGVtXG4gICAqIG9uIHRvIGFueSBhdHRhY2hlZCB7VjJJbmRpZURlbGVnYXRlfXMuXG4gICAqXG4gICAqIEBwYXJhbSBwYXJhbXMgVGhlIHtQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXN9IHJlY2VpdmVkIGZyb20gdGhlIGxhbmd1YWdlIHNlcnZlciB0aGF0IHNob3VsZCBiZSBjYXB0dXJlZCBhbmRcbiAgICogICBmb3J3YXJkZWQgb24gdG8gYW55IGF0dGFjaGVkIHtWMkluZGllRGVsZWdhdGV9cy5cbiAgICovXG4gIHB1YmxpYyBjYXB0dXJlRGlhZ25vc3RpY3MocGFyYW1zOiBQdWJsaXNoRGlhZ25vc3RpY3NQYXJhbXMpOiB2b2lkIHtcbiAgICBjb25zdCBwYXRoID0gQ29udmVydC51cmlUb1BhdGgocGFyYW1zLnVyaSlcbiAgICBjb25zdCBjb2RlTWFwID0gbmV3IE1hcDxzdHJpbmcsIERpYWdub3N0aWM+KClcbiAgICBjb25zdCBtZXNzYWdlcyA9IHBhcmFtcy5kaWFnbm9zdGljcy5tYXAoKGQpID0+IHtcbiAgICAgIGNvbnN0IGxpbnRlck1lc3NhZ2UgPSBsc0RpYWdub3N0aWNUb1YyTWVzc2FnZShwYXRoLCBkKVxuICAgICAgY29kZU1hcC5zZXQoZ2V0TWVzc2FnZUtleShsaW50ZXJNZXNzYWdlKSwgZClcbiAgICAgIHJldHVybiBsaW50ZXJNZXNzYWdlXG4gICAgfSlcbiAgICB0aGlzLl9kaWFnbm9zdGljTWFwLnNldChwYXRoLCBtZXNzYWdlcylcbiAgICB0aGlzLl9sc0RpYWdub3N0aWNNYXAuc2V0KHBhdGgsIGNvZGVNYXApXG4gICAgdGhpcy5faW5kaWVzLmZvckVhY2goKGkpID0+IGkuc2V0TWVzc2FnZXMocGF0aCwgbWVzc2FnZXMpKVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogQ29udmVydCBhIHNpbmdsZSB7RGlhZ25vc3RpY30gcmVjZWl2ZWQgZnJvbSBhIGxhbmd1YWdlIHNlcnZlciBpbnRvIGEgc2luZ2xlIHtWMk1lc3NhZ2V9IGV4cGVjdGVkIGJ5IHRoZVxuICAgKiBMaW50ZXIgVjIgQVBJLlxuICAgKlxuICAgKiBAcGFyYW0gcGF0aCBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIHBhdGggb2YgdGhlIGZpbGUgdGhlIGRpYWdub3N0aWMgYmVsb25ncyB0by5cbiAgICogQHBhcmFtIGRpYWdub3N0aWNzIEEge0RpYWdub3N0aWN9IG9iamVjdCByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gICAqIEByZXR1cm5zIEEge1YyTWVzc2FnZX0gZXF1aXZhbGVudCB0byB0aGUge0RpYWdub3N0aWN9IG9iamVjdCBzdXBwbGllZCBieSB0aGUgbGFuZ3VhZ2Ugc2VydmVyLlxuICAgKi9cbiAgcHVibGljIGRpYWdub3N0aWNUb1YyTWVzc2FnZShwYXRoOiBzdHJpbmcsIGRpYWdub3N0aWM6IERpYWdub3N0aWMpOiBsaW50ZXIuTWVzc2FnZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGxvY2F0aW9uOiB7XG4gICAgICAgIGZpbGU6IHBhdGgsXG4gICAgICAgIHBvc2l0aW9uOiBDb252ZXJ0LmxzUmFuZ2VUb0F0b21SYW5nZShkaWFnbm9zdGljLnJhbmdlKSxcbiAgICAgIH0sXG4gICAgICBleGNlcnB0OiBkaWFnbm9zdGljLm1lc3NhZ2UsXG4gICAgICBsaW50ZXJOYW1lOiBkaWFnbm9zdGljLnNvdXJjZSxcbiAgICAgIHNldmVyaXR5OiBMaW50ZXJQdXNoVjJBZGFwdGVyLmRpYWdub3N0aWNTZXZlcml0eVRvU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSB8fCAtMSksXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIFB1YmxpYzogZ2V0IGRpYWdub3N0aWNzIGZvciB0aGUgZ2l2ZW4gbGludGVyIG1lc3NhZ2VzXG4gICAqXG4gICAqIEBwYXJhbSBsaW50ZXJNZXNzYWdlcyBBbiBhcnJheSBvZiBsaW50ZXIge1YyTWVzc2FnZX1cbiAgICogQHJldHVybnMgQW4gYXJyYXkgb2YgTFMge0RpYWdub3N0aWNbXX1cbiAgICovXG4gIHB1YmxpYyBnZXRMU0RpYWdub3N0aWNzRm9yTWVzc2FnZXMobGludGVyTWVzc2FnZXM6IGxpbnRlci5NZXNzYWdlW10pOiBEaWFnbm9zdGljW10ge1xuICAgIHJldHVybiAoXG4gICAgICBsaW50ZXJNZXNzYWdlc1xuICAgICAgICAubWFwKHRoaXMuZ2V0TFNEaWFnbm9zdGljRm9yTWVzc2FnZSlcbiAgICAgICAgLy8gZmlsdGVyIG91dCB1bmRlZmluZWRcbiAgICAgICAgLmZpbHRlcigoZGlhZ25vc3RpYykgPT4gZGlhZ25vc3RpYyAhPT0gdW5kZWZpbmVkKSBhcyBEaWFnbm9zdGljW11cbiAgICApXG4gIH1cblxuICAvKipcbiAgICogUHVibGljOiBHZXQgdGhlIHtEaWFnbm9zdGljfSB0aGF0IGlzIGFzc29jaWF0ZWQgd2l0aCB0aGUgZ2l2ZW4gQmFzZSBMaW50ZXIgdjIge01lc3NhZ2V9LlxuICAgKlxuICAgKiBAcGFyYW0gbWVzc2FnZSBUaGUge01lc3NhZ2V9IG9iamVjdCB0byBmZXRjaCB0aGUge0RpYWdub3N0aWN9IGZvci5cbiAgICogQHJldHVybnMgVGhlIGFzc29jaWF0ZWQge0RpYWdub3N0aWN9LlxuICAgKi9cbiAgcHVibGljIGdldExTRGlhZ25vc3RpY0Zvck1lc3NhZ2UobWVzc2FnZTogbGludGVyLk1lc3NhZ2UpOiBEaWFnbm9zdGljIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5fbHNEaWFnbm9zdGljTWFwLmdldChtZXNzYWdlLmxvY2F0aW9uLmZpbGUpPy5nZXQoZ2V0TWVzc2FnZUtleShtZXNzYWdlKSlcbiAgfVxuXG4gIC8qKlxuICAgKiBQdWJsaWM6IENvbnZlcnQgYSBkaWFnbm9zdGljIHNldmVyaXR5IG51bWJlciBvYnRhaW5lZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIgaW50byB0aGUgdGV4dHVhbCBlcXVpdmFsZW50IGZvciBhXG4gICAqIExpbnRlciB7VjJNZXNzYWdlfS5cbiAgICpcbiAgICogQHBhcmFtIHNldmVyaXR5IEEgbnVtYmVyIHJlcHJlc2VudGluZyB0aGUgc2V2ZXJpdHkgb2YgdGhlIGRpYWdub3N0aWMuXG4gICAqIEByZXR1cm5zIEEgc3RyaW5nIG9mICdlcnJvcicsICd3YXJuaW5nJyBvciAnaW5mbycgZGVwZW5kaW5nIG9uIHRoZSBzZXZlcml0eS5cbiAgICovXG4gIHB1YmxpYyBzdGF0aWMgZGlhZ25vc3RpY1NldmVyaXR5VG9TZXZlcml0eShzZXZlcml0eTogbnVtYmVyKTogXCJlcnJvclwiIHwgXCJ3YXJuaW5nXCIgfCBcImluZm9cIiB7XG4gICAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3I6XG4gICAgICAgIHJldHVybiBcImVycm9yXCJcbiAgICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5Lldhcm5pbmc6XG4gICAgICAgIHJldHVybiBcIndhcm5pbmdcIlxuICAgICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuSW5mb3JtYXRpb246XG4gICAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5IaW50OlxuICAgICAgZGVmYXVsdDpcbiAgICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgfVxuICB9XG59XG5cbi8qKlxuICogUHVibGljOiBDb252ZXJ0IGEgc2luZ2xlIHtEaWFnbm9zdGljfSByZWNlaXZlZCBmcm9tIGEgbGFuZ3VhZ2Ugc2VydmVyIGludG8gYSBzaW5nbGUge01lc3NhZ2V9IGV4cGVjdGVkIGJ5IHRoZSBMaW50ZXIgVjIgQVBJLlxuICpcbiAqIEBwYXJhbSBwYXRoIEEgc3RyaW5nIHJlcHJlc2VudGluZyB0aGUgcGF0aCBvZiB0aGUgZmlsZSB0aGUgZGlhZ25vc3RpYyBiZWxvbmdzIHRvLlxuICogQHBhcmFtIGRpYWdub3N0aWNzIEEge0RpYWdub3N0aWN9IG9iamVjdCByZWNlaXZlZCBmcm9tIHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gKiBAcmV0dXJucyBBIHtNZXNzYWdlfSBlcXVpdmFsZW50IHRvIHRoZSB7RGlhZ25vc3RpY30gb2JqZWN0IHN1cHBsaWVkIGJ5IHRoZSBsYW5ndWFnZSBzZXJ2ZXIuXG4gKi9cbmZ1bmN0aW9uIGxzRGlhZ25vc3RpY1RvVjJNZXNzYWdlKHBhdGg6IHN0cmluZywgZGlhZ25vc3RpYzogRGlhZ25vc3RpYyk6IGxpbnRlci5NZXNzYWdlIHtcbiAgcmV0dXJuIHtcbiAgICBsb2NhdGlvbjoge1xuICAgICAgZmlsZTogcGF0aCxcbiAgICAgIHBvc2l0aW9uOiBDb252ZXJ0LmxzUmFuZ2VUb0F0b21SYW5nZShkaWFnbm9zdGljLnJhbmdlKSxcbiAgICB9LFxuICAgIHJlZmVyZW5jZTogcmVsYXRlZEluZm9ybWF0aW9uVG9SZWZlcmVuY2UoZGlhZ25vc3RpYy5yZWxhdGVkSW5mb3JtYXRpb24pLFxuICAgIHVybDogZGlhZ25vc3RpYy5jb2RlRGVzY3JpcHRpb24/LmhyZWYsXG4gICAgaWNvbjogaWNvbkZvckxTU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSA/PyBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3IpLFxuICAgIGV4Y2VycHQ6IGRpYWdub3N0aWMubWVzc2FnZSxcbiAgICBsaW50ZXJOYW1lOiBkaWFnbm9zdGljLnNvdXJjZSxcbiAgICBzZXZlcml0eTogbHNTZXZlcml0eVRvVjJNZXNzYWdlU2V2ZXJpdHkoZGlhZ25vc3RpYy5zZXZlcml0eSA/PyBEaWFnbm9zdGljU2V2ZXJpdHkuRXJyb3IpLFxuICAgIC8vIEJMT0NLRUQ6IG9uIHN0ZWVsYnJhaW4vbGludGVyIzE3MjJcbiAgICBzb2x1dGlvbnM6IHVuZGVmaW5lZCxcbiAgfVxufVxuXG4vKipcbiAqIENvbnZlcnQgYSBzZXZlcml0eSBsZXZlbCBvZiBhbiBMU1Age0RpYWdub3N0aWN9IHRvIHRoYXQgb2YgYSBCYXNlIExpbnRlciB2MiB7TWVzc2FnZX0uIE5vdGU6IHRoaXMgY29udmVyc2lvbiBpcyBsb3NzeVxuICogZHVlIHRvIHRoZSB2MiBNZXNzYWdlIG5vdCBiZWluZyBhYmxlIHRvIHJlcHJlc2VudCBoaW50cy5cbiAqXG4gKiBAcGFyYW0gc2V2ZXJpdHkgQSBzZXZlcml0eSBsZXZlbCBvZiBvZiBhbiBMU1Age0RpYWdub3N0aWN9IHRvIGJlIGNvbnZlcnRlZC5cbiAqIEByZXR1cm5zIEEgc2V2ZXJpdHkgbGV2ZWwgYSBCYXNlIExpbnRlciB2MiB7TWVzc2FnZX0uXG4gKi9cbmZ1bmN0aW9uIGxzU2V2ZXJpdHlUb1YyTWVzc2FnZVNldmVyaXR5KHNldmVyaXR5OiBEaWFnbm9zdGljU2V2ZXJpdHkpOiBsaW50ZXIuTWVzc2FnZVtcInNldmVyaXR5XCJdIHtcbiAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkVycm9yOlxuICAgICAgcmV0dXJuIFwiZXJyb3JcIlxuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5Lldhcm5pbmc6XG4gICAgICByZXR1cm4gXCJ3YXJuaW5nXCJcbiAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5JbmZvcm1hdGlvbjpcbiAgICBjYXNlIERpYWdub3N0aWNTZXZlcml0eS5IaW50OlxuICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgZGVmYXVsdDpcbiAgICAgIHRocm93IEVycm9yKGBVbmV4cGVjdGVkIGRpYWdub3N0aWMgc2V2ZXJpdHkgJyR7c2V2ZXJpdHl9J2ApXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0IGEgZGlhZ25vc3RpYyBzZXZlcml0eSBudW1iZXIgb2J0YWluZWQgZnJvbSB0aGUgbGFuZ3VhZ2Ugc2VydmVyIGludG8gYW4gT2N0aWNvbiBpY29uLlxuICpcbiAqIEBwYXJhbSBzZXZlcml0eSBBIG51bWJlciByZXByZXNlbnRpbmcgdGhlIHNldmVyaXR5IG9mIHRoZSBkaWFnbm9zdGljLlxuICogQHJldHVybnMgQW4gT2N0aWNvbiBuYW1lLlxuICovXG5mdW5jdGlvbiBpY29uRm9yTFNTZXZlcml0eShzZXZlcml0eTogRGlhZ25vc3RpY1NldmVyaXR5KTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgc3dpdGNoIChzZXZlcml0eSkge1xuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkVycm9yOlxuICAgICAgcmV0dXJuIFwic3RvcFwiXG4gICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuV2FybmluZzpcbiAgICAgIHJldHVybiBcIndhcm5pbmdcIlxuICAgIGNhc2UgRGlhZ25vc3RpY1NldmVyaXR5LkluZm9ybWF0aW9uOlxuICAgICAgcmV0dXJuIFwiaW5mb1wiXG4gICAgY2FzZSBEaWFnbm9zdGljU2V2ZXJpdHkuSGludDpcbiAgICAgIHJldHVybiBcImxpZ2h0LWJ1bGJcIlxuICAgIGRlZmF1bHQ6XG4gICAgICByZXR1cm4gdW5kZWZpbmVkXG4gIH1cbn1cblxuLyoqXG4gKiBDb252ZXJ0IHRoZSByZWxhdGVkIGluZm9ybWF0aW9uIGZyb20gYSBkaWFnbm9zdGljIGludG8gYSByZWZlcmVuY2UgcG9pbnQgZm9yIGEgTGludGVyIHtWMk1lc3NhZ2V9LlxuICpcbiAqIEBwYXJhbSByZWxhdGVkSW5mbyBTZXZlcmFsIHJlbGF0ZWQgaW5mb3JtYXRpb24gb2JqZWN0cyAob25seSB0aGUgZmlyc3QgaXMgdXNlZCkuXG4gKiBAcmV0dXJucyBBIHZhbHVlIHRoYXQgaXMgc3VpdGFibGUgZm9yIHVzaW5nIGFzIHtWMk1lc3NhZ2V9LnJlZmVyZW5jZS5cbiAqL1xuZnVuY3Rpb24gcmVsYXRlZEluZm9ybWF0aW9uVG9SZWZlcmVuY2UoXG4gIHJlbGF0ZWRJbmZvOiBEaWFnbm9zdGljUmVsYXRlZEluZm9ybWF0aW9uW10gfCB1bmRlZmluZWRcbik6IGxpbnRlci5NZXNzYWdlW1wicmVmZXJlbmNlXCJdIHtcbiAgaWYgKHJlbGF0ZWRJbmZvID09PSB1bmRlZmluZWQgfHwgcmVsYXRlZEluZm8ubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIHVuZGVmaW5lZFxuICB9XG5cbiAgY29uc3QgbG9jYXRpb24gPSByZWxhdGVkSW5mb1swXS5sb2NhdGlvblxuICByZXR1cm4ge1xuICAgIGZpbGU6IENvbnZlcnQudXJpVG9QYXRoKGxvY2F0aW9uLnVyaSksXG4gICAgcG9zaXRpb246IENvbnZlcnQubHNSYW5nZVRvQXRvbVJhbmdlKGxvY2F0aW9uLnJhbmdlKS5zdGFydCxcbiAgfVxufVxuXG4vKipcbiAqIEdldCBhIHVuaXF1ZSBrZXkgZm9yIGEgTGludGVyIHYyIE1lc3NhZ2VcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBBIHtNZXNzYWdlfSBvYmplY3RcbiAqIEByZXR1cm5zICR7c3RyaW5nfSBhIHVuaXF1ZSBrZXlcbiAqL1xuZnVuY3Rpb24gZ2V0TWVzc2FnZUtleShtZXNzYWdlOiBsaW50ZXIuTWVzc2FnZSk6IHN0cmluZyB7XG4gIGlmICh0eXBlb2YgbWVzc2FnZS5rZXkgIT09IFwic3RyaW5nXCIpIHtcbiAgICB1cGRhdGVNZXNzYWdlS2V5KG1lc3NhZ2UpXG4gIH1cbiAgcmV0dXJuIG1lc3NhZ2Uua2V5IGFzIHN0cmluZyAvLyB1cGRhdGVNZXNzYWdlS2V5IGFkZHMgbWVzc2FnZS5rZXkgc3RyaW5nXG59XG5cbi8qKlxuICogQ29uc3RydWN0IGFuIHVuaXF1ZSBrZXkgZm9yIGEgTGludGVyIHYyIE1lc3NhZ2UgYW5kIHN0b3JlIGl0IGluIGBNZXNzYWdlLmtleWBcbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSBBIHtNZXNzYWdlfSBvYmplY3QgdG8gc2VyaWFsaXplLlxuICogQHJldHVybnMgJHtzdHJpbmd9IGEgdW5pcXVlIGtleVxuICovXG5mdW5jdGlvbiB1cGRhdGVNZXNzYWdlS2V5KG1lc3NhZ2U6IGxpbnRlci5NZXNzYWdlKTogdm9pZCB7XG4gIC8vIEZyb20gaHR0cHM6Ly9naXRodWIuY29tL3N0ZWVsYnJhaW4vbGludGVyL2Jsb2IvZmFkZDQ2MjkxNGVmMGE4ZWQ1YjczYTQ4OWY2NjJhOTM5M2JkYmU5Zi9saWIvaGVscGVycy50cyNMNTAtTDY0XG4gIGNvbnN0IHsgcmVmZXJlbmNlLCBsb2NhdGlvbiB9ID0gbWVzc2FnZVxuICBjb25zdCBuYW1lU3RyID0gYCRMSU5URVI6JHttZXNzYWdlLmxpbnRlck5hbWV9YFxuICBjb25zdCBsb2NhdGlvblN0ciA9IGAkTE9DQVRJT046JHtsb2NhdGlvbi5maWxlfSQke2xvY2F0aW9uLnBvc2l0aW9uLnN0YXJ0LnJvd30kJHtsb2NhdGlvbi5wb3NpdGlvbi5zdGFydC5jb2x1bW59JCR7bG9jYXRpb24ucG9zaXRpb24uZW5kLnJvd30kJHtsb2NhdGlvbi5wb3NpdGlvbi5lbmQuY29sdW1ufWBcbiAgY29uc3QgcmVmZXJlbmNlU3RyID0gcmVmZXJlbmNlXG4gICAgPyBgJFJFRkVSRU5DRToke3JlZmVyZW5jZS5maWxlfSQke1xuICAgICAgICByZWZlcmVuY2UucG9zaXRpb24gPyBgJHtyZWZlcmVuY2UucG9zaXRpb24ucm93fSQke3JlZmVyZW5jZS5wb3NpdGlvbi5jb2x1bW59YCA6IFwiXCJcbiAgICAgIH1gXG4gICAgOiBcIiRSRUZFUkVOQ0U6bnVsbFwiXG4gIGNvbnN0IGV4Y2VycHRTdHIgPSBgJEVYQ0VSUFQ6JHttZXNzYWdlLmV4Y2VycHR9YFxuICBjb25zdCBzZXZlcml0eVN0ciA9IGAkU0VWRVJJVFk6JHttZXNzYWdlLnNldmVyaXR5fWBcbiAgY29uc3QgaWNvblN0ciA9IG1lc3NhZ2UuaWNvbiA/IGAkSUNPTjoke21lc3NhZ2UuaWNvbn1gIDogXCIkSUNPTjpudWxsXCJcbiAgY29uc3QgdXJsU3RyID0gbWVzc2FnZS51cmwgPyBgJFVSTDoke21lc3NhZ2UudXJsfWAgOiBcIiRVUkw6bnVsbFwiXG4gIGNvbnN0IGRlc2NyaXB0aW9uU3RyID1cbiAgICB0eXBlb2YgbWVzc2FnZS5kZXNjcmlwdGlvbiA9PT0gXCJzdHJpbmdcIiA/IGAkREVTQ1JJUFRJT046JHttZXNzYWdlLmRlc2NyaXB0aW9ufWAgOiBcIiRERVNDUklQVElPTjpudWxsXCJcbiAgbWVzc2FnZS5rZXkgPSBgJHtuYW1lU3RyfSR7bG9jYXRpb25TdHJ9JHtyZWZlcmVuY2VTdHJ9JHtleGNlcnB0U3RyfSR7c2V2ZXJpdHlTdHJ9JHtpY29uU3RyfSR7dXJsU3RyfSR7ZGVzY3JpcHRpb25TdHJ9YFxufVxuIl19