simplr-tslint
Version:
A set of TSLint rules used in SimplrJS projects.
157 lines • 27.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const ts = require("typescript");
const Lint = require("tslint");
class Rule extends Lint.Rules.AbstractRule {
static resolveModuleFilename(moduleName) {
return moduleName + this.moduleFilenameSuffix;
}
apply(sourceFile) {
return this.applyWithWalker(new ImportModuleWalker(sourceFile, this.getOptions()));
}
}
Rule.sep = "/";
Rule.searchModulePath = ["app", "modules"].join(Rule.sep);
Rule.searchModulePathSplitter = Rule.searchModulePath + Rule.sep;
Rule.entryFailureString = "Module should be imported from an entry file.";
Rule.insideRelativeFailureString = "A relative import should be used inside the module.";
Rule.insideEntryFailureString = "An entry file import should not be used inside the module.";
Rule.forbiddenReexportAllFailureString = "Forbidden 'export * from', use named re-exports.";
Rule.moduleFilenameSuffix = "-module";
Rule.reexportPathRegex = /export[\s\S]*from[\s]*[\'\"](.*)[\'\"]/;
Rule.reexportAllPathRegex = /export[\s\S]*\*/;
exports.Rule = Rule;
class ImportModuleWalker extends Lint.RuleWalker {
/**
* Update import path with module entry file.
*/
importEntryFileFixer(start, length, prefix, moduleName, fullModuleName, quoteSymbol) {
const resolvedImport = [
prefix + Rule.searchModulePath,
moduleName,
fullModuleName + quoteSymbol
].join(Rule.sep);
return new Lint.Replacement(start, length, resolvedImport);
}
/**
* Change path to relative.
*/
importWithRelativePathFixer(start, length, importFileName, sourceSplitPath, importSplitPath, quoteSymbol) {
const sourcePath = sourceSplitPath.slice(0, -1).join(Rule.sep);
const importPath = importSplitPath.slice(0, -1).join(Rule.sep);
const relativePath = path.relative(sourcePath, importPath).split(path.sep);
relativePath.push(importFileName);
let relativePathString = relativePath.join(Rule.sep);
if (relativePathString[0] === Rule.sep) {
relativePathString = "." + relativePathString;
}
else if (relativePathString[0] !== ".") {
relativePathString = `.${Rule.sep}${relativePathString}`;
}
const fixedPath = `${quoteSymbol}${relativePathString}${quoteSymbol}`;
return new Lint.Replacement(start, length, fixedPath);
}
/**
* Generate path details object from pathname.
*/
parsePathDetails(pathname, withQuotes = true) {
const [prefix, suffix] = pathname.split(Rule.searchModulePathSplitter);
const [moduleName, ...importSplitPath] = suffix.split(Rule.sep);
if (withQuotes) {
importSplitPath[importSplitPath.length - 1] = importSplitPath[importSplitPath.length - 1].slice(0, -1);
}
const [fileName] = importSplitPath.slice(-1);
return {
prefix: prefix,
suffix: suffix,
moduleName: moduleName,
fullModuleName: Rule.resolveModuleFilename(moduleName),
splitPath: importSplitPath,
fileName: fileName,
withQuotes: withQuotes
};
}
/**
* Validate import line.
*/
startValidating(sourceFile, importFile, importStart, quote = "") {
const sourceFileIsFromModule = sourceFile.indexOf(Rule.searchModulePath) > -1;
const importFileIsFromModule = importFile.indexOf(Rule.searchModulePath) > -1;
if (!sourceFileIsFromModule && !importFileIsFromModule) {
return;
}
// Check if importing file is not from module
if (!importFileIsFromModule) {
// Check if source file is from module
if (sourceFileIsFromModule) {
const sourceDetails = this.parsePathDetails(sourceFile, false);
const importFileName = importFile.split(Rule.sep).slice(-1)[0].slice(0, -1);
const targetFileName = sourceDetails.fullModuleName;
// Check if module itself doesn't import from entry file
if (importFileName === targetFileName) {
this.addFailureAt(importStart, importFile.length, Rule.insideEntryFailureString);
}
}
return;
}
const importDetails = this.parsePathDetails(importFile, Boolean(quote));
if (sourceFileIsFromModule && importFileIsFromModule) {
const sourceDetails = this.parsePathDetails(sourceFile, false);
if (sourceDetails.moduleName === importDetails.moduleName) {
const fix = this.importWithRelativePathFixer(importStart, importFile.length, importDetails.fileName, sourceDetails.splitPath, importDetails.splitPath, quote);
this.addFailureAt(importStart, importFile.length, Rule.insideRelativeFailureString, fix);
return;
}
}
if (importFileIsFromModule && (importDetails.splitPath.length > 1 || importDetails.fullModuleName !== importDetails.fileName)) {
const fix = this.importEntryFileFixer(importStart, importFile.length, importDetails.prefix, importDetails.moduleName, importDetails.fullModuleName, quote);
this.addFailureAt(importStart, importFile.length, Rule.entryFailureString, fix);
return;
}
}
startValidatingReExportAll(fullText, sourceFile, node) {
const sourceFileIsFromModule = sourceFile.indexOf(Rule.searchModulePath) > -1;
if (sourceFileIsFromModule && Rule.reexportAllPathRegex.test(fullText)) {
this.addFailureAtNode(node, Rule.forbiddenReexportAllFailureString);
}
}
/**
* Visit on import declaration found.
*/
visitImportDeclaration(node) {
const sourceFile = node.getSourceFile().fileName;
const importFile = node.moduleSpecifier.getText();
const importStart = node.moduleSpecifier.getStart();
const quoteSymbol = importFile[0];
this.startValidating(sourceFile, importFile, importStart, quoteSymbol);
super.visitImportDeclaration(node);
}
/**
* Visit on any source file.
*/
visitSourceFile(node) {
const fullText = node.getFullText();
const sourceFile = node.fileName;
if (node.statements.length > 0) {
node.statements
.filter(x => x.kind === ts.SyntaxKind.ExportDeclaration && x.getFullText().indexOf("from") > -1)
.forEach(statement => {
const text = statement.getFullText();
const regexResult = Rule.reexportPathRegex.exec(text);
if (regexResult == null) {
return;
}
const importFile = regexResult[1];
if (importFile == null) {
return;
}
this.startValidatingReExportAll(text, sourceFile, statement);
const importStart = fullText.indexOf(importFile);
this.startValidating(sourceFile, importFile, importStart);
});
}
super.visitSourceFile(node);
}
}
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0TW9kdWxlUnVsZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbXBvcnRNb2R1bGVSdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7O0FBQUEsNkJBQTZCO0FBQzdCLGlDQUFpQztBQUNqQywrQkFBK0I7QUFZL0IsVUFBa0IsU0FBUSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVk7SUFnQnRDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxVQUFrQjtRQUNsRCxPQUFPLFVBQVUsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7SUFDbEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxVQUF5QjtRQUNsQyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDOztBQXJCc0IsUUFBRyxHQUFXLEdBQUcsQ0FBQztBQUVsQixxQkFBZ0IsR0FBVyxDQUFDLEtBQUssRUFBRSxTQUFTLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxDQUFDO0FBQzdELDZCQUF3QixHQUFXLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFDO0FBRXBFLHVCQUFrQixHQUFXLCtDQUErQyxDQUFDO0FBQzdFLGdDQUEyQixHQUFXLHFEQUFxRCxDQUFDO0FBQzVGLDZCQUF3QixHQUFXLDREQUE0RCxDQUFDO0FBQ2hHLHNDQUFpQyxHQUFXLGtEQUFrRCxDQUFDO0FBRS9GLHlCQUFvQixHQUFXLFNBQVMsQ0FBQztBQUV6QyxzQkFBaUIsR0FBVyx3Q0FBd0MsQ0FBQztBQUNyRSx5QkFBb0IsR0FBVyxpQkFBaUIsQ0FBQztBQWQ1RSxvQkF1QkM7QUFFRCx3QkFBeUIsU0FBUSxJQUFJLENBQUMsVUFBVTtJQUM1Qzs7T0FFRztJQUNLLG9CQUFvQixDQUN4QixLQUFhLEVBQ2IsTUFBYyxFQUNkLE1BQWMsRUFD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QUNqQixNQUFNLElBQUksR0FBRyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUM7Z0JBRXJDLE1BQU0sV0FBVyxHQUFHLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RELElBQUksV0FBVyxJQUFJLElBQUksRUFBRTtvQkFDckIsT0FBTztpQkFDVjtnQkFFRCxNQUFNLFVBQVUsR0FBRyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7Z0JBQ2xDLElBQUksVUFBVSxJQUFJLElBQUksRUFBRTtvQkFDcEIsT0FBTztpQkFDVjtnQkFFRCxJQUFJLENBQUMsMEJBQTBCLENBQUMsSUFBSSxFQUFFLFVBQVUsRUFBRSxTQUFTLENBQUMsQ0FBQztnQkFFN0QsTUFBTSxXQUFXLEdBQUcsUUFBUSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQztnQkFDakQsSUFBSSxDQUFDLGVBQWUsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFdBQVcsQ0FBQyxDQUFDO1lBQzlELENBQUMsQ0FBQyxDQUFDO1NBQ1Y7UUFFRCxLQUFLLENBQUMsZUFBZSxDQUFDLElBQUksQ0FBQyxDQUFDO0lBQ2hDLENBQUM7Q0FDSiIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCAqIGFzIHBhdGggZnJvbSBcInBhdGhcIjtcclxuaW1wb3J0ICogYXMgdHMgZnJvbSBcInR5cGVzY3JpcHRcIjtcclxuaW1wb3J0ICogYXMgTGludCBmcm9tIFwidHNsaW50XCI7XHJcblxyXG5pbnRlcmZhY2UgUGF0aERldGFpbHMge1xyXG4gICAgcHJlZml4OiBzdHJpbmc7XHJcbiAgICBzdWZmaXg6IHN0cmluZztcclxuICAgIG1vZHVsZU5hbWU6IHN0cmluZztcclxuICAgIGZ1bGxNb2R1bGVOYW1lOiBzdHJpbmc7XHJcbiAgICBmaWxlTmFtZTogc3RyaW5nO1xyXG4gICAgc3BsaXRQYXRoOiBzdHJpbmdbXTtcclxuICAgIHdpdGhRdW90ZXM6IGJvb2xlYW47XHJcbn1cclxuXHJcbmV4cG9ydCBjbGFzcyBSdWxlIGV4dGVuZHMgTGludC5SdWxlcy5BYnN0cmFjdFJ1bGUge1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBzZXA6IHN0cmluZyA9IFwiL1wiO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgc2VhcmNoTW9kdWxlUGF0aDogc3RyaW5nID0gW1wiYXBwXCIsIFwibW9kdWxlc1wiXS5qb2luKFJ1bGUuc2VwKTtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgc2VhcmNoTW9kdWxlUGF0aFNwbGl0dGVyOiBzdHJpbmcgPSBSdWxlLnNlYXJjaE1vZHVsZVBhdGggKyBSdWxlLnNlcDtcclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGVudHJ5RmFpbHVyZVN0cmluZzogc3RyaW5nID0gXCJNb2R1bGUgc2hvdWxkIGJlIGltcG9ydGVkIGZyb20gYW4gZW50cnkgZmlsZS5cIjtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgaW5zaWRlUmVsYXRpdmVGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkEgcmVsYXRpdmUgaW1wb3J0IHNob3VsZCBiZSB1c2VkIGluc2lkZSB0aGUgbW9kdWxlLlwiO1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBpbnNpZGVFbnRyeUZhaWx1cmVTdHJpbmc6IHN0cmluZyA9IFwiQW4gZW50cnkgZmlsZSBpbXBvcnQgc2hvdWxkIG5vdCBiZSB1c2VkIGluc2lkZSB0aGUgbW9kdWxlLlwiO1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBmb3JiaWRkZW5SZWV4cG9ydEFsbEZhaWx1cmVTdHJpbmc6IHN0cmluZyA9IFwiRm9yYmlkZGVuICdleHBvcnQgKiBmcm9tJywgdXNlIG5hbWVkIHJlLWV4cG9ydHMuXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBtb2R1bGVGaWxlbmFtZVN1ZmZpeDogc3RyaW5nID0gXCItbW9kdWxlXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSByZWV4cG9ydFBhdGhSZWdleDogUmVnRXhwID0gL2V4cG9ydFtcXHNcXFNdKmZyb21bXFxzXSpbXFwnXFxcIl0oLiopW1xcJ1xcXCJdLztcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgcmVleHBvcnRBbGxQYXRoUmVnZXg6IFJlZ0V4cCA9IC9leHBvcnRbXFxzXFxTXSpcXCovO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVzb2x2ZU1vZHVsZUZpbGVuYW1lKG1vZHVsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIG1vZHVsZU5hbWUgKyB0aGlzLm1vZHVsZUZpbGVuYW1lU3VmZml4O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhcHBseShzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlKTogTGludC5SdWxlRmFpbHVyZVtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5hcHBseVdpdGhXYWxrZXIobmV3IEltcG9ydE1vZHVsZVdhbGtlcihzb3VyY2VGaWxlLCB0aGlzLmdldE9wdGlvbnMoKSkpO1xyXG4gICAgfVxyXG59XHJcblxyXG5jbGFzcyBJbXBvcnRNb2R1bGVXYWxrZXIgZXh0ZW5kcyBMaW50LlJ1bGVXYWxrZXIge1xyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGUgaW1wb3J0IHBhdGggd2l0aCBtb2R1bGUgZW50cnkgZmlsZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpbXBvcnRFbnRyeUZpbGVGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIHByZWZpeDogc3RyaW5nLFxyXG4gICAgICAgIG1vZHVsZU5hbWU6IHN0cmluZyxcclxuICAgICAgICBmdWxsTW9kdWxlTmFtZTogc3RyaW5nLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydCA9IFtcclxuICAgICAgICAgICAgcHJlZml4ICsgUnVsZS5zZWFyY2hNb2R1bGVQYXRoLFxyXG4gICAgICAgICAgICBtb2R1bGVOYW1lLFxyXG4gICAgICAgICAgICBmdWxsTW9kdWxlTmFtZSArIHF1b3RlU3ltYm9sXHJcbiAgICAgICAgXS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBMaW50LlJlcGxhY2VtZW50KHN0YXJ0LCBsZW5ndGgsIHJlc29sdmVkSW1wb3J0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoYW5nZSBwYXRoIHRvIHJlbGF0aXZlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGltcG9ydFdpdGhSZWxhdGl2ZVBhdGhGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIGltcG9ydEZpbGVOYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgc291cmNlU3BsaXRQYXRoOiBzdHJpbmdbXSxcclxuICAgICAgICBpbXBvcnRTcGxpdFBhdGg6IHN0cmluZ1tdLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gc291cmNlU3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRQYXRoID0gaW1wb3J0U3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZShzb3VyY2VQYXRoLCBpbXBvcnRQYXRoKS5zcGxpdChwYXRoLnNlcCk7XHJcbiAgICAgICAgcmVsYXRpdmVQYXRoLnB1c2goaW1wb3J0RmlsZU5hbWUpO1xyXG5cclxuICAgICAgICBsZXQgcmVsYXRpdmVQYXRoU3RyaW5nID0gcmVsYXRpdmVQYXRoLmpvaW4oUnVsZS5zZXApO1xyXG5cclxuICAgICAgICBpZiAocmVsYXRpdmVQYXRoU3RyaW5nWzBdID09PSBSdWxlLnNlcCkge1xyXG4gICAgICAgICAgICByZWxhdGl2ZVBhdGhTdHJpbmcgPSBcIi5cIiArIHJlbGF0aXZlUGF0aFN0cmluZztcclxuICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aXZlUGF0aFN0cmluZ1swXSAhPT0gXCIuXCIpIHtcclxuICAgICAgICAgICAgcmVsYXRpdmVQYXRoU3RyaW5nID0gYC4ke1J1bGUuc2VwfSR7cmVsYXRpdmVQYXRoU3RyaW5nfWA7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBmaXhlZFBhdGggPSBgJHtxdW90ZVN5bWJvbH0ke3JlbGF0aXZlUGF0aFN0cmluZ30ke3F1b3RlU3ltYm9sfWA7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgTGludC5SZXBsYWNlbWVudChzdGFydCwgbGVuZ3RoLCBmaXhlZFBhdGgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgcGF0aCBkZXRhaWxzIG9iamVjdCBmcm9tIHBhdGhuYW1lLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHBhcnNlUGF0aERldGFpbHMocGF0aG5hbWU6IHN0cmluZywgd2l0aFF1b3RlczogYm9vbGVhbiA9IHRydWUpOiBQYXRoRGV0YWlscyB7XHJcbiAgICAgICAgY29uc3QgW3ByZWZpeCwgc3VmZml4XSA9IHBhdGhuYW1lLnNwbGl0KFJ1bGUuc2VhcmNoTW9kdWxlUGF0aFNwbGl0dGVyKTtcclxuICAgICAgICBjb25zdCBbbW9kdWxlTmFtZSwgLi4uaW1wb3J0U3BsaXRQYXRoXSA9IHN1ZmZpeC5zcGxpdChSdWxlLnNlcCk7XHJcblxyXG4gICAgICAgIGlmICh3aXRoUXVvdGVzKSB7XHJcbiAgICAgICAgICAgIGltcG9ydFNwbGl0UGF0aFtpbXBvcnRTcGxpdFBhdGgubGVuZ3RoIC0gMV0gPSBpbXBvcnRTcGxpdFBhdGhbaW1wb3J0U3BsaXRQYXRoLmxlbmd0aCAtIDFdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IFtmaWxlTmFtZV0gPSBpbXBvcnRTcGxpdFBhdGguc2xpY2UoLTEpO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBwcmVmaXg6IHByZWZpeCxcclxuICAgICAgICAgICAgc3VmZml4OiBzdWZmaXgsXHJcbiAgICAgICAgICAgIG1vZHVsZU5hbWU6IG1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgIGZ1bGxNb2R1bGVOYW1lOiBSdWxlLnJlc29sdmVNb2R1bGVGaWxlbmFtZShtb2R1bGVOYW1lKSxcclxuICAgICAgICAgICAgc3BsaXRQYXRoOiBpbXBvcnRTcGxpdFBhdGgsXHJcbiAgICAgICAgICAgIGZpbGVOYW1lOiBmaWxlTmFtZSxcclxuICAgICAgICAgICAgd2l0aFF1b3Rlczogd2l0aFF1b3Rlc1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZSBpbXBvcnQgbGluZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzdGFydFZhbGlkYXRpbmcoc291cmNlRmlsZTogc3RyaW5nLCBpbXBvcnRGaWxlOiBzdHJpbmcsIGltcG9ydFN0YXJ0OiBudW1iZXIsIHF1b3RlOiBzdHJpbmcgPSBcIlwiKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSA9IGltcG9ydEZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcblxyXG4gICAgICAgIGlmICghc291cmNlRmlsZUlzRnJvbU1vZHVsZSAmJiAhaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiBpbXBvcnRpbmcgZmlsZSBpcyBub3QgZnJvbSBtb2R1bGVcclxuICAgICAgICBpZiAoIWltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHNvdXJjZSBmaWxlIGlzIGZyb20gbW9kdWxlXHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VEZXRhaWxzID0gdGhpcy5wYXJzZVBhdGhEZXRhaWxzKHNvdXJjZUZpbGUsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydEZpbGVOYW1lID0gaW1wb3J0RmlsZS5zcGxpdChSdWxlLnNlcCkuc2xpY2UoLTEpWzBdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldEZpbGVOYW1lID0gc291cmNlRGV0YWlscy5mdWxsTW9kdWxlTmFtZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBtb2R1bGUgaXRzZWxmIGRvZXNuJ3QgaW1wb3J0IGZyb20gZW50cnkgZmlsZVxyXG4gICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGVOYW1lID09PSB0YXJnZXRGaWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVFbnRyeUZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGltcG9ydERldGFpbHMgPSB0aGlzLnBhcnNlUGF0aERldGFpbHMoaW1wb3J0RmlsZSwgQm9vbGVhbihxdW90ZSkpO1xyXG4gICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlICYmIGltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuICAgICAgICAgICAgY29uc3Qgc291cmNlRGV0YWlscyA9IHRoaXMucGFyc2VQYXRoRGV0YWlscyhzb3VyY2VGaWxlLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VEZXRhaWxzLm1vZHVsZU5hbWUgPT09IGltcG9ydERldGFpbHMubW9kdWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZml4ID0gdGhpcy5pbXBvcnRXaXRoUmVsYXRpdmVQYXRoRml4ZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0U3RhcnQsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RmlsZS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5maWxlTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VEZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBxdW90ZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVSZWxhdGl2ZUZhaWx1cmVTdHJpbmcsIGZpeCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChpbXBvcnRGaWxlSXNGcm9tTW9kdWxlICYmIChpbXBvcnREZXRhaWxzLnNwbGl0UGF0aC5sZW5ndGggPiAxIHx8IGltcG9ydERldGFpbHMuZnVsbE1vZHVsZU5hbWUgIT09IGltcG9ydERldGFpbHMuZmlsZU5hbWUpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZpeCA9IHRoaXMuaW1wb3J0RW50cnlGaWxlRml4ZXIoXHJcbiAgICAgICAgICAgICAgICBpbXBvcnRTdGFydCxcclxuICAgICAgICAgICAgICAgIGltcG9ydEZpbGUubGVuZ3RoLFxyXG4gICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5wcmVmaXgsXHJcbiAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLm1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLmZ1bGxNb2R1bGVOYW1lLFxyXG4gICAgICAgICAgICAgICAgcXVvdGVcclxuICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgdGhpcy5hZGRGYWlsdXJlQXQoaW1wb3J0U3RhcnQsIGltcG9ydEZpbGUubGVuZ3RoLCBSdWxlLmVudHJ5RmFpbHVyZVN0cmluZywgZml4KTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKGZ1bGxUZXh0OiBzdHJpbmcsIHNvdXJjZUZpbGU6IHN0cmluZywgbm9kZTogdHMuU3RhdGVtZW50KTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgaWYgKHNvdXJjZUZpbGVJc0Zyb21Nb2R1bGUgJiYgUnVsZS5yZWV4cG9ydEFsbFBhdGhSZWdleC50ZXN0KGZ1bGxUZXh0KSkge1xyXG4gICAgICAgICAgICB0aGlzLmFkZEZhaWx1cmVBdE5vZGUobm9kZSwgUnVsZS5mb3JiaWRkZW5SZWV4cG9ydEFsbEZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFZpc2l0IG9uIGltcG9ydCBkZWNsYXJhdGlvbiBmb3VuZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogdHMuSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5nZXRTb3VyY2VGaWxlKCkuZmlsZU5hbWU7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZSA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFRleHQoKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRTdGFydCA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFN0YXJ0KCk7XHJcbiAgICAgICAgY29uc3QgcXVvdGVTeW1ib2wgPSBpbXBvcnRGaWxlWzBdO1xyXG5cclxuICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCwgcXVvdGVTeW1ib2wpO1xyXG5cclxuICAgICAgICBzdXBlci52aXNpdEltcG9ydERlY2xhcmF0aW9uKG5vZGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmlzaXQgb24gYW55IHNvdXJjZSBmaWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdmlzaXRTb3VyY2VGaWxlKG5vZGU6IHRzLlNvdXJjZUZpbGUpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBmdWxsVGV4dCA9IG5vZGUuZ2V0RnVsbFRleHQoKTtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5maWxlTmFtZTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUuc3RhdGVtZW50cy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIG5vZGUuc3RhdGVtZW50c1xyXG4gICAgICAgICAgICAgICAgLmZpbHRlcih4ID0+IHgua2luZCA9PT0gdHMuU3ludGF4S2luZC5FeHBvcnREZWNsYXJhdGlvbiAmJiB4LmdldEZ1bGxUZXh0KCkuaW5kZXhPZihcImZyb21cIikgPiAtMSlcclxuICAgICAgICAgICAgICAgIC5mb3JFYWNoKHN0YXRlbWVudCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dCA9IHN0YXRlbWVudC5nZXRGdWxsVGV4dCgpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdleFJlc3VsdCA9IFJ1bGUucmVleHBvcnRQYXRoUmVnZXguZXhlYyh0ZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhSZXN1bHQgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbXBvcnRGaWxlID0gcmVnZXhSZXN1bHRbMV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKHRleHQsIHNvdXJjZUZpbGUsIHN0YXRlbWVudCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydFN0YXJ0ID0gZnVsbFRleHQuaW5kZXhPZihpbXBvcnRGaWxlKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHN1cGVyLnZpc2l0U291cmNlRmlsZShub2RlKTtcclxuICAgIH1cclxufVxyXG4iXX0=