eslint-plugin-import-order-autofix
Version:
eslint-plugin-import/order autofixing.
314 lines (258 loc) • 35.2 kB
JavaScript
;
var _os = require('os');
var _importType = require('../core/importType');
var _importType2 = _interopRequireDefault(_importType);
var _staticRequire = require('../core/staticRequire');
var _staticRequire2 = _interopRequireDefault(_staticRequire);
var _babelEslint = require('babel-eslint');
var _babelEslint2 = _interopRequireDefault(_babelEslint);
var _jscodeshift = require('jscodeshift');
var _jscodeshift2 = _interopRequireDefault(_jscodeshift);
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
require('./../core/add-types');
const j = _jscodeshift2.default.withParser(_babelEslint2.default);
_jscodeshift2.default.types.Type.def('ExperimentalSpreadProperty').bases('Node');
_jscodeshift2.default.types.Type.def('ExperimentalRestProperty').bases('Node');
_jscodeshift2.default.types.finalize();
const defaultGroups = ['builtin', 'external', 'parent', 'sibling', 'index'];
// REPORTING
function reverse(array) {
return array.map(function (v) {
return {
name: v.name,
rank: -v.rank,
node: v.node
};
}).reverse();
}
function findOutOfOrder(imported) {
if (imported.length === 0) {
return [];
}
let maxSeenRankNode = imported[0];
return imported.filter(function (importedModule) {
const res = importedModule.rank < maxSeenRankNode.rank;
if (maxSeenRankNode.rank < importedModule.rank) {
maxSeenRankNode = importedModule;
}
return res;
});
}
function findRootNode(j, root, node) {
let result = null;
root.find(j.Node).filter(p => p.node === node).forEach(p => {
let parent = p;
while (parent.parent != null && parent.parent.value.body == null) {
parent = parent.parent;
}
result = parent;
});
return result;
}
function fixOutOfOrder(context, firstNode, secondNode, order) {
const sourceCode = context.getSourceCode();
const root = j(sourceCode.ast);
const firstRoot = findRootNode(j, root, firstNode.node);
const secondRoot = findRootNode(j, root, secondNode.node);
const newCode = sourceCode.getText(secondRoot.node);
const msg = () => `\`${ secondNode.name }\` import should occur ${ order }` + ` import \`${ firstNode.name }\``;
if (order === 'before') {
context.report({
node: secondNode.node,
message: msg(),
fix: fixer => fixer.insertTextBefore(firstRoot.node, newCode)
});
} else if (order === 'after') {
context.report({
node: secondNode.node,
message: msg(),
fix: fixer => fixer.insertTextAfter(firstRoot.node, newCode)
});
}
context.report({
node: secondNode.node,
message: msg(),
fix: fixer => fixer.remove(secondRoot.node)
});
}
function reportOutOfOrder(context, imported, outOfOrder, order) {
outOfOrder.forEach(function (imp) {
const found = imported.find(function hasHigherRank(importedItem) {
return importedItem.rank > imp.rank;
});
fixOutOfOrder(context, found, imp, order);
});
}
function makeOutOfOrderReport(context, imported) {
const outOfOrder = findOutOfOrder(imported);
if (!outOfOrder.length) {
return;
}
// There are things to report. Try to minimize the number of reported errors.
const reversedImported = reverse(imported);
const reversedOrder = findOutOfOrder(reversedImported);
if (reversedOrder.length < outOfOrder.length) {
reportOutOfOrder(context, reversedImported, reversedOrder, 'after');
return;
}
reportOutOfOrder(context, imported, outOfOrder, 'before');
}
// DETECTING
function computeRank(context, ranks, name, type) {
return ranks[(0, _importType2.default)(name, context)] + (type === 'import' ? 0 : 100);
}
function registerNode(context, node, name, type, ranks, imported) {
const rank = computeRank(context, ranks, name, type);
if (rank !== -1) {
imported.push({ name, rank, node });
}
}
function isInVariableDeclarator(node) {
return node && (node.type === 'VariableDeclarator' || isInVariableDeclarator(node.parent));
}
const types = ['builtin', 'external', 'internal', 'parent', 'sibling', 'index'];
// Creates an object with type-rank pairs.
// Example: { index: 0, sibling: 1, parent: 1, external: 1, builtin: 2, internal: 2 }
// Will throw an error if it contains a type that does not exist, or has a duplicate
function convertGroupsToRanks(groups) {
const rankObject = groups.reduce(function (res, group, index) {
if (typeof group === 'string') {
group = [group];
}
group.forEach(function (groupItem) {
if (types.indexOf(groupItem) === -1) {
throw new Error('Incorrect configuration of the rule: Unknown type `' + JSON.stringify(groupItem) + '`');
}
if (res[groupItem] !== undefined) {
throw new Error('Incorrect configuration of the rule: `' + groupItem + '` is duplicated');
}
res[groupItem] = index;
});
return res;
}, {});
const omittedTypes = types.filter(function (type) {
return rankObject[type] === undefined;
});
return omittedTypes.reduce(function (res, type) {
res[type] = groups.length;
return res;
}, rankObject);
}
function fixNewLineAfterImport(context, previousImport) {
const root = j(context.getSourceCode().ast);
const prevRoot = findRootNode(j, root, previousImport.node);
return fixer => fixer.insertTextAfter(prevRoot.node, _os.EOL);
}
function removeNewLineAfterImport(context, currentImport, previousImport) {
const root = j(context.getSourceCode().ast);
const prevRoot = findRootNode(j, root, previousImport.node);
const currRoot = findRootNode(j, root, currentImport.node);
return fixer => fixer.removeRange([prevRoot.node.range[1] + 1, currRoot.node.range[0]]);
}
function makeNewlinesBetweenReport(context, imported, newlinesBetweenImports) {
const getNumberOfEmptyLinesBetween = (currentImport, previousImport) => {
const linesBetweenImports = context.getSourceCode().lines.slice(previousImport.node.loc.end.line, currentImport.node.loc.start.line - 1);
return linesBetweenImports.filter(line => !line.trim().length).length;
};
let previousImport = imported[0];
imported.slice(1).forEach(function (currentImport) {
const emptyLinesCount = getNumberOfEmptyLinesBetween(currentImport, previousImport);
if (newlinesBetweenImports === 'always') {
if (currentImport.rank !== previousImport.rank && emptyLinesCount === 0) {
context.report({
node: previousImport.node,
message: 'There should be at least one empty line between import groups',
fix: fixNewLineAfterImport(context, previousImport)
});
} else if (currentImport.rank === previousImport.rank && emptyLinesCount > 0) {
context.report({
node: previousImport.node,
message: 'There should be no empty line within import group',
fix: removeNewLineAfterImport(context, currentImport, previousImport)
});
}
} else if (emptyLinesCount > 0) {
context.report({
node: previousImport.node,
message: 'There should be no empty line between import groups',
fix: removeNewLineAfterImport(context, currentImport, previousImport)
});
}
previousImport = currentImport;
});
}
module.exports = {
meta: {
docs: {},
fixable: 'code',
schema: [{
type: 'object',
properties: {
groups: {
type: 'array'
},
'newlines-between': {
enum: ['ignore', 'always', 'never']
}
},
additionalProperties: false
}]
},
create: function importOrderRule(context) {
const options = context.options[0] || {};
const newlinesBetweenImports = options['newlines-between'] || 'ignore';
let ranks;
try {
ranks = convertGroupsToRanks(options.groups || defaultGroups);
} catch (error) {
// Malformed configuration
return {
Program: function (node) {
context.report(node, error.message);
}
};
}
let imported = [];
let level = 0;
function incrementLevel() {
level++;
}
function decrementLevel() {
level--;
}
return {
ImportDeclaration: function handleImports(node) {
if (node.specifiers.length) {
// Ignoring unassigned imports
const name = node.source.value;
registerNode(context, node, name, 'import', ranks, imported);
}
},
CallExpression: function handleRequires(node) {
if (level !== 0 || !(0, _staticRequire2.default)(node) || !isInVariableDeclarator(node.parent)) {
return;
}
const name = node.arguments[0].value;
registerNode(context, node, name, 'require', ranks, imported);
},
'Program:exit': function reportAndReset() {
makeOutOfOrderReport(context, imported);
if (newlinesBetweenImports !== 'ignore') {
makeNewlinesBetweenReport(context, imported, newlinesBetweenImports);
}
imported = [];
},
FunctionDeclaration: incrementLevel,
FunctionExpression: incrementLevel,
ArrowFunctionExpression: incrementLevel,
BlockStatement: incrementLevel,
ObjectExpression: incrementLevel,
'FunctionDeclaration:exit': decrementLevel,
'FunctionExpression:exit': decrementLevel,
'ArrowFunctionExpression:exit': decrementLevel,
'BlockStatement:exit': decrementLevel,
'ObjectExpression:exit': decrementLevel
};
}
};
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInJ1bGVzL29yZGVyLmpzIl0sIm5hbWVzIjpbInJlcXVpcmUiLCJqIiwid2l0aFBhcnNlciIsInR5cGVzIiwiVHlwZSIsImRlZiIsImJhc2VzIiwiZmluYWxpemUiLCJkZWZhdWx0R3JvdXBzIiwicmV2ZXJzZSIsImFycmF5IiwibWFwIiwidiIsIm5hbWUiLCJyYW5rIiwibm9kZSIsImZpbmRPdXRPZk9yZGVyIiwiaW1wb3J0ZWQiLCJsZW5ndGgiLCJtYXhTZWVuUmFua05vZGUiLCJmaWx0ZXIiLCJpbXBvcnRlZE1vZHVsZSIsInJlcyIsImZpbmRSb290Tm9kZSIsInJvb3QiLCJyZXN1bHQiLCJmaW5kIiwiTm9kZSIsInAiLCJmb3JFYWNoIiwicGFyZW50IiwidmFsdWUiLCJib2R5IiwiZml4T3V0T2ZPcmRlciIsImNvbnRleHQiLCJmaXJzdE5vZGUiLCJzZWNvbmROb2RlIiwib3JkZXIiLCJzb3VyY2VDb2RlIiwiZ2V0U291cmNlQ29kZSIsImFzdCIsImZpcnN0Um9vdCIsInNlY29uZFJvb3QiLCJuZXdDb2RlIiwiZ2V0VGV4dCIsIm1zZyIsInJlcG9ydCIsIm1lc3NhZ2UiLCJmaXgiLCJmaXhlciIsImluc2VydFRleHRCZWZvcmUiLCJpbnNlcnRUZXh0QWZ0ZXIiLCJyZW1vdmUiLCJyZXBvcnRPdXRPZk9yZGVyIiwib3V0T2ZPcmRlciIsImltcCIsImZvdW5kIiwiaGFzSGlnaGVyUmFuayIsImltcG9ydGVkSXRlbSIsIm1ha2VPdXRPZk9yZGVyUmVwb3J0IiwicmV2ZXJzZWRJbXBvcnRlZCIsInJldmVyc2VkT3JkZXIiLCJjb21wdXRlUmFuayIsInJhbmtzIiwidHlwZSIsInJlZ2lzdGVyTm9kZSIsInB1c2giLCJpc0luVmFyaWFibGVEZWNsYXJhdG9yIiwiY29udmVydEdyb3Vwc1RvUmFua3MiLCJncm91cHMiLCJyYW5rT2JqZWN0IiwicmVkdWNlIiwiZ3JvdXAiLCJpbmRleCIsImdyb3VwSXRlbSIsImluZGV4T2YiLCJFcnJvciIsIkpTT04iLCJzdHJpbmdpZnkiLCJ1bmRlZmluZWQiLCJvbWl0dGVkVHlwZXMiLCJmaXhOZXdMaW5lQWZ0ZXJJbXBvcnQiLCJwcmV2aW91c0ltcG9ydCIsInByZXZSb290IiwicmVtb3ZlTmV3TGluZUFmdGVySW1wb3J0IiwiY3VycmVudEltcG9ydCIsImN1cnJSb290IiwicmVtb3ZlUmFuZ2UiLCJyYW5nZSIsIm1ha2VOZXdsaW5lc0JldHdlZW5SZXBvcnQiLCJuZXdsaW5lc0JldHdlZW5JbXBvcnRzIiwiZ2V0TnVtYmVyT2ZFbXB0eUxpbmVzQmV0d2VlbiIsImxpbmVzQmV0d2VlbkltcG9ydHMiLCJsaW5lcyIsInNsaWNlIiwibG9jIiwiZW5kIiwibGluZSIsInN0YXJ0IiwidHJpbSIsImVtcHR5TGluZXNDb3VudCIsIm1vZHVsZSIsImV4cG9ydHMiLCJtZXRhIiwiZG9jcyIsImZpeGFibGUiLCJzY2hlbWEiLCJwcm9wZXJ0aWVzIiwiZW51bSIsImFkZGl0aW9uYWxQcm9wZXJ0aWVzIiwiY3JlYXRlIiwiaW1wb3J0T3JkZXJSdWxlIiwib3B0aW9ucyIsImVycm9yIiwiUHJvZ3JhbSIsImxldmVsIiwiaW5jcmVtZW50TGV2ZWwiLCJkZWNyZW1lbnRMZXZlbCIsIkltcG9ydERlY2xhcmF0aW9uIiwiaGFuZGxlSW1wb3J0cyIsInNwZWNpZmllcnMiLCJzb3VyY2UiLCJDYWxsRXhwcmVzc2lvbiIsImhhbmRsZVJlcXVpcmVzIiwiYXJndW1lbnRzIiwicmVwb3J0QW5kUmVzZXQiLCJGdW5jdGlvbkRlY2xhcmF0aW9uIiwiRnVuY3Rpb25FeHByZXNzaW9uIiwiQXJyb3dGdW5jdGlvbkV4cHJlc3Npb24iLCJCbG9ja1N0YXRlbWVudCIsIk9iamVjdEV4cHJlc3Npb24iXSwibWFwcGluZ3MiOiJBQUFBOztBQUlBOztBQUNBOzs7O0FBQ0E7Ozs7QUFDQTs7OztBQUVBOzs7Ozs7QUFQQUEsUUFBUSxxQkFBUjs7QUFRQSxNQUFNQyxJQUFJLHNCQUFZQyxVQUFaLHVCQUFWOztBQUVBLHNCQUFZQyxLQUFaLENBQWtCQyxJQUFsQixDQUF1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QTVCLEVBQWtDLFFBQWxDLEVBQTRDa0QsS0FBNUMsRUFBbUQ5QyxRQUFuRDtBQUNEO0FBQ0YsT0FOSTtBQU9MeUcsc0JBQWdCLFNBQVNDLGNBQVQsQ0FBd0I1RyxJQUF4QixFQUE4QjtBQUM1QyxZQUFJb0csVUFBVSxDQUFWLElBQWUsQ0FBQyw2QkFBZ0JwRyxJQUFoQixDQUFoQixJQUF5QyxDQUFDb0QsdUJBQXVCcEQsS0FBS2UsTUFBNUIsQ0FBOUMsRUFBbUY7QUFDakY7QUFDRDtBQUNELGNBQU1qQixPQUFPRSxLQUFLNkcsU0FBTCxDQUFlLENBQWYsRUFBa0I3RixLQUEvQjtBQUNBa0MscUJBQWEvQixPQUFiLEVBQXNCbkIsSUFBdEIsRUFBNEJGLElBQTVCLEVBQWtDLFNBQWxDLEVBQTZDa0QsS0FBN0MsRUFBb0Q5QyxRQUFwRDtBQUNELE9BYkk7QUFjTCxzQkFBZ0IsU0FBUzRHLGNBQVQsR0FBMEI7QUFDeENsRSw2QkFBcUJ6QixPQUFyQixFQUE4QmpCLFFBQTlCOztBQUVBLFlBQUl5RSwyQkFBMkIsUUFBL0IsRUFBeUM7QUFDdkNELG9DQUEwQnZELE9BQTFCLEVBQW1DakIsUUFBbkMsRUFBNkN5RSxzQkFBN0M7QUFDRDs7QUFFRHpFLG1CQUFXLEVBQVg7QUFDRCxPQXRCSTtBQXVCTDZHLDJCQUFxQlYsY0F2QmhCO0FBd0JMVywwQkFBb0JYLGNBeEJmO0FBeUJMWSwrQkFBeUJaLGNBekJwQjtBQTBCTGEsc0JBQWdCYixjQTFCWDtBQTJCTGMsd0JBQWtCZCxjQTNCYjtBQTRCTCxrQ0FBNEJDLGNBNUJ2QjtBQTZCTCxpQ0FBMkJBLGNBN0J0QjtBQThCTCxzQ0FBZ0NBLGNBOUIzQjtBQStCTCw2QkFBdUJBLGNBL0JsQjtBQWdDTCwrQkFBeUJBO0FBaENwQixLQUFQO0FBa0NEO0FBL0VjLENBQWpCIiwiZmlsZSI6InJ1bGVzL29yZGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiJ3VzZSBzdHJpY3QnXG5cbnJlcXVpcmUoJy4vLi4vY29yZS9hZGQtdHlwZXMnKTtcblxuaW1wb3J0IHsgRU9MIH0gZnJvbSAnb3MnO1xuaW1wb3J0IGltcG9ydFR5cGUgZnJvbSAnLi4vY29yZS9pbXBvcnRUeXBlJ1xuaW1wb3J0IGlzU3RhdGljUmVxdWlyZSBmcm9tICcuLi9jb3JlL3N0YXRpY1JlcXVpcmUnXG5pbXBvcnQgcGFyc2VyIGZyb20gJ2JhYmVsLWVzbGludCc7XG5cbmltcG9ydCBqc2NvZGVzaGlmdCBmcm9tICdqc2NvZGVzaGlmdCc7XG5jb25zdCBqID0ganNjb2Rlc2hpZnQud2l0aFBhcnNlcihwYXJzZXIpO1xuXG5qc2NvZGVzaGlmdC50eXBlcy5UeXBlLmRlZignRXhwZXJpbWVudGFsU3ByZWFkUHJvcGVydHknKS5iYXNlcygnTm9kZScpO1xuanNjb2Rlc2hpZnQudHlwZXMuVHlwZS5kZWYoJ0V4cGVyaW1lbnRhbFJlc3RQcm9wZXJ0eScpLmJhc2VzKCdOb2RlJyk7XG5cbmpzY29kZXNoaWZ0LnR5cGVzLmZpbmFsaXplKCk7XG5cbmNvbnN0IGRlZmF1bHRHcm91cHMgPSBbJ2J1aWx0aW4nLCAnZXh0ZXJuYWwnLCAncGFyZW50JywgJ3NpYmxpbmcnLCAnaW5kZXgnXVxuXG4vLyBSRVBPUlRJTkdcblxuZnVuY3Rpb24gcmV2ZXJzZShhcnJheSkge1xuICByZXR1cm4gYXJyYXkubWFwKGZ1bmN0aW9uICh2KSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWU6IHYubmFtZSxcbiAgICAgIHJhbms6IC12LnJhbmssXG4gICAgICBub2RlOiB2Lm5vZGUsXG4gICAgfVxuICB9KS5yZXZlcnNlKClcbn1cblxuZnVuY3Rpb24gZmluZE91dE9mT3JkZXIoaW1wb3J0ZWQpIHtcbiAgaWYgKGltcG9ydGVkLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG4gIGxldCBtYXhTZWVuUmFua05vZGUgPSBpbXBvcnRlZFswXVxuICByZXR1cm4gaW1wb3J0ZWQuZmlsdGVyKGZ1bmN0aW9uIChpbXBvcnRlZE1vZHVsZSkge1xuICAgIGNvbnN0IHJlcyA9IGltcG9ydGVkTW9kdWxlLnJhbmsgPCBtYXhTZWVuUmFua05vZGUucmFua1xuICAgIGlmIChtYXhTZWVuUmFua05vZGUucmFuayA8IGltcG9ydGVkTW9kdWxlLnJhbmspIHtcbiAgICAgIG1heFNlZW5SYW5rTm9kZSA9IGltcG9ydGVkTW9kdWxlXG4gICAgfVxuICAgIHJldHVybiByZXNcbiAgfSlcbn1cblxuXG5mdW5jdGlvbiBmaW5kUm9vdE5vZGUoaiwgcm9vdCwgbm9kZSkge1xuICBsZXQgcmVzdWx0ID0gbnVsbDtcblxuICByb290XG4gICAgLmZpbmQoai5Ob2RlKVxuICAgIC5maWx0ZXIoKHApID0+IHAubm9kZSA9PT0gbm9kZSkuZm9yRWFjaChwID0+IHtcbiAgICBsZXQgcGFyZW50ID0gcDtcblxuICAgIHdoaWxlIChwYXJlbnQucGFyZW50ICE9IG51bGwgJiYgcGFyZW50LnBhcmVudC52YWx1ZS5ib2R5ID09IG51bGwpIHtcbiAgICAgIHBhcmVudCA9IHBhcmVudC5wYXJlbnQ7XG4gICAgfVxuXG4gICAgcmVzdWx0ID0gcGFyZW50O1xuICB9KTtcblxuICByZXR1cm4gcmVzdWx0O1xufVxuXG5mdW5jdGlvbiBmaXhPdXRPZk9yZGVyKGNvbnRleHQsIGZpcnN0Tm9kZSwgc2Vjb25kTm9kZSwgb3JkZXIpIHtcbiAgY29uc3Qgc291cmNlQ29kZSA9IGNvbnRleHQuZ2V0U291cmNlQ29kZSgpO1xuICBjb25zdCByb290ID0gaihzb3VyY2VDb2RlLmFzdCk7XG5cbiAgY29uc3QgZmlyc3RSb290ID0gZmluZFJvb3ROb2RlKGosIHJvb3QsIGZpcnN0Tm9kZS5ub2RlKTtcbiAgY29uc3Qgc2Vjb25kUm9vdCA9IGZpbmRSb290Tm9kZShqLCByb290LCBzZWNvbmROb2RlLm5vZGUpO1xuICBjb25zdCBuZXdDb2RlID0gc291cmNlQ29kZS5nZXRUZXh0KHNlY29uZFJvb3Qubm9kZSk7XG5cbiAgY29uc3QgbXNnID0gKCkgPT4gYFxcYCR7c2Vjb25kTm9kZS5uYW1lfVxcYCBpbXBvcnQgc2hvdWxkIG9jY3VyICR7b3JkZXJ9YCArXG4gICAgYCBpbXBvcnQgXFxgJHtmaXJzdE5vZGUubmFtZX1cXGBgO1xuXG4gIGlmIChvcmRlciA9PT0gJ2JlZm9yZScpIHtcbiAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICBub2RlOiBzZWNvbmROb2RlLm5vZGUsXG4gICAgICBtZXNzYWdlOiBtc2coKSxcbiAgICAgIGZpeDogZml4ZXIgPT4gZml4ZXIuaW5zZXJ0VGV4dEJlZm9yZShmaXJzdFJvb3Qubm9kZSwgbmV3Q29kZSlcbiAgICB9KTtcbiAgfSBlbHNlIGlmIChvcmRlciA9PT0gJ2FmdGVyJykge1xuICAgIGNvbnRleHQucmVwb3J0KHtcbiAgICAgIG5vZGU6IHNlY29uZE5vZGUubm9kZSxcbiAgICAgIG1lc3NhZ2U6IG1zZygpLFxuICAgICAgZml4OiBmaXhlciA9PiBmaXhlci5pbnNlcnRUZXh0QWZ0ZXIoZmlyc3RSb290Lm5vZGUsIG5ld0NvZGUpXG4gICAgfSk7XG4gIH1cblxuICBjb250ZXh0LnJlcG9ydCh7XG4gICAgbm9kZTogc2Vjb25kTm9kZS5ub2RlLFxuICAgIG1lc3NhZ2U6IG1zZygpLFxuICAgIGZpeDogZml4ZXIgPT4gZml4ZXIucmVtb3ZlKHNlY29uZFJvb3Qubm9kZSlcbiAgfSk7XG59XG5cbmZ1bmN0aW9uIHJlcG9ydE91dE9mT3JkZXIoY29udGV4dCwgaW1wb3J0ZWQsIG91dE9mT3JkZXIsIG9yZGVyKSB7XG4gIG91dE9mT3JkZXIuZm9yRWFjaChmdW5jdGlvbiAoaW1wKSB7XG4gICAgY29uc3QgZm91bmQgPSBpbXBvcnRlZC5maW5kKGZ1bmN0aW9uIGhhc0hpZ2hlclJhbmsoaW1wb3J0ZWRJdGVtKSB7XG4gICAgICByZXR1cm4gaW1wb3J0ZWRJdGVtLnJhbmsgPiBpbXAucmFua1xuICAgIH0pXG4gICAgZml4T3V0T2ZPcmRlcihjb250ZXh0LCBmb3VuZCwgaW1wLCBvcmRlcik7XG4gIH0pXG59XG5cbmZ1bmN0aW9uIG1ha2VPdXRPZk9yZGVyUmVwb3J0KGNvbnRleHQsIGltcG9ydGVkKSB7XG4gIGNvbnN0IG91dE9mT3JkZXIgPSBmaW5kT3V0T2ZPcmRlcihpbXBvcnRlZClcbiAgaWYgKCFvdXRPZk9yZGVyLmxlbmd0aCkge1xuICAgIHJldHVyblxuICB9XG4gIC8vIFRoZXJlIGFyZSB0aGluZ3MgdG8gcmVwb3J0LiBUcnkgdG8gbWluaW1pemUgdGhlIG51bWJlciBvZiByZXBvcnRlZCBlcnJvcnMuXG4gIGNvbnN0IHJldmVyc2VkSW1wb3J0ZWQgPSByZXZlcnNlKGltcG9ydGVkKVxuICBjb25zdCByZXZlcnNlZE9yZGVyID0gZmluZE91dE9mT3JkZXIocmV2ZXJzZWRJbXBvcnRlZClcbiAgaWYgKHJldmVyc2VkT3JkZXIubGVuZ3RoIDwgb3V0T2ZPcmRlci5sZW5ndGgpIHtcbiAgICByZXBvcnRPdXRPZk9yZGVyKGNvbnRleHQsIHJldmVyc2VkSW1wb3J0ZWQsIHJldmVyc2VkT3JkZXIsICdhZnRlcicpXG4gICAgcmV0dXJuXG4gIH1cbiAgcmVwb3J0T3V0T2ZPcmRlcihjb250ZXh0LCBpbXBvcnRlZCwgb3V0T2ZPcmRlciwgJ2JlZm9yZScpXG59XG5cbi8vIERFVEVDVElOR1xuXG5mdW5jdGlvbiBjb21wdXRlUmFuayhjb250ZXh0LCByYW5rcywgbmFtZSwgdHlwZSkge1xuICByZXR1cm4gcmFua3NbaW1wb3J0VHlwZShuYW1lLCBjb250ZXh0KV0gK1xuICAgICh0eXBlID09PSAnaW1wb3J0JyA/IDAgOiAxMDApXG59XG5cbmZ1bmN0aW9uIHJlZ2lzdGVyTm9kZShjb250ZXh0LCBub2RlLCBuYW1lLCB0eXBlLCByYW5rcywgaW1wb3J0ZWQpIHtcbiAgY29uc3QgcmFuayA9IGNvbXB1dGVSYW5rKGNvbnRleHQsIHJhbmtzLCBuYW1lLCB0eXBlKVxuICBpZiAocmFuayAhPT0gLTEpIHtcbiAgICBpbXBvcnRlZC5wdXNoKHtuYW1lLCByYW5rLCBub2RlfSlcbiAgfVxufVxuXG5mdW5jdGlvbiBpc0luVmFyaWFibGVEZWNsYXJhdG9yKG5vZGUpIHtcbiAgcmV0dXJuIG5vZGUgJiZcbiAgICAobm9kZS50eXBlID09PSAnVmFyaWFibGVEZWNsYXJhdG9yJyB8fCBpc0luVmFyaWFibGVEZWNsYXJhdG9yKG5vZGUucGFyZW50KSlcbn1cblxuY29uc3QgdHlwZXMgPSBbJ2J1aWx0aW4nLCAnZXh0ZXJuYWwnLCAnaW50ZXJuYWwnLCAncGFyZW50JywgJ3NpYmxpbmcnLCAnaW5kZXgnXVxuXG4vLyBDcmVhdGVzIGFuIG9iamVjdCB3aXRoIHR5cGUtcmFuayBwYWlycy5cbi8vIEV4YW1wbGU6IHsgaW5kZXg6IDAsIHNpYmxpbmc6IDEsIHBhcmVudDogMSwgZXh0ZXJuYWw6IDEsIGJ1aWx0aW46IDIsIGludGVybmFsOiAyIH1cbi8vIFdpbGwgdGhyb3cgYW4gZXJyb3IgaWYgaXQgY29udGFpbnMgYSB0eXBlIHRoYXQgZG9lcyBub3QgZXhpc3QsIG9yIGhhcyBhIGR1cGxpY2F0ZVxuZnVuY3Rpb24gY29udmVydEdyb3Vwc1RvUmFua3MoZ3JvdXBzKSB7XG4gIGNvbnN0IHJhbmtPYmplY3QgPSBncm91cHMucmVkdWNlKGZ1bmN0aW9uKHJlcywgZ3JvdXAsIGluZGV4KSB7XG4gICAgaWYgKHR5cGVvZiBncm91cCA9PT0gJ3N0cmluZycpIHtcbiAgICAgIGdyb3VwID0gW2dyb3VwXVxuICAgIH1cbiAgICBncm91cC5mb3JFYWNoKGZ1bmN0aW9uKGdyb3VwSXRlbSkge1xuICAgICAgaWYgKHR5cGVzLmluZGV4T2YoZ3JvdXBJdGVtKSA9PT0gLTEpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbmNvcnJlY3QgY29uZmlndXJhdGlvbiBvZiB0aGUgcnVsZTogVW5rbm93biB0eXBlIGAnICtcbiAgICAgICAgICBKU09OLnN0cmluZ2lmeShncm91cEl0ZW0pICsgJ2AnKVxuICAgICAgfVxuICAgICAgaWYgKHJlc1tncm91cEl0ZW1dICE9PSB1bmRlZmluZWQpIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKCdJbmNvcnJlY3QgY29uZmlndXJhdGlvbiBvZiB0aGUgcnVsZTogYCcgKyBncm91cEl0ZW0gKyAnYCBpcyBkdXBsaWNhdGVkJylcbiAgICAgIH1cbiAgICAgIHJlc1tncm91cEl0ZW1dID0gaW5kZXhcbiAgICB9KVxuICAgIHJldHVybiByZXNcbiAgfSwge30pXG5cbiAgY29uc3Qgb21pdHRlZFR5cGVzID0gdHlwZXMuZmlsdGVyKGZ1bmN0aW9uKHR5cGUpIHtcbiAgICByZXR1cm4gcmFua09iamVjdFt0eXBlXSA9PT0gdW5kZWZpbmVkXG4gIH0pXG5cbiAgcmV0dXJuIG9taXR0ZWRUeXBlcy5yZWR1Y2UoZnVuY3Rpb24ocmVzLCB0eXBlKSB7XG4gICAgcmVzW3R5cGVdID0gZ3JvdXBzLmxlbmd0aFxuICAgIHJldHVybiByZXNcbiAgfSwgcmFua09iamVjdClcbn1cblxuZnVuY3Rpb24gZml4TmV3TGluZUFmdGVySW1wb3J0KGNvbnRleHQsIHByZXZpb3VzSW1wb3J0KSB7XG4gIGNvbnN0IHJvb3QgPSBqKGNvbnRleHQuZ2V0U291cmNlQ29kZSgpLmFzdCk7XG5cbiAgY29uc3QgcHJldlJvb3QgPSBmaW5kUm9vdE5vZGUoaiwgcm9vdCwgcHJldmlvdXNJbXBvcnQubm9kZSk7XG5cbiAgcmV0dXJuIChmaXhlcikgPT4gZml4ZXIuaW5zZXJ0VGV4dEFmdGVyKHByZXZSb290Lm5vZGUsIEVPTCk7XG59XG5cbmZ1bmN0aW9uIHJlbW92ZU5ld0xpbmVBZnRlckltcG9ydChjb250ZXh0LCBjdXJyZW50SW1wb3J0LCBwcmV2aW91c0ltcG9ydCkge1xuICBjb25zdCByb290ID0gaihjb250ZXh0LmdldFNvdXJjZUNvZGUoKS5hc3QpO1xuXG4gIGNvbnN0IHByZXZSb290ID0gZmluZFJvb3ROb2RlKGosIHJvb3QsIHByZXZpb3VzSW1wb3J0Lm5vZGUpO1xuICBjb25zdCBjdXJyUm9vdCA9IGZpbmRSb290Tm9kZShqLCByb290LCBjdXJyZW50SW1wb3J0Lm5vZGUpO1xuXG4gIHJldHVybiAoZml4ZXIpID0+IGZpeGVyLnJlbW92ZVJhbmdlKFtwcmV2Um9vdC5ub2RlLnJhbmdlWzFdICsgMSwgY3VyclJvb3Qubm9kZS5yYW5nZVswXV0pO1xufVxuXG5mdW5jdGlvbiBtYWtlTmV3bGluZXNCZXR3ZWVuUmVwb3J0IChjb250ZXh0LCBpbXBvcnRlZCwgbmV3bGluZXNCZXR3ZWVuSW1wb3J0cykge1xuICBjb25zdCBnZXROdW1iZXJPZkVtcHR5TGluZXNCZXR3ZWVuID0gKGN1cnJlbnRJbXBvcnQsIHByZXZpb3VzSW1wb3J0KSA9PiB7XG4gICAgY29uc3QgbGluZXNCZXR3ZWVuSW1wb3J0cyA9IGNvbnRleHQuZ2V0U291cmNlQ29kZSgpLmxpbmVzLnNsaWNlKFxuICAgICAgcHJldmlvdXNJbXBvcnQubm9kZS5sb2MuZW5kLmxpbmUsXG4gICAgICBjdXJyZW50SW1wb3J0Lm5vZGUubG9jLnN0YXJ0LmxpbmUgLSAxXG4gICAgKVxuXG4gICAgcmV0dXJuIGxpbmVzQmV0d2VlbkltcG9ydHMuZmlsdGVyKChsaW5lKSA9PiAhbGluZS50cmltKCkubGVuZ3RoKS5sZW5ndGhcbiAgfVxuXG4gIGxldCBwcmV2aW91c0ltcG9ydCA9IGltcG9ydGVkWzBdXG5cbiAgaW1wb3J0ZWQuc2xpY2UoMSkuZm9yRWFjaChmdW5jdGlvbihjdXJyZW50SW1wb3J0KSB7XG4gICAgY29uc3QgZW1wdHlMaW5lc0NvdW50ID0gZ2V0TnVtYmVyT2ZFbXB0eUxpbmVzQmV0d2VlbihjdXJyZW50SW1wb3J0LCBwcmV2aW91c0ltcG9ydCk7XG4gICAgaWYgKG5ld2xpbmVzQmV0d2VlbkltcG9ydHMgPT09ICdhbHdheXMnKSB7XG4gICAgICBpZiAoY3VycmVudEltcG9ydC5yYW5rICE9PSBwcmV2aW91c0ltcG9ydC5yYW5rICYmIGVtcHR5TGluZXNDb3VudCA9PT0gMCkge1xuICAgICAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICAgICAgbm9kZTogcHJldmlvdXNJbXBvcnQubm9kZSxcbiAgICAgICAgICBtZXNzYWdlOiAnVGhlcmUgc2hvdWxkIGJlIGF0IGxlYXN0IG9uZSBlbXB0eSBsaW5lIGJldHdlZW4gaW1wb3J0IGdyb3VwcycsXG4gICAgICAgICAgZml4OiBmaXhOZXdMaW5lQWZ0ZXJJbXBvcnQoY29udGV4dCwgcHJldmlvdXNJbXBvcnQpXG4gICAgICAgIH0pO1xuICAgICAgfSBlbHNlIGlmIChjdXJyZW50SW1wb3J0LnJhbmsgPT09IHByZXZpb3VzSW1wb3J0LnJhbmsgJiYgZW1wdHlMaW5lc0NvdW50ID4gMCkge1xuICAgICAgICBjb250ZXh0LnJlcG9ydCh7XG4gICAgICAgICAgbm9kZTogcHJldmlvdXNJbXBvcnQubm9kZSxcbiAgICAgICAgICBtZXNzYWdlOiAnVGhlcmUgc2hvdWxkIGJlIG5vIGVtcHR5IGxpbmUgd2l0aGluIGltcG9ydCBncm91cCcsXG4gICAgICAgICAgZml4OiByZW1vdmVOZXdMaW5lQWZ0ZXJJbXBvcnQoY29udGV4dCwgY3VycmVudEltcG9ydCwgcHJldmlvdXNJbXBvcnQpXG4gICAgICAgIH0pO1xuICAgICAgfVxuICAgIH0gZWxzZSBpZiAoZW1wdHlMaW5lc0NvdW50ID4gMCkge1xuICAgICAgY29udGV4dC5yZXBvcnQoe1xuICAgICAgICBub2RlOiBwcmV2aW91c0ltcG9ydC5ub2RlLFxuICAgICAgICBtZXNzYWdlOiAnVGhlcmUgc2hvdWxkIGJlIG5vIGVtcHR5IGxpbmUgYmV0d2VlbiBpbXBvcnQgZ3JvdXBzJyxcbiAgICAgICAgZml4OiByZW1vdmVOZXdMaW5lQWZ0ZXJJbXBvcnQoY29udGV4dCwgY3VycmVudEltcG9ydCwgcHJldmlvdXNJbXBvcnQpXG4gICAgICB9KTtcbiAgICB9XG5cbiAgICBwcmV2aW91c0ltcG9ydCA9IGN1cnJlbnRJbXBvcnRcbiAgfSlcbn1cblxubW9kdWxlLmV4cG9ydHMgPSB7XG4gIG1ldGE6IHtcbiAgICBkb2NzOiB7fSxcbiAgICBmaXhhYmxlOiAnY29kZScsXG4gICAgc2NoZW1hOiBbXG4gICAgICB7XG4gICAgICAgIHR5cGU6ICdvYmplY3QnLFxuICAgICAgICBwcm9wZXJ0aWVzOiB7XG4gICAgICAgICAgZ3JvdXBzOiB7XG4gICAgICAgICAgICB0eXBlOiAnYXJyYXknLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgJ25ld2xpbmVzLWJldHdlZW4nOiB7XG4gICAgICAgICAgICBlbnVtOiBbICdpZ25vcmUnLCAnYWx3YXlzJywgJ25ldmVyJyBdLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIGFkZGl0aW9uYWxQcm9wZXJ0aWVzOiBmYWxzZSxcbiAgICAgIH0sXG4gICAgXSxcbiAgfSxcblxuICBjcmVhdGU6IGZ1bmN0aW9uIGltcG9ydE9yZGVyUnVsZSAoY29udGV4dCkge1xuICAgIGNvbnN0IG9wdGlvbnMgPSBjb250ZXh0Lm9wdGlvbnNbMF0gfHwge31cbiAgICBjb25zdCBuZXdsaW5lc0JldHdlZW5JbXBvcnRzID0gb3B0aW9uc1snbmV3bGluZXMtYmV0d2VlbiddIHx8ICdpZ25vcmUnXG4gICAgbGV0IHJhbmtzXG5cbiAgICB0cnkge1xuICAgICAgcmFua3MgPSBjb252ZXJ0R3JvdXBzVG9SYW5rcyhvcHRpb25zLmdyb3VwcyB8fCBkZWZhdWx0R3JvdXBzKVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBNYWxmb3JtZWQgY29uZmlndXJhdGlvblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgUHJvZ3JhbTogZnVuY3Rpb24obm9kZSkge1xuICAgICAgICAgIGNvbnRleHQucmVwb3J0KG5vZGUsIGVycm9yLm1lc3NhZ2UpXG4gICAgICAgIH0sXG4gICAgICB9XG4gICAgfVxuICAgIGxldCBpbXBvcnRlZCA9IFtdXG4gICAgbGV0IGxldmVsID0gMFxuXG4gICAgZnVuY3Rpb24gaW5jcmVtZW50TGV2ZWwoKSB7XG4gICAgICBsZXZlbCsrXG4gICAgfVxuICAgIGZ1bmN0aW9uIGRlY3JlbWVudExldmVsKCkge1xuICAgICAgbGV2ZWwtLVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBJbXBvcnREZWNsYXJhdGlvbjogZnVuY3Rpb24gaGFuZGxlSW1wb3J0cyhub2RlKSB7XG4gICAgICAgIGlmIChub2RlLnNwZWNpZmllcnMubGVuZ3RoKSB7IC8vIElnbm9yaW5nIHVuYXNzaWduZWQgaW1wb3J0c1xuICAgICAgICAgIGNvbnN0IG5hbWUgPSBub2RlLnNvdXJjZS52YWx1ZVxuICAgICAgICAgIHJlZ2lzdGVyTm9kZShjb250ZXh0LCBub2RlLCBuYW1lLCAnaW1wb3J0JywgcmFua3MsIGltcG9ydGVkKVxuICAgICAgICB9XG4gICAgICB9LFxuICAgICAgQ2FsbEV4cHJlc3Npb246IGZ1bmN0aW9uIGhhbmRsZVJlcXVpcmVzKG5vZGUpIHtcbiAgICAgICAgaWYgKGxldmVsICE9PSAwIHx8ICFpc1N0YXRpY1JlcXVpcmUobm9kZSkgfHwgIWlzSW5WYXJpYWJsZURlY2xhcmF0b3Iobm9kZS5wYXJlbnQpKSB7XG4gICAgICAgICAgcmV0dXJuXG4gICAgICAgIH1cbiAgICAgICAgY29uc3QgbmFtZSA9IG5vZGUuYXJndW1lbnRzWzBdLnZhbHVlXG4gICAgICAgIHJlZ2lzdGVyTm9kZShjb250ZXh0LCBub2RlLCBuYW1lLCAncmVxdWlyZScsIHJhbmtzLCBpbXBvcnRlZClcbiAgICAgIH0sXG4gICAgICAnUHJvZ3JhbTpleGl0JzogZnVuY3Rpb24gcmVwb3J0QW5kUmVzZXQoKSB7XG4gICAgICAgIG1ha2VPdXRPZk9yZGVyUmVwb3J0KGNvbnRleHQsIGltcG9ydGVkKVxuXG4gICAgICAgIGlmIChuZXdsaW5lc0JldHdlZW5JbXBvcnRzICE9PSAnaWdub3JlJykge1xuICAgICAgICAgIG1ha2VOZXdsaW5lc0JldHdlZW5SZXBvcnQoY29udGV4dCwgaW1wb3J0ZWQsIG5ld2xpbmVzQmV0d2VlbkltcG9ydHMpXG4gICAgICAgIH1cblxuICAgICAgICBpbXBvcnRlZCA9IFtdXG4gICAgICB9LFxuICAgICAgRnVuY3Rpb25EZWNsYXJhdGlvbjogaW5jcmVtZW50TGV2ZWwsXG4gICAgICBGdW5jdGlvbkV4cHJlc3Npb246IGluY3JlbWVudExldmVsLFxuICAgICAgQXJyb3dGdW5jdGlvbkV4cHJlc3Npb246IGluY3JlbWVudExldmVsLFxuICAgICAgQmxvY2tTdGF0ZW1lbnQ6IGluY3JlbWVudExldmVsLFxuICAgICAgT2JqZWN0RXhwcmVzc2lvbjogaW5jcmVtZW50TGV2ZWwsXG4gICAgICAnRnVuY3Rpb25EZWNsYXJhdGlvbjpleGl0JzogZGVjcmVtZW50TGV2ZWwsXG4gICAgICAnRnVuY3Rpb25FeHByZXNzaW9uOmV4aXQnOiBkZWNyZW1lbnRMZXZlbCxcbiAgICAgICdBcnJvd0Z1bmN0aW9uRXhwcmVzc2lvbjpleGl0JzogZGVjcmVtZW50TGV2ZWwsXG4gICAgICAnQmxvY2tTdGF0ZW1lbnQ6ZXhpdCc6IGRlY3JlbWVudExldmVsLFxuICAgICAgJ09iamVjdEV4cHJlc3Npb246ZXhpdCc6IGRlY3JlbWVudExldmVsLFxuICAgIH1cbiAgfSxcbn1cbiJdfQ==