tslint-language-service
Version:
tslint - language services
364 lines • 59.1 kB
JavaScript
"use strict";
const path = require("path");
const mockRequire = require("mock-require");
const TSLINT_ERROR_CODE = 100000;
function init(modules) {
const ts = modules.typescript;
let tslint = require('tslint');
let codeFixActions = new Map();
let registeredCodeFixes = false;
let configCache = {
filePath: null,
configuration: null,
isDefaultConfig: false,
configFilePath: null
};
// Work around the lack of API to register a CodeFix
function registerCodeFix(action) {
return ts.codefix.registerCodeFix(action);
}
if (!registeredCodeFixes && ts && ts.codefix) {
registerCodeFixes(registerCodeFix);
registeredCodeFixes = true;
}
function registerCodeFixes(registerCodeFix) {
// Code fix for that is used for all tslint fixes
registerCodeFix({
errorCodes: [TSLINT_ERROR_CODE],
getCodeActions: (_context) => {
return null;
}
});
}
function fixRelativeConfigFilePath(config, projectRoot) {
if (!config.configFile) {
return config;
}
if (path.isAbsolute(config.configFile)) {
return config;
}
config.configFile = path.join(projectRoot, config.configFile);
return config;
}
function create(info) {
info.project.projectService.logger.info("tslint-language-service loaded");
let config = fixRelativeConfigFilePath(info.config, info.project.getCurrentDirectory());
let configuration = null;
if (config.mockTypeScriptVersion) {
mockRequire('typescript', ts);
tslint = mockRequire.reRequire('tslint');
}
// Set up decorator
const proxy = Object.create(null);
const oldLS = info.languageService;
for (const k in oldLS) {
proxy[k] = function () {
return oldLS[k].apply(oldLS, arguments);
};
}
// key to identify a rule failure
function computeKey(start, end) {
return `[${start},${end}]`;
}
function makeDiagnostic(problem, file) {
let message = (problem.getRuleName() !== null)
? `${problem.getFailure()} (${problem.getRuleName()})`
: `${problem.getFailure()}`;
let category;
if (config.alwaysShowRuleFailuresAsWarnings === true) {
category = ts.DiagnosticCategory.Warning;
}
else if (problem.getRuleSeverity && problem.getRuleSeverity() === 'error') {
// tslint5 supports to assign severities to rules
category = ts.DiagnosticCategory.Error;
}
else {
category = ts.DiagnosticCategory.Warning;
}
let diagnostic = {
file: file,
start: problem.getStartPosition().getPosition(),
length: problem.getEndPosition().getPosition() - problem.getStartPosition().getPosition(),
messageText: message,
category: category,
source: 'tslint',
code: TSLINT_ERROR_CODE
};
return diagnostic;
}
/**
* Filter failures for the given document
*/
function filterProblemsForDocument(documentPath, failures) {
let normalizedPath = path.normalize(documentPath);
// we only show diagnostics targetting this open document, some tslint rule return diagnostics for other documents/files
let normalizedFiles = new Map();
return failures.filter(each => {
let fileName = each.getFileName();
if (!normalizedFiles.has(fileName)) {
normalizedFiles.set(fileName, path.normalize(fileName));
}
return normalizedFiles.get(fileName) === normalizedPath;
});
}
function replacementsAreEmpty(fix) {
// in tslint 4 a Fix has a replacement property witht the Replacements
if (fix.replacements) {
return fix.replacements.length === 0;
}
// tslint 5
if (Array.isArray(fix)) {
return fix.length === 0;
}
return false;
}
function recordCodeAction(problem, file) {
let fix = null;
// tslint can return a fix with an empty replacements array, these fixes are ignored
if (problem.getFix && problem.getFix() && !replacementsAreEmpty(problem.getFix())) {
fix = problem.getFix(); // createAutoFix(problem, document, problem.getFix());
}
if (!fix) {
return;
}
let documentAutoFixes = codeFixActions.get(file.fileName);
if (!documentAutoFixes) {
documentAutoFixes = new Map();
codeFixActions.set(file.fileName, documentAutoFixes);
}
documentAutoFixes.set(computeKey(problem.getStartPosition().getPosition(), problem.getEndPosition().getPosition()), problem);
}
function getConfigurationFailureMessage(err) {
let errorMessage = `unknown error`;
if (typeof err.message === 'string' || err.message instanceof String) {
errorMessage = err.message;
}
return `tslint: Cannot read tslint configuration - '${errorMessage}'`;
}
function getConfiguration(filePath, configFileName) {
if (configCache.configuration && configCache.filePath === filePath) {
return configCache.configuration;
}
let isDefaultConfig = false;
let configuration;
let configFilePath = null;
isDefaultConfig = tslint.Configuration.findConfigurationPath(configFileName, filePath) === undefined;
let configurationResult = tslint.Configuration.findConfiguration(configFileName, filePath);
// between tslint 4.0.1 and tslint 4.0.2 the attribute 'error' has been removed from IConfigurationLoadResult
// in 4.0.2 findConfiguration throws an exception as in version ^3.0.0
if (configurationResult.error) {
throw configurationResult.error;
}
configuration = configurationResult.results;
// In tslint version 5 the 'no-unused-variable' rules breaks the TypeScript language service plugin.
// See https://github.com/Microsoft/TypeScript/issues/15344
// Therefore we remove the rule from the configuration.
//
// In tslint 5 the rules are stored in a Map, in earlier versions they were stored in an Object
if (config.disableNoUnusedVariableRule === true || config.disableNoUnusedVariableRule === undefined) {
if (configuration.rules && configuration.rules instanceof Map) {
configuration.rules.delete('no-unused-variable');
}
if (configuration.jsRules && configuration.jsRules instanceof Map) {
configuration.jsRules.delete('no-unused-variable');
}
}
configFilePath = configurationResult.path;
configCache = {
filePath: filePath,
isDefaultConfig: isDefaultConfig,
configuration: configuration,
configFilePath: configFilePath
};
return configCache.configuration;
}
function captureWarnings(message) {
// TODO log to a user visible log and not only the TS-Server log
info.project.projectService.logger.info(`[tslint] ${message}`);
}
function convertReplacementToTextChange(repl) {
return {
newText: repl.text,
span: { start: repl.start, length: repl.length }
};
}
function getReplacements(fix) {
let replacements = null;
// in tslint4 a Fix has a replacement property with the Replacements
if (fix.replacements) {
// tslint4
replacements = fix.replacements;
}
else {
// in tslint 5 a Fix is a Replacement | Replacement[]
if (!Array.isArray(fix)) {
replacements = [fix];
}
else {
replacements = fix;
}
}
return replacements;
}
function addRuleFailureFix(fixes, problem, fileName) {
let fix = problem.getFix();
let replacements = getReplacements(fix);
fixes.push({
description: `Fix '${problem.getRuleName()}'`,
changes: [{
fileName: fileName,
textChanges: replacements.map(each => convertReplacementToTextChange(each))
}]
});
}
function addDisableRuleFix(fixes, problem, fileName, file) {
fixes.push({
description: `Disable rule '${problem.getRuleName()}'`,
changes: [{
fileName: fileName,
textChanges: [{
newText: `// tslint:disable-next-line:${problem.getRuleName()}\n`,
span: { start: file.getLineStarts()[problem.getStartPosition().getLineAndCharacter().line], length: 0 }
}]
}]
});
}
function addOpenConfigurationFix(fixes) {
// the Open Configuration code action is disabled since there is no specified API to open an editor
let openConfigFixEnabled = false;
if (openConfigFixEnabled && configCache && configCache.configFilePath) {
fixes.push({
description: `Open tslint.json`,
changes: [{
fileName: configCache.configFilePath,
textChanges: []
}]
});
}
}
function addAllAutoFixable(fixes, documentFixes, fileName) {
const allReplacements = getNonOverlappingReplacements(documentFixes);
fixes.push({
description: `Fix all auto-fixable tslint failures`,
changes: [{
fileName: fileName,
textChanges: allReplacements.map(each => convertReplacementToTextChange(each))
}]
});
}
function getReplacement(failure, at) {
return getReplacements(failure.getFix())[at];
}
function sortFailures(failures) {
// The failures.replacements are sorted by position, we sort on the position of the first replacement
return failures.sort((a, b) => {
return getReplacement(a, 0).start - getReplacement(b, 0).start;
});
}
function getNonOverlappingReplacements(documentFixes) {
function overlaps(a, b) {
return a.end >= b.start;
}
let sortedFailures = sortFailures([...documentFixes.values()]);
let nonOverlapping = [];
for (let i = 0; i < sortedFailures.length; i++) {
let replacements = getReplacements(sortedFailures[i].getFix());
if (i === 0 || !overlaps(nonOverlapping[nonOverlapping.length - 1], replacements[0])) {
nonOverlapping.push(...replacements);
}
}
return nonOverlapping;
}
proxy.getSemanticDiagnostics = (fileName) => {
const prior = oldLS.getSemanticDiagnostics(fileName);
if (config.supressWhileTypeErrorsPresent && prior.length > 0) {
return prior;
}
try {
info.project.projectService.logger.info(`Computing tslint semantic diagnostics...`);
if (codeFixActions.has(fileName)) {
codeFixActions.delete(fileName);
}
if (config.ignoreDefinitionFiles === true && fileName.endsWith('.d.ts')) {
return prior;
}
try {
configuration = getConfiguration(fileName, config.configFile);
}
catch (err) {
// TODO: show the reason for the configuration failure to the user and not only in the log
// https://github.com/Microsoft/TypeScript/issues/15913
info.project.projectService.logger.info(getConfigurationFailureMessage(err));
return prior;
}
let result;
// tslint writes warning messages using console.warn()
// capture the warnings and write them to the tslint plugin log
let warn = console.warn;
console.warn = captureWarnings;
try {
// TODO the types of the Program provided by tsserver libary are not compatible with the one provided by typescript
// casting away the type
let options = { fix: false };
let linter = new tslint.Linter(options, oldLS.getProgram());
linter.lint(fileName, "", configuration);
result = linter.getResult();
}
catch (err) {
let errorMessage = `unknown error`;
if (typeof err.message === 'string' || err.message instanceof String) {
errorMessage = err.message;
}
info.project.projectService.logger.info('tslint error ' + errorMessage);
return prior;
}
finally {
console.warn = warn;
}
if (result.failures.length > 0) {
const tslintProblems = filterProblemsForDocument(fileName, result.failures);
if (tslintProblems && tslintProblems.length) {
const file = oldLS.getProgram().getSourceFile(fileName);
const diagnostics = prior ? [...prior] : [];
tslintProblems.forEach(problem => {
diagnostics.push(makeDiagnostic(problem, file));
recordCodeAction(problem, file);
});
return diagnostics;
}
}
}
catch (e) {
info.project.projectService.logger.info(`tslint-language service error: ${e.toString()}`);
info.project.projectService.logger.info(`Stack trace: ${e.stack}`);
}
return prior;
};
proxy.getCodeFixesAtPosition = function (fileName, start, end, errorCodes, formatOptions) {
let prior = oldLS.getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions);
if (config.supressWhileTypeErrorsPresent && prior.length > 0) {
return prior;
}
info.project.projectService.logger.info("tslint-language-service getCodeFixes " + errorCodes[0]);
let documentFixes = codeFixActions.get(fileName);
if (documentFixes) {
const fixes = prior ? [...prior] : [];
let problem = documentFixes.get(computeKey(start, end));
if (problem) {
addRuleFailureFix(fixes, problem, fileName);
}
addAllAutoFixable(fixes, documentFixes, fileName);
if (problem) {
addOpenConfigurationFix(fixes);
addDisableRuleFix(fixes, problem, fileName, oldLS.getProgram().getSourceFile(fileName));
}
return fixes;
}
return prior;
};
return proxy;
}
return { create };
}
module.exports = init;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvaW5kZXgudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUVBLDZCQUE2QjtBQUM3Qiw0Q0FBNEM7QUFZNUMsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLENBQUM7QUFFakMsY0FBYyxPQUF5QztJQUNuRCxNQUFNLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxDQUFDO0lBQzlCLElBQUksTUFBTSxHQUFHLE9BQU8sQ0FBQyxRQUFRLENBQUMsQ0FBQztJQUUvQixJQUFJLGNBQWMsR0FBRyxJQUFJLEdBQUcsRUFBMkMsQ0FBQztJQUN4RSxJQUFJLG1CQUFtQixHQUFHLEtBQUssQ0FBQztJQUVoQyxJQUFJLFdBQVcsR0FBRztRQUNkLFFBQVEsRUFBVSxJQUFJO1FBQ3RCLGFBQWEsRUFBTyxJQUFJO1FBQ3hCLGVBQWUsRUFBRSxLQUFLO1FBQ3RCLGNBQWMsRUFBVSxJQUFJO0tBQy9CLENBQUM7SUFFRixvREFBb0Q7SUFDcEQseUJBQXlCLE1BQXVCO1FBQzVDLE1BQU0sQ0FBRSxFQUFVLENBQUMsT0FBTyxDQUFDLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztJQUN2RCxDQUFDO0lBRUQsRUFBRSxDQUFDLENBQUMsQ0FBQyxtQkFBbUIsSUFBSSxFQUFFLElBQUssRUFBVSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUM7UUFDcEQsaUJBQWlCLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDbkMsbUJBQW1CLEdBQUcsSUFBSSxDQUFDO0lBQy9CLENBQUM7SUFFRCwyQkFBMkIsZUFBa0Q7UUFDekUsaURBQWlEO1FBQ2pELGVBQWUsQ0FBQztZQUNaLFVBQVUsRUFBRSxDQUFDLGlCQUFpQixDQUFDO1lBQy9CLGNBQWMsRUFBRSxDQUFDLFFBQWEsRUFBRSxFQUFFO2dCQUM5QixNQUFNLENBQUMsSUFBSSxDQUFDO1lBQ2hCLENBQUM7U0FDSixDQUFDLENBQUM7SUFDUCxDQUFDO0lBRUQsbUNBQW1DLE1B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LENBQUMsQ0FBQztnQkFDNUYsQ0FBQztnQkFFRCxNQUFNLENBQUMsS0FBSyxDQUFDO1lBQ2pCLENBQUM7WUFFRCxNQUFNLENBQUMsS0FBSyxDQUFDO1FBQ2pCLENBQUMsQ0FBQztRQUNGLE1BQU0sQ0FBQyxLQUFLLENBQUM7SUFDakIsQ0FBQztJQUVELE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDO0FBQ3RCLENBQUM7QUFFRCxpQkFBUyxJQUFJLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyB0c19tb2R1bGUgZnJvbSBcIi4uL25vZGVfbW9kdWxlcy90eXBlc2NyaXB0L2xpYi90c3NlcnZlcmxpYnJhcnlcIjtcbmltcG9ydCAqIGFzIHRzbGludCBmcm9tICd0c2xpbnQnO1xuaW1wb3J0ICogYXMgcGF0aCBmcm9tICdwYXRoJztcbmltcG9ydCAqIGFzIG1vY2tSZXF1aXJlIGZyb20gJ21vY2stcmVxdWlyZSc7XG5cbi8vIFNldHRpbmdzIGZvciB0aGUgcGx1Z2luIHNlY3Rpb24gaW4gdHNjb25maWcuanNvblxuaW50ZXJmYWNlIFNldHRpbmdzIHtcbiAgICBhbHdheXNTaG93UnVsZUZhaWx1cmVzQXNXYXJuaW5ncz86IGJvb2xlYW47XG4gICAgaWdub3JlRGVmaW5pdGlvbkZpbGVzPzogYm9vbGVhbjtcbiAgICBjb25maWdGaWxlPzogc3RyaW5nO1xuICAgIGRpc2FibGVOb1VudXNlZFZhcmlhYmxlUnVsZT86IGJvb2xlYW4gIC8vIHN1cHBvcnQgdG8gZW5hYmxlL2Rpc2FibGUgdGhlIHdvcmthcm91bmQgZm9yIGh0dHBzOi8vZ2l0aHViLmNvbS9NaWNyb3NvZnQvVHlwZVNjcmlwdC9pc3N1ZXMvMTUzNDRcbiAgICBzdXByZXNzV2hpbGVUeXBlRXJyb3JzUHJlc2VudDogYm9vbGVhbjtcbiAgICBtb2NrVHlwZVNjcmlwdFZlcnNpb246IGJvb2xlYW47XG59XG5cbmNvbnN0IFRTTElOVF9FUlJPUl9DT0RFID0gMTAwMDAwO1xuXG5mdW5jdGlvbiBpbml0KG1vZHVsZXM6IHsgdHlwZXNjcmlwdDogdHlwZW9mIHRzX21vZHVsZSB9KSB7XG4gICAgY29uc3QgdHMgPSBtb2R1bGVzLnR5cGVzY3JpcHQ7XG4gICAgbGV0IHRzbGludCA9IHJlcXVpcmUoJ3RzbGludCcpO1xuXG4gICAgbGV0IGNvZGVGaXhBY3Rpb25zID0gbmV3IE1hcDxzdHJpbmcsIE1hcDxzdHJpbmcsIHRzbGludC5SdWxlRmFpbHVyZT4+KCk7XG4gICAgbGV0IHJlZ2lzdGVyZWRDb2RlRml4ZXMgPSBmYWxzZTtcblxuICAgIGxldCBjb25maWdDYWNoZSA9IHtcbiAgICAgICAgZmlsZVBhdGg6IDxzdHJpbmc+bnVsbCxcbiAgICAgICAgY29uZmlndXJhdGlvbjogPGFueT5udWxsLFxuICAgICAgICBpc0RlZmF1bHRDb25maWc6IGZhbHNlLFxuICAgICAgICBjb25maWdGaWxlUGF0aDogPHN0cmluZz5udWxsXG4gICAgfTtcblxuICAgIC8vIFdvcmsgYXJvdW5kIHRoZSBsYWNrIG9mIEFQSSB0byByZWdpc3RlciBhIENvZGVGaXhcbiAgICBmdW5jdGlvbiByZWdpc3RlckNvZGVGaXgoYWN0aW9uOiBjb2RlZml4LkNvZGVGaXgpIHtcbiAgICAgICAgcmV0dXJuICh0cyBhcyBhbnkpLmNvZGVmaXgucmVnaXN0ZXJDb2RlRml4KGFjdGlvbik7XG4gICAgfVxuXG4gICAgaWYgKCFyZWdpc3RlcmVkQ29kZUZpeGVzICYmIHRzICYmICh0cyBhcyBhbnkpLmNvZGVmaXgpIHtcbiAgICAgICAgcmVnaXN0ZXJDb2RlRml4ZXMocmVnaXN0ZXJDb2RlRml4KTtcbiAgICAgICAgcmVnaXN0ZXJlZENvZGVGaXhlcyA9IHRydWU7XG4gICAgfVxuXG4gICAgZnVuY3Rpb24gcmVnaXN0ZXJDb2RlRml4ZXMocmVnaXN0ZXJDb2RlRml4OiAoYWN0aW9uOiBjb2RlZml4LkNvZGVGaXgpID0+IHZvaWQpIHtcbiAgICAgICAgLy8gQ29kZSBmaXggZm9yIHRoYXQgaXMgdXNlZCBmb3IgYWxsIHRzbGludCBmaXhlc1xuICAgICAgICByZWdpc3RlckNvZGVGaXgoe1xuICAgICAgICAgICAgZXJyb3JDb2RlczogW1RTTElOVF9FUlJPUl9DT0RFXSxcbiAgICAgICAgICAgIGdldENvZGVBY3Rpb25zOiAoX2NvbnRleHQ6IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgIHJldHVybiBudWxsO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBmaXhSZWxhdGl2ZUNvbmZpZ0ZpbGVQYXRoKGNvbmZpZzogU2V0dGluZ3MsIHByb2plY3RSb290OiBzdHJpbmcpOiBTZXR0aW5ncyB7XG4gICAgICAgIGlmICghY29uZmlnLmNvbmZpZ0ZpbGUpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHBhdGguaXNBYnNvbHV0ZShjb25maWcuY29uZmlnRmlsZSkpIHtcbiAgICAgICAgICAgIHJldHVybiBjb25maWc7XG4gICAgICAgIH1cbiAgICAgICAgY29uZmlnLmNvbmZpZ0ZpbGUgPSBwYXRoLmpvaW4ocHJvamVjdFJvb3QsIGNvbmZpZy5jb25maWdGaWxlKTtcbiAgICAgICAgcmV0dXJuIGNvbmZpZztcbiAgICB9XG5cbiAgICBmdW5jdGlvbiBjcmVhdGUoaW5mbzogdHMuc2VydmVyLlBsdWdpbkNyZWF0ZUluZm8pIHtcbiAgICAgICAgaW5mby5wcm9qZWN0LnByb2plY3RTZXJ2aWNlLmxvZ2dlci5pbmZvKFwidHNsaW50LWxhbmd1YWdlLXNlcnZpY2UgbG9hZGVkXCIpO1xuICAgICAgICBsZXQgY29uZmlnOiBTZXR0aW5ncyA9IGZpeFJlbGF0aXZlQ29uZmlnRmlsZVBhdGgoaW5mby5jb25maWcsIGluZm8ucHJvamVjdC5nZXRDdXJyZW50RGlyZWN0b3J5KCkpO1xuICAgICAgICBsZXQgY29uZmlndXJhdGlvbjogdHNsaW50LkNvbmZpZ3VyYXRpb24uSUNvbmZpZ3VyYXRpb25GaWxlID0gbnVsbDtcblxuICAgICAgICBpZihjb25maWcubW9ja1R5cGVTY3JpcHRWZXJzaW9uKSB7XG4gICAgICAgICAgICBtb2NrUmVxdWlyZSgndHlwZXNjcmlwdCcsIHRzKTtcbiAgICAgICAgICAgIHRzbGludCA9IG1vY2tSZXF1aXJlLnJlUmVxdWlyZSgndHNsaW50Jyk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTZXQgdXAgZGVjb3JhdG9yXG4gICAgICAgIGNvbnN0IHByb3h5ID0gT2JqZWN0LmNyZWF0ZShudWxsKSBhcyB0cy5MYW5ndWFnZVNlcnZpY2U7XG4gICAgICAgIGNvbnN0IG9sZExTID0gaW5mby5sYW5ndWFnZVNlcnZpY2U7XG4gICAgICAgIGZvciAoY29uc3QgayBpbiBvbGRMUykge1xuICAgICAgICAgICAgKDxhbnk+cHJveHkpW2tdID0gZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHJldHVybiAoPGFueT5vbGRMUylba10uYXBwbHkob2xkTFMsIGFyZ3VtZW50cyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyBrZXkgdG8gaWRlbnRpZnkgYSBydWxlIGZhaWx1cmVcbiAgICAgICAgZnVuY3Rpb24gY29tcHV0ZUtleShzdGFydDogbnVtYmVyLCBlbmQ6IG51bWJlcik6IHN0cmluZyB7XG4gICAgICAgICAgICByZXR1cm4gYFske3N0YXJ0fSwke2VuZH1dYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIG1ha2VEaWFnbm9zdGljKHByb2JsZW06IHRzbGludC5SdWxlRmFpbHVyZSwgZmlsZTogdHMuU291cmNlRmlsZSk6IHRzLkRpYWdub3N0aWMge1xuICAgICAgICAgICAgbGV0IG1lc3NhZ2UgPSAocHJvYmxlbS5nZXRSdWxlTmFtZSgpICE9PSBudWxsKVxuICAgICAgICAgICAgICAgID8gYCR7cHJvYmxlbS5nZXRGYWlsdXJlKCl9ICgke3Byb2JsZW0uZ2V0UnVsZU5hbWUoKX0pYFxuICAgICAgICAgICAgICAgIDogYCR7cHJvYmxlbS5nZXRGYWlsdXJlKCl9YDtcblxuICAgICAgICAgICAgbGV0IGNhdGVnb3J5O1xuICAgICAgICAgICAgaWYgKGNvbmZpZy5hbHdheXNTaG93UnVsZUZhaWx1cmVzQXNXYXJuaW5ncyA9PT0gdHJ1ZSkge1xuICAgICAgICAgICAgICAgIGNhdGVnb3J5ID0gdHMuRGlhZ25vc3RpY0NhdGVnb3J5Lldhcm5pbmc7XG4gICAgICAgICAgICB9IGVsc2UgaWYgKCg8YW55PnByb2JsZW0pLmdldFJ1bGVTZXZlcml0eSAmJiAoPGFueT5wcm9ibGVtKS5nZXRSdWxlU2V2ZXJpdHkoKSA9PT0gJ2Vycm9yJykge1xuICAgICAgICAgICAgICAgIC8vIHRzbGludDUgc3VwcG9ydHMgdG8gYXNzaWduIHNldmVyaXRpZXMgdG8gcnVsZXNcbiAgICAgICAgICAgICAgICBjYXRlZ29yeSA9IHRzLkRpYWdub3N0aWNDYXRlZ29yeS5FcnJvcjtcbiAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgY2F0ZWdvcnkgPSB0cy5EaWFnbm9zdGljQ2F0ZWdvcnkuV2FybmluZztcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGRpYWdub3N0aWM6IHRzLkRpYWdub3N0aWMgPSB7XG4gICAgICAgICAgICAgICAgZmlsZTogZmlsZSxcbiAgICAgICAgICAgICAgICBzdGFydDogcHJvYmxlbS5nZXRTdGFydFBvc2l0aW9uKCkuZ2V0UG9zaXRpb24oKSxcbiAgICAgICAgICAgICAgICBsZW5ndGg6IHByb2JsZW0uZ2V0RW5kUG9zaXRpb24oKS5nZXRQb3NpdGlvbigpIC0gcHJvYmxlbS5nZXRTdGFydFBvc2l0aW9uKCkuZ2V0UG9zaXRpb24oKSxcbiAgICAgICAgICAgICAgICBtZXNzYWdlVGV4dDogbWVzc2FnZSxcbiAgICAgICAgICAgICAgICBjYXRlZ29yeTogY2F0ZWdvcnksXG4gICAgICAgICAgICAgICAgc291cmNlOiAndHNsaW50JyxcbiAgICAgICAgICAgICAgICBjb2RlOiBUU0xJTlRfRVJST1JfQ09ERVxuICAgICAgICAgICAgfTtcbiAgICAgICAgICAgIHJldHVybiBkaWFnbm9zdGljO1xuICAgICAgICB9XG5cbiAgICAgICAgLyoqXG4gICAgICAgICAqIEZpbHRlciBmYWlsdXJlcyBmb3IgdGhlIGdpdmVuIGRvY3VtZW50XG4gICAgICAgICAqL1xuICAgICAgICBmdW5jdGlvbiBmaWx0ZXJQcm9ibGVtc0ZvckRvY3VtZW50KGRvY3VtZW50UGF0aDogc3RyaW5nLCBmYWlsdXJlczogdHNsaW50LlJ1bGVGYWlsdXJlW10pOiB0c2xpbnQuUnVsZUZhaWx1cmVbXSB7XG4gICAgICAgICAgICBsZXQgbm9ybWFsaXplZFBhdGggPSBwYXRoLm5vcm1hbGl6ZShkb2N1bWVudFBhdGgpO1xuICAgICAgICAgICAgLy8gd2Ugb25seSBzaG93IGRpYWdub3N0aWNzIHRhcmdldHRpbmcgdGhpcyBvcGVuIGRvY3VtZW50LCBzb21lIHRzbGludCBydWxlIHJldHVybiBkaWFnbm9zdGljcyBmb3Igb3RoZXIgZG9jdW1lbnRzL2ZpbGVzXG4gICAgICAgICAgICBsZXQgbm9ybWFsaXplZEZpbGVzID0gbmV3IE1hcDxzdHJpbmcsIHN0cmluZz4oKTtcbiAgICAgICAgICAgIHJldHVybiBmYWlsdXJlcy5maWx0ZXIoZWFjaCA9PiB7XG4gICAgICAgICAgICAgICAgbGV0IGZpbGVOYW1lID0gZWFjaC5nZXRGaWxlTmFtZSgpO1xuICAgICAgICAgICAgICAgIGlmICghbm9ybWFsaXplZEZpbGVzLmhhcyhmaWxlTmFtZSkpIHtcbiAgICAgICAgICAgICAgICAgICAgbm9ybWFsaXplZEZpbGVzLnNldChmaWxlTmFtZSwgcGF0aC5ub3JtYWxpemUoZmlsZU5hbWUpKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuIG5vcm1hbGl6ZWRGaWxlcy5nZXQoZmlsZU5hbWUpID09PSBub3JtYWxpemVkUGF0aDtcbiAgICAgICAgICAgIH0pO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gcmVwbGFjZW1lbnRzQXJlRW1wdHkoZml4OiB0c2xpbnQuRml4KTogYm9vbGVhbiB7XG4gICAgICAgICAgICAvLyBpbiB0c2xpbnQgNCBhIEZpeCBoYXMgYSByZXBsYWNlbWVudCBwcm9wZXJ0eSB3aXRodCB0aGUgUmVwbGFjZW1lbnRzXG4gICAgICAgICAgICBpZiAoKDxhbnk+Zml4KS5yZXBsYWNlbWVudHMpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gKDxhbnk+Zml4KS5yZXBsYWNlbWVudHMubGVuZ3RoID09PSAwO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgLy8gdHNsaW50IDVcbiAgICAgICAgICAgIGlmIChBcnJheS5pc0FycmF5KGZpeCkpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gZml4Lmxlbmd0aCA9PT0gMDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIHJlY29yZENvZGVBY3Rpb24ocHJvYmxlbTogdHNsaW50LlJ1bGVGYWlsdXJlLCBmaWxlOiB0cy5Tb3VyY2VGaWxlKSB7XG4gICAgICAgICAgICBsZXQgZml4OiB0c2xpbnQuRml4ID0gbnVsbDtcblxuICAgICAgICAgICAgLy8gdHNsaW50IGNhbiByZXR1cm4gYSBmaXggd2l0aCBhbiBlbXB0eSByZXBsYWNlbWVudHMgYXJyYXksIHRoZXNlIGZpeGVzIGFyZSBpZ25vcmVkXG4gICAgICAgICAgICBpZiAocHJvYmxlbS5nZXRGaXggJiYgcHJvYmxlbS5nZXRGaXgoKSAmJiAhcmVwbGFjZW1lbnRzQXJlRW1wdHkocHJvYmxlbS5nZXRGaXgoKSkpIHsgLy8gdHNsaW50IGZpeGVzIGFyZSBub3QgYXZhaWxhYmxlIGluIHRzbGludCA8IDMuMTdcbiAgICAgICAgICAgICAgICBmaXggPSBwcm9ibGVtLmdldEZpeCgpOyAvLyBjcmVhdGVBdXRvRml4KHByb2JsZW0sIGRvY3VtZW50LCBwcm9ibGVtLmdldEZpeCgpKTtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKCFmaXgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGxldCBkb2N1bWVudEF1dG9GaXhlczogTWFwPHN0cmluZywgdHNsaW50LlJ1bGVGYWlsdXJlPiA9IGNvZGVGaXhBY3Rpb25zLmdldChmaWxlLmZpbGVOYW1lKTtcbiAgICAgICAgICAgIGlmICghZG9jdW1lbnRBdXRvRml4ZXMpIHtcbiAgICAgICAgICAgICAgICBkb2N1bWVudEF1dG9GaXhlcyA9IG5ldyBNYXA8c3RyaW5nLCB0c2xpbnQuUnVsZUZhaWx1cmU+KCk7XG4gICAgICAgICAgICAgICAgY29kZUZpeEFjdGlvbnMuc2V0KGZpbGUuZmlsZU5hbWUsIGRvY3VtZW50QXV0b0ZpeGVzKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRvY3VtZW50QXV0b0ZpeGVzLnNldChjb21wdXRlS2V5KHByb2JsZW0uZ2V0U3RhcnRQb3NpdGlvbigpLmdldFBvc2l0aW9uKCksIHByb2JsZW0uZ2V0RW5kUG9zaXRpb24oKS5nZXRQb3NpdGlvbigpKSwgcHJvYmxlbSk7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBnZXRDb25maWd1cmF0aW9uRmFpbHVyZU1lc3NhZ2UoZXJyOiBhbnkpOiBzdHJpbmcge1xuICAgICAgICAgICAgbGV0IGVycm9yTWVzc2FnZSA9IGB1bmtub3duIGVycm9yYDtcbiAgICAgICAgICAgIGlmICh0eXBlb2YgZXJyLm1lc3NhZ2UgPT09ICdzdHJpbmcnIHx8IGVyci5tZXNzYWdlIGluc3RhbmNlb2YgU3RyaW5nKSB7XG4gICAgICAgICAgICAgICAgZXJyb3JNZXNzYWdlID0gPHN0cmluZz5lcnIubWVzc2FnZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiBgdHNsaW50OiBDYW5ub3QgcmVhZCB0c2xpbnQgY29uZmlndXJhdGlvbiAtICcke2Vycm9yTWVzc2FnZX0nYDtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGdldENvbmZpZ3VyYXRpb24oZmlsZVBhdGg6IHN0cmluZywgY29uZmlnRmlsZU5hbWU6IHN0cmluZyk6IGFueSB7XG4gICAgICAgICAgICBpZiAoY29uZmlnQ2FjaGUuY29uZmlndXJhdGlvbiAmJiBjb25maWdDYWNoZS5maWxlUGF0aCA9PT0gZmlsZVBhdGgpIHtcbiAgICAgICAgICAgICAgICByZXR1cm4gY29uZmlnQ2FjaGUuY29uZmlndXJhdGlvbjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgbGV0IGlzRGVmYXVsdENvbmZpZyA9IGZhbHNlO1xuICAgICAgICAgICAgbGV0IGNvbmZpZ3VyYXRpb247XG4gICAgICAgICAgICBsZXQgY29uZmlnRmlsZVBhdGggPSBudWxsO1xuXG4gICAgICAgICAgICBpc0RlZmF1bHRDb25maWcgPSB0c2xpbnQuQ29uZmlndXJhdGlvbi5maW5kQ29uZmlndXJhdGlvblBhdGgoY29uZmlnRmlsZU5hbWUsIGZpbGVQYXRoKSA9PT0gdW5kZWZpbmVkO1xuICAgICAgICAgICAgbGV0IGNvbmZpZ3VyYXRpb25SZXN1bHQgPSB0c2xpbnQuQ29uZmlndXJhdGlvbi5maW5kQ29uZmlndXJhdGlvbihjb25maWdGaWxlTmFtZSwgZmlsZVBhdGgpO1xuXG4gICAgICAgICAgICAvLyBiZXR3ZWVuIHRzbGludCA0LjAuMSBhbmQgdHNsaW50IDQuMC4yIHRoZSBhdHRyaWJ1dGUgJ2Vycm9yJyBoYXMgYmVlbiByZW1vdmVkIGZyb20gSUNvbmZpZ3VyYXRpb25Mb2FkUmVzdWx0XG4gICAgICAgICAgICAvLyBpbiA0LjAuMiBmaW5kQ29uZmlndXJhdGlvbiB0aHJvd3MgYW4gZXhjZXB0aW9uIGFzIGluIHZlcnNpb24gXjMuMC4wXG4gICAgICAgICAgICBpZiAoKDxhbnk+Y29uZmlndXJhdGlvblJlc3VsdCkuZXJyb3IpIHtcbiAgICAgICAgICAgICAgICB0aHJvdyAoPGFueT5jb25maWd1cmF0aW9uUmVzdWx0KS5lcnJvcjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGNvbmZpZ3VyYXRpb24gPSBjb25maWd1cmF0aW9uUmVzdWx0LnJlc3VsdHM7XG5cbiAgICAgICAgICAgIC8vIEluIHRzbGludCB2ZXJzaW9uIDUgdGhlICduby11bnVzZWQtdmFyaWFibGUnIHJ1bGVzIGJyZWFrcyB0aGUgVHlwZVNjcmlwdCBsYW5ndWFnZSBzZXJ2aWNlIHBsdWdpbi5cbiAgICAgICAgICAgIC8vIFNlZSBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L1R5cGVTY3JpcHQvaXNzdWVzLzE1MzQ0XG4gICAgICAgICAgICAvLyBUaGVyZWZvcmUgd2UgcmVtb3ZlIHRoZSBydWxlIGZyb20gdGhlIGNvbmZpZ3VyYXRpb24uXG4gICAgICAgICAgICAvL1xuICAgICAgICAgICAgLy8gSW4gdHNsaW50IDUgdGhlIHJ1bGVzIGFyZSBzdG9yZWQgaW4gYSBNYXAsIGluIGVhcmxpZXIgdmVyc2lvbnMgdGhleSB3ZXJlIHN0b3JlZCBpbiBhbiBPYmplY3RcbiAgICAgICAgICAgIGlmIChjb25maWcuZGlzYWJsZU5vVW51c2VkVmFyaWFibGVSdWxlID09PSB0cnVlIHx8IGNvbmZpZy5kaXNhYmxlTm9VbnVzZWRWYXJpYWJsZVJ1bGUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICAgICAgICAgIGlmIChjb25maWd1cmF0aW9uLnJ1bGVzICYmIGNvbmZpZ3VyYXRpb24ucnVsZXMgaW5zdGFuY2VvZiBNYXApIHtcbiAgICAgICAgICAgICAgICAgICAgY29uZmlndXJhdGlvbi5ydWxlcy5kZWxldGUoJ25vLXVudXNlZC12YXJpYWJsZScpO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICBpZiAoY29uZmlndXJhdGlvbi5qc1J1bGVzICYmIGNvbmZpZ3VyYXRpb24uanNSdWxlcyBpbnN0YW5jZW9mIE1hcCkge1xuICAgICAgICAgICAgICAgICAgICBjb25maWd1cmF0aW9uLmpzUnVsZXMuZGVsZXRlKCduby11bnVzZWQtdmFyaWFibGUnKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG5cbiAgICAgICAgICAgIGNvbmZpZ0ZpbGVQYXRoID0gY29uZmlndXJhdGlvblJlc3VsdC5wYXRoO1xuXG4gICAgICAgICAgICBjb25maWdDYWNoZSA9IHtcbiAgICAgICAgICAgICAgICBmaWxlUGF0aDogZmlsZVBhdGgsXG4gICAgICAgICAgICAgICAgaXNEZWZhdWx0Q29uZmlnOiBpc0RlZmF1bHRDb25maWcsXG4gICAgICAgICAgICAgICAgY29uZmlndXJhdGlvbjogY29uZmlndXJhdGlvbixcbiAgICAgICAgICAgICAgICBjb25maWdGaWxlUGF0aDogY29uZmlnRmlsZVBhdGhcbiAgICAgICAgICAgIH07XG4gICAgICAgICAgICByZXR1cm4gY29uZmlnQ2FjaGUuY29uZmlndXJhdGlvbjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgZnVuY3Rpb24gY2FwdHVyZVdhcm5pbmdzKG1lc3NhZ2U/OiBhbnkpOiB2b2lkIHtcbiAgICAgICAgICAgIC8vIFRPRE8gbG9nIHRvIGEgdXNlciB2aXNpYmxlIGxvZyBhbmQgbm90IG9ubHkgdGhlIFRTLVNlcnZlciBsb2dcbiAgICAgICAgICAgIGluZm8ucHJvamVjdC5wcm9qZWN0U2VydmljZS5sb2dnZXIuaW5mbyhgW3RzbGludF0gJHttZXNzYWdlfWApO1xuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gY29udmVydFJlcGxhY2VtZW50VG9UZXh0Q2hhbmdlKHJlcGw6IHRzbGludC5SZXBsYWNlbWVudCk6IHRzLlRleHRDaGFuZ2Uge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgICBuZXdUZXh0OiByZXBsLnRleHQsXG4gICAgICAgICAgICAgICAgc3BhbjogeyBzdGFydDogcmVwbC5zdGFydCwgbGVuZ3RoOiByZXBsLmxlbmd0aCB9XG4gICAgICAgICAgICB9O1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICBmdW5jdGlvbiBnZXRSZXBsYWNlbWVudHMoZml4OiB0c2xpbnQuRml4KTogdHNsaW50LlJlcGxhY2VtZW50W117XG4gICAgICAgICAgICBsZXQgcmVwbGFjZW1lbnRzOiB0c2xpbnQuUmVwbGFjZW1lbnRbXSA9IG51bGw7XG4gICAgICAgICAgICAvLyBpbiB0c2xpbnQ0IGEgRml4IGhhcyBhIHJlcGxhY2VtZW50IHByb3BlcnR5IHdpdGggdGhlIFJlcGxhY2VtZW50c1xuICAgICAgICAgICAgaWYgKCg8YW55PmZpeCkucmVwbGFjZW1lbnRzKSB7XG4gICAgICAgICAgICAgICAgLy8gdHNsaW50NFxuICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50cyA9ICg8YW55PmZpeCkucmVwbGFjZW1lbnRzO1xuICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAvLyBpbiB0c2xpbnQgNSBhIEZpeCBpcyBhIFJlcGxhY2VtZW50IHwgUmVwbGFjZW1lbnRbXSAgICAgICAgICAgICAgICAgIFxuICAgICAgICAgICAgICAgIGlmICghQXJyYXkuaXNBcnJheShmaXgpKSB7XG4gICAgICAgICAgICAgICAgICAgIHJlcGxhY2VtZW50cyA9IFs8YW55PmZpeF07XG4gICAgICAgICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgcmVwbGFjZW1lbnRzID0gZml4O1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIHJldHVybiByZXBsYWNlbWVudHM7XG4gICAgICAgIH1cblxuICAgICAgICBmdW5jdGlvbiBhZGRSdWxlRmFpbHVyZUZpeChmaXhlczogdHNfbW9kdWxlLkNvZGVBY3Rpb25bXSwgcHJvYmxlbTogdHNsaW50LlJ1bGVGYWlsdXJlLCBmaWxlTmFtZTogc3RyaW5nKSB7XG4gICAgICAgICAgICBsZXQgZml4ID0gcHJvYmxlbS5nZXRGaXgoKTtcbiAgICAgICAgICAgIGxldCByZXBsYWNlbWVudHM6IHRzbGludC5SZXBsYWNlbWVudFtdID0gZ2V0UmVwbGFjZW1lbnRzKGZpeCk7XG5cbiAgICAgICAgICAgIGZpeGVzLnB1c2goe1xuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgRml4ICcke3Byb2JsZW0uZ2V0UnVsZU5hbWUoKX0nYCxcbiAgICAgICAgICAgICAgICBjaGFuZ2VzOiBbe1xuICAgICAgICAgICAgICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHRleHRDaGFuZ2VzOiByZXBsYWNlbWVudHMubWFwKGVhY2ggPT4gY29udmVydFJlcGxhY2VtZW50VG9UZXh0Q2hhbmdlKGVhY2gpKVxuICAgICAgICAgICAgICAgIH1dXG4gICAgICAgICAgICB9KTsgIFxuICAgICAgICB9XG5cbiAgICAgICAgZnVuY3Rpb24gYWRkRGlzYWJsZVJ1bGVGaXgoZml4ZXM6IHRzX21vZHVsZS5Db2RlQWN0aW9uW10sIHByb2JsZW06IHRzbGludC5SdWxlRmFpbHVyZSwgZmlsZU5hbWU6IHN0cmluZywgZmlsZTogdHNfbW9kdWxlLlNvdXJjZUZpbGUpIHtcbiAgICAgICAgICAgIGZpeGVzLnB1c2goe1xuICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgRGlzYWJsZSBydWxlICcke3Byb2JsZW0uZ2V0UnVsZU5hbWUoKX0nYCxcbiAgICAgICAgICAgICAgICBjaGFuZ2VzOiBbe1xuICAgICAgICAgICAgICAgICAgICBmaWxlTmFtZTogZmlsZU5hbWUsXG4gICAgICAgICAgICAgICAgICAgIHRleHRDaGFuZ2VzOiBbe1xuICAgICAgICAgICAgICAgICAgICAgICAgbmV3VGV4dDogYC8vIHRzbGludDpkaXNhYmxlLW5leHQtbGluZToke3Byb2JsZW0uZ2V0UnVsZU5hbWUoKX1cXG5gLFxuICAgICAgICAgICAgICAgICAgICAgICAgc3BhbjogeyBzdGFydDogZmlsZS5nZXRMaW5lU3RhcnRzKClbcHJvYmxlbS5nZXRTdGFydFBvc2l0aW9uKCkuZ2V0TGluZUFuZENoYXJhY3RlcigpLmxpbmVdLCBsZW5ndGg6IDAgfVxuICAgICAgICAgICAgICAgICAgICB9XVxuICAgICAgICAgICAgICAgIH1dXG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIGZ1bmN0aW9uIGFkZE9wZW5Db25maWd1cmF0aW9uRml4KGZpeGVzOiB0c19tb2R1bGUuQ29kZUFjdGlvbltdKSB7XG4gICAgICAgICAgICAvLyB0aGUgT3BlbiBDb25maWd1cmF0aW9uIGNvZGUgYWN0aW9uIGlzIGRpc2FibGVkIHNpbmNlIHRoZXJlIGlzIG5vIHNwZWNpZmllZCBBUEkgdG8gb3BlbiBhbiBlZGl0b3JcbiAgICAgICAgICAgIGxldCBvcGVuQ29uZmlnRml4RW5hYmxlZCA9IGZhbHNlO1xuICAgICAgICAgICAgaWYgKG9wZW5Db25maWdGaXhFbmFibGVkICYmIGNvbmZpZ0NhY2hlICYmIGNvbmZpZ0NhY2hlLmNvbmZpZ0ZpbGVQYXRoKSB7XG4gICAgICAgICAgICAgICAgZml4ZXMucHVzaCh7XG4gICAgICAgICAgICAgICAgICAgIGRlc2NyaXB0aW9uOiBgT3BlbiB0c2xpbnQuanNvbmAsXG4gICAgICAgICAgICAgICAgICAgIGNoYW5nZXM6IFt7XG4gICAgICAgICAgICAgICAgICAgICAgICBmaWxlTmFtZTogY29uZmlnQ2FjaGUuY29uZmlnRmlsZVBhdGgsXG4gICAgICAgICAgICAgICAgICAgICAgICB0ZXh0Q2hhbmdlczogW11cbiAgICAgICAgICAgICAgICAgICAgfV1cbiAgICAgICAgICAgICAgICB9KTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGZ