simplr-tslint
Version:
A set of TSLint rules used in SimplrJS projects.
176 lines • 30.4 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const path = require("path");
const ts = require("typescript");
const Lint = require("tslint");
const fs = require("fs");
class Rule extends Lint.Rules.AbstractRule {
static resolveModuleFilename(moduleName) {
return moduleName + this.moduleFilenameSuffix;
}
apply(sourceFile) {
return this.applyWithWalker(new ImportModuleWalker(sourceFile, this.getOptions()));
}
static getComponentEntryFileFromCache(fileName) {
return this.componentsEntryFilesCache[fileName];
}
static setComponentEntryFileToCache(fileName, value) {
this.componentsEntryFilesCache[fileName] = value;
}
}
Rule.sep = "/";
Rule.searchModulePath = ["app", "components"].join(Rule.sep);
Rule.searchModulePathSplitter = Rule.searchModulePath + Rule.sep;
Rule.entryFailureString = "Components should be imported from an entry file.";
Rule.insideRelativeFailureString = "A relative import should be used inside the components.";
Rule.insideEntryFailureString = "An entry file import should not be used inside the components.";
Rule.forbiddenReexportAllFailureString = "Forbidden 'export * from', use named re-exports.";
Rule.moduleFilenameSuffix = "-components";
Rule.reexportPathRegex = /export[\s\S]*from[\s]*[\'\"](.*)[\'\"]/;
Rule.reexportAllPathRegex = /export[\s\S]*\*/;
Rule.componentsEntryFilesCache = {};
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 fromCache = Rule.getComponentEntryFileFromCache(importDetails.fullModuleName);
let isComponentsWithEntry;
if (fromCache == null) {
isComponentsWithEntry = fs.existsSync(importDetails.fullModuleName);
Rule.setComponentEntryFileToCache(importDetails.fullModuleName, isComponentsWithEntry);
}
else {
isComponentsWithEntry = fromCache;
}
if (isComponentsWithEntry) {
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,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW1wb3J0Q29tcG9uZW50c1J1bGUuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvaW1wb3J0Q29tcG9uZW50c1J1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7QUFBQSw2QkFBNkI7QUFDN0IsaUNBQWlDO0FBQ2pDLCtCQUErQjtBQUMvQix5QkFBeUI7QUFZekIsVUFBa0IsU0FBUSxJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVk7SUFnQnRDLE1BQU0sQ0FBQyxxQkFBcUIsQ0FBQyxVQUFrQjtRQUNsRCxPQUFPLFVBQVUsR0FBRyxJQUFJLENBQUMsb0JBQW9CLENBQUM7SUFDbEQsQ0FBQztJQUVNLEtBQUssQ0FBQyxVQUF5QjtRQUNsQyxPQUFPLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxrQkFBa0IsQ0FBQyxVQUFVLEVBQUUsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQztJQUN2RixDQUFDO0lBSU0sTUFBTSxDQUFDLDhCQUE4QixDQUFDLFFBQWdCO1FBQ3pELE9BQU8sSUFBSSxDQUFDLHlCQUF5QixDQUFDLFFBQVEsQ0FBQyxDQUFDO0lBQ3BELENBQUM7SUFFTSxNQUFNLENBQUMsNEJBQTRCLENBQUMsUUFBZ0IsRUFBRSxLQUFjO1FBQ3ZFLElBQUksQ0FBQyx5QkFBeUIsQ0FBQyxRQUFRLENBQUMsR0FBRyxLQUFLLENBQUM7SUFDckQsQ0FBQzs7QUEvQnNCLFFBQUcsR0FBVyxHQUFHLENBQUM7QUFFbEIscUJBQWdCLEdBQVcsQ0FBQyxLQUFLLEVBQUUsWUFBWSxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztBQUNoRSw2QkFBd0IsR0FBVyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDLEdBQUcsQ0FBQztBQUVwRSx1QkFBa0IsR0FBVyxtREFBbUQsQ0FBQztBQUNqRixnQ0FBMkIsR0FBVyx5REFBeUQsQ0FBQztBQUNoRyw2QkFBd0IsR0FBVyxnRUFBZ0UsQ0FBQztB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Z0JBRTdELE1BQU0sV0FBVyxHQUFHLFFBQVEsQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLENBQUM7Z0JBQ2pELElBQUksQ0FBQyxlQUFlLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxXQUFXLENBQUMsQ0FBQztZQUM5RCxDQUFDLENBQUMsQ0FBQztTQUNWO1FBRUQsS0FBSyxDQUFDLGVBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQztJQUNoQyxDQUFDO0NBQ0oiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgKiBhcyBwYXRoIGZyb20gXCJwYXRoXCI7XHJcbmltcG9ydCAqIGFzIHRzIGZyb20gXCJ0eXBlc2NyaXB0XCI7XHJcbmltcG9ydCAqIGFzIExpbnQgZnJvbSBcInRzbGludFwiO1xyXG5pbXBvcnQgKiBhcyBmcyBmcm9tIFwiZnNcIjtcclxuXHJcbmludGVyZmFjZSBQYXRoRGV0YWlscyB7XHJcbiAgICBwcmVmaXg6IHN0cmluZztcclxuICAgIHN1ZmZpeDogc3RyaW5nO1xyXG4gICAgbW9kdWxlTmFtZTogc3RyaW5nO1xyXG4gICAgZnVsbE1vZHVsZU5hbWU6IHN0cmluZztcclxuICAgIGZpbGVOYW1lOiBzdHJpbmc7XHJcbiAgICBzcGxpdFBhdGg6IHN0cmluZ1tdO1xyXG4gICAgd2l0aFF1b3RlczogYm9vbGVhbjtcclxufVxyXG5cclxuZXhwb3J0IGNsYXNzIFJ1bGUgZXh0ZW5kcyBMaW50LlJ1bGVzLkFic3RyYWN0UnVsZSB7XHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IHNlcDogc3RyaW5nID0gXCIvXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBzZWFyY2hNb2R1bGVQYXRoOiBzdHJpbmcgPSBbXCJhcHBcIiwgXCJjb21wb25lbnRzXCJdLmpvaW4oUnVsZS5zZXApO1xyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSBzZWFyY2hNb2R1bGVQYXRoU3BsaXR0ZXI6IHN0cmluZyA9IFJ1bGUuc2VhcmNoTW9kdWxlUGF0aCArIFJ1bGUuc2VwO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgZW50cnlGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkNvbXBvbmVudHMgc2hvdWxkIGJlIGltcG9ydGVkIGZyb20gYW4gZW50cnkgZmlsZS5cIjtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgaW5zaWRlUmVsYXRpdmVGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkEgcmVsYXRpdmUgaW1wb3J0IHNob3VsZCBiZSB1c2VkIGluc2lkZSB0aGUgY29tcG9uZW50cy5cIjtcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgaW5zaWRlRW50cnlGYWlsdXJlU3RyaW5nOiBzdHJpbmcgPSBcIkFuIGVudHJ5IGZpbGUgaW1wb3J0IHNob3VsZCBub3QgYmUgdXNlZCBpbnNpZGUgdGhlIGNvbXBvbmVudHMuXCI7XHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IGZvcmJpZGRlblJlZXhwb3J0QWxsRmFpbHVyZVN0cmluZzogc3RyaW5nID0gXCJGb3JiaWRkZW4gJ2V4cG9ydCAqIGZyb20nLCB1c2UgbmFtZWQgcmUtZXhwb3J0cy5cIjtcclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIHJlYWRvbmx5IG1vZHVsZUZpbGVuYW1lU3VmZml4OiBzdHJpbmcgPSBcIi1jb21wb25lbnRzXCI7XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyByZWFkb25seSByZWV4cG9ydFBhdGhSZWdleDogUmVnRXhwID0gL2V4cG9ydFtcXHNcXFNdKmZyb21bXFxzXSpbXFwnXFxcIl0oLiopW1xcJ1xcXCJdLztcclxuICAgIHB1YmxpYyBzdGF0aWMgcmVhZG9ubHkgcmVleHBvcnRBbGxQYXRoUmVnZXg6IFJlZ0V4cCA9IC9leHBvcnRbXFxzXFxTXSpcXCovO1xyXG5cclxuICAgIHB1YmxpYyBzdGF0aWMgcmVzb2x2ZU1vZHVsZUZpbGVuYW1lKG1vZHVsZU5hbWU6IHN0cmluZyk6IHN0cmluZyB7XHJcbiAgICAgICAgcmV0dXJuIG1vZHVsZU5hbWUgKyB0aGlzLm1vZHVsZUZpbGVuYW1lU3VmZml4O1xyXG4gICAgfVxyXG5cclxuICAgIHB1YmxpYyBhcHBseShzb3VyY2VGaWxlOiB0cy5Tb3VyY2VGaWxlKTogTGludC5SdWxlRmFpbHVyZVtdIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5hcHBseVdpdGhXYWxrZXIobmV3IEltcG9ydE1vZHVsZVdhbGtlcihzb3VyY2VGaWxlLCB0aGlzLmdldE9wdGlvbnMoKSkpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgc3RhdGljIGNvbXBvbmVudHNFbnRyeUZpbGVzQ2FjaGU6IHsgW2ZpbGVOYW1lOiBzdHJpbmddOiBib29sZWFuIH0gPSB7fTtcclxuXHJcbiAgICBwdWJsaWMgc3RhdGljIGdldENvbXBvbmVudEVudHJ5RmlsZUZyb21DYWNoZShmaWxlTmFtZTogc3RyaW5nKTogdW5kZWZpbmVkIHwgYm9vbGVhbiB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuY29tcG9uZW50c0VudHJ5RmlsZXNDYWNoZVtmaWxlTmFtZV07XHJcbiAgICB9XHJcblxyXG4gICAgcHVibGljIHN0YXRpYyBzZXRDb21wb25lbnRFbnRyeUZpbGVUb0NhY2hlKGZpbGVOYW1lOiBzdHJpbmcsIHZhbHVlOiBib29sZWFuKTogdm9pZCB7XHJcbiAgICAgICAgdGhpcy5jb21wb25lbnRzRW50cnlGaWxlc0NhY2hlW2ZpbGVOYW1lXSA9IHZhbHVlO1xyXG4gICAgfVxyXG59XHJcblxyXG5jbGFzcyBJbXBvcnRNb2R1bGVXYWxrZXIgZXh0ZW5kcyBMaW50LlJ1bGVXYWxrZXIge1xyXG4gICAgLyoqXHJcbiAgICAgKiBVcGRhdGUgaW1wb3J0IHBhdGggd2l0aCBtb2R1bGUgZW50cnkgZmlsZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBpbXBvcnRFbnRyeUZpbGVGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIHByZWZpeDogc3RyaW5nLFxyXG4gICAgICAgIG1vZHVsZU5hbWU6IHN0cmluZyxcclxuICAgICAgICBmdWxsTW9kdWxlTmFtZTogc3RyaW5nLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCByZXNvbHZlZEltcG9ydCA9IFtcclxuICAgICAgICAgICAgcHJlZml4ICsgUnVsZS5zZWFyY2hNb2R1bGVQYXRoLFxyXG4gICAgICAgICAgICBtb2R1bGVOYW1lLFxyXG4gICAgICAgICAgICBmdWxsTW9kdWxlTmFtZSArIHF1b3RlU3ltYm9sXHJcbiAgICAgICAgXS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgcmV0dXJuIG5ldyBMaW50LlJlcGxhY2VtZW50KHN0YXJ0LCBsZW5ndGgsIHJlc29sdmVkSW1wb3J0KTtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIENoYW5nZSBwYXRoIHRvIHJlbGF0aXZlLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIGltcG9ydFdpdGhSZWxhdGl2ZVBhdGhGaXhlcihcclxuICAgICAgICBzdGFydDogbnVtYmVyLFxyXG4gICAgICAgIGxlbmd0aDogbnVtYmVyLFxyXG4gICAgICAgIGltcG9ydEZpbGVOYW1lOiBzdHJpbmcsXHJcbiAgICAgICAgc291cmNlU3BsaXRQYXRoOiBzdHJpbmdbXSxcclxuICAgICAgICBpbXBvcnRTcGxpdFBhdGg6IHN0cmluZ1tdLFxyXG4gICAgICAgIHF1b3RlU3ltYm9sOiBzdHJpbmdcclxuICAgICk6IExpbnQuUmVwbGFjZW1lbnQge1xyXG5cclxuICAgICAgICBjb25zdCBzb3VyY2VQYXRoID0gc291cmNlU3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRQYXRoID0gaW1wb3J0U3BsaXRQYXRoLnNsaWNlKDAsIC0xKS5qb2luKFJ1bGUuc2VwKTtcclxuXHJcbiAgICAgICAgY29uc3QgcmVsYXRpdmVQYXRoID0gcGF0aC5yZWxhdGl2ZShzb3VyY2VQYXRoLCBpbXBvcnRQYXRoKS5zcGxpdChwYXRoLnNlcCk7XHJcbiAgICAgICAgcmVsYXRpdmVQYXRoLnB1c2goaW1wb3J0RmlsZU5hbWUpO1xyXG5cclxuICAgICAgICBsZXQgcmVsYXRpdmVQYXRoU3RyaW5nID0gcmVsYXRpdmVQYXRoLmpvaW4oUnVsZS5zZXApO1xyXG5cclxuICAgICAgICBpZiAocmVsYXRpdmVQYXRoU3RyaW5nWzBdID09PSBSdWxlLnNlcCkge1xyXG4gICAgICAgICAgICByZWxhdGl2ZVBhdGhTdHJpbmcgPSBcIi5cIiArIHJlbGF0aXZlUGF0aFN0cmluZztcclxuICAgICAgICB9IGVsc2UgaWYgKHJlbGF0aXZlUGF0aFN0cmluZ1swXSAhPT0gXCIuXCIpIHtcclxuICAgICAgICAgICAgcmVsYXRpdmVQYXRoU3RyaW5nID0gYC4ke1J1bGUuc2VwfSR7cmVsYXRpdmVQYXRoU3RyaW5nfWA7XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBjb25zdCBmaXhlZFBhdGggPSBgJHtxdW90ZVN5bWJvbH0ke3JlbGF0aXZlUGF0aFN0cmluZ30ke3F1b3RlU3ltYm9sfWA7XHJcblxyXG4gICAgICAgIHJldHVybiBuZXcgTGludC5SZXBsYWNlbWVudChzdGFydCwgbGVuZ3RoLCBmaXhlZFBhdGgpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2VuZXJhdGUgcGF0aCBkZXRhaWxzIG9iamVjdCBmcm9tIHBhdGhuYW1lLlxyXG4gICAgICovXHJcbiAgICBwcml2YXRlIHBhcnNlUGF0aERldGFpbHMocGF0aG5hbWU6IHN0cmluZywgd2l0aFF1b3RlczogYm9vbGVhbiA9IHRydWUpOiBQYXRoRGV0YWlscyB7XHJcbiAgICAgICAgY29uc3QgW3ByZWZpeCwgc3VmZml4XSA9IHBhdGhuYW1lLnNwbGl0KFJ1bGUuc2VhcmNoTW9kdWxlUGF0aFNwbGl0dGVyKTtcclxuICAgICAgICBjb25zdCBbbW9kdWxlTmFtZSwgLi4uaW1wb3J0U3BsaXRQYXRoXSA9IHN1ZmZpeC5zcGxpdChSdWxlLnNlcCk7XHJcblxyXG4gICAgICAgIGlmICh3aXRoUXVvdGVzKSB7XHJcbiAgICAgICAgICAgIGltcG9ydFNwbGl0UGF0aFtpbXBvcnRTcGxpdFBhdGgubGVuZ3RoIC0gMV0gPSBpbXBvcnRTcGxpdFBhdGhbaW1wb3J0U3BsaXRQYXRoLmxlbmd0aCAtIDFdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IFtmaWxlTmFtZV0gPSBpbXBvcnRTcGxpdFBhdGguc2xpY2UoLTEpO1xyXG5cclxuICAgICAgICByZXR1cm4ge1xyXG4gICAgICAgICAgICBwcmVmaXg6IHByZWZpeCxcclxuICAgICAgICAgICAgc3VmZml4OiBzdWZmaXgsXHJcbiAgICAgICAgICAgIG1vZHVsZU5hbWU6IG1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgIGZ1bGxNb2R1bGVOYW1lOiBSdWxlLnJlc29sdmVNb2R1bGVGaWxlbmFtZShtb2R1bGVOYW1lKSxcclxuICAgICAgICAgICAgc3BsaXRQYXRoOiBpbXBvcnRTcGxpdFBhdGgsXHJcbiAgICAgICAgICAgIGZpbGVOYW1lOiBmaWxlTmFtZSxcclxuICAgICAgICAgICAgd2l0aFF1b3Rlczogd2l0aFF1b3Rlc1xyXG4gICAgICAgIH07XHJcbiAgICB9XHJcblxyXG4gICAgLyoqXHJcbiAgICAgKiBWYWxpZGF0ZSBpbXBvcnQgbGluZS5cclxuICAgICAqL1xyXG4gICAgcHJpdmF0ZSBzdGFydFZhbGlkYXRpbmcoc291cmNlRmlsZTogc3RyaW5nLCBpbXBvcnRGaWxlOiBzdHJpbmcsIGltcG9ydFN0YXJ0OiBudW1iZXIsIHF1b3RlOiBzdHJpbmcgPSBcIlwiKTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSA9IGltcG9ydEZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcblxyXG4gICAgICAgIGlmICghc291cmNlRmlsZUlzRnJvbU1vZHVsZSAmJiAhaW1wb3J0RmlsZUlzRnJvbU1vZHVsZSkge1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICAvLyBDaGVjayBpZiBpbXBvcnRpbmcgZmlsZSBpcyBub3QgZnJvbSBtb2R1bGVcclxuICAgICAgICBpZiAoIWltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHNvdXJjZSBmaWxlIGlzIGZyb20gbW9kdWxlXHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlKSB7XHJcbiAgICAgICAgICAgICAgICBjb25zdCBzb3VyY2VEZXRhaWxzID0gdGhpcy5wYXJzZVBhdGhEZXRhaWxzKHNvdXJjZUZpbGUsIGZhbHNlKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydEZpbGVOYW1lID0gaW1wb3J0RmlsZS5zcGxpdChSdWxlLnNlcCkuc2xpY2UoLTEpWzBdLnNsaWNlKDAsIC0xKTtcclxuICAgICAgICAgICAgICAgIGNvbnN0IHRhcmdldEZpbGVOYW1lID0gc291cmNlRGV0YWlscy5mdWxsTW9kdWxlTmFtZTtcclxuXHJcbiAgICAgICAgICAgICAgICAvLyBDaGVjayBpZiBtb2R1bGUgaXRzZWxmIGRvZXNuJ3QgaW1wb3J0IGZyb20gZW50cnkgZmlsZVxyXG4gICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGVOYW1lID09PSB0YXJnZXRGaWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVFbnRyeUZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGltcG9ydERldGFpbHMgPSB0aGlzLnBhcnNlUGF0aERldGFpbHMoaW1wb3J0RmlsZSwgQm9vbGVhbihxdW90ZSkpO1xyXG4gICAgICAgIGlmIChzb3VyY2VGaWxlSXNGcm9tTW9kdWxlICYmIGltcG9ydEZpbGVJc0Zyb21Nb2R1bGUpIHtcclxuICAgICAgICAgICAgY29uc3Qgc291cmNlRGV0YWlscyA9IHRoaXMucGFyc2VQYXRoRGV0YWlscyhzb3VyY2VGaWxlLCBmYWxzZSk7XHJcbiAgICAgICAgICAgIGlmIChzb3VyY2VEZXRhaWxzLm1vZHVsZU5hbWUgPT09IGltcG9ydERldGFpbHMubW9kdWxlTmFtZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZml4ID0gdGhpcy5pbXBvcnRXaXRoUmVsYXRpdmVQYXRoRml4ZXIoXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0U3RhcnQsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RmlsZS5sZW5ndGgsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5maWxlTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBzb3VyY2VEZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLnNwbGl0UGF0aCxcclxuICAgICAgICAgICAgICAgICAgICBxdW90ZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5pbnNpZGVSZWxhdGl2ZUZhaWx1cmVTdHJpbmcsIGZpeCk7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChpbXBvcnRGaWxlSXNGcm9tTW9kdWxlICYmIChpbXBvcnREZXRhaWxzLnNwbGl0UGF0aC5sZW5ndGggPiAxIHx8IGltcG9ydERldGFpbHMuZnVsbE1vZHVsZU5hbWUgIT09IGltcG9ydERldGFpbHMuZmlsZU5hbWUpKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IGZyb21DYWNoZSA9IFJ1bGUuZ2V0Q29tcG9uZW50RW50cnlGaWxlRnJvbUNhY2hlKGltcG9ydERldGFpbHMuZnVsbE1vZHVsZU5hbWUpO1xyXG4gICAgICAgICAgICBsZXQgaXNDb21wb25lbnRzV2l0aEVudHJ5OiBib29sZWFuO1xyXG4gICAgICAgICAgICBpZiAoZnJvbUNhY2hlID09IG51bGwpIHtcclxuICAgICAgICAgICAgICAgIGlzQ29tcG9uZW50c1dpdGhFbnRyeSA9IGZzLmV4aXN0c1N5bmMoaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSk7XHJcbiAgICAgICAgICAgICAgICBSdWxlLnNldENvbXBvbmVudEVudHJ5RmlsZVRvQ2FjaGUoaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSwgaXNDb21wb25lbnRzV2l0aEVudHJ5KTtcclxuICAgICAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgICAgIGlzQ29tcG9uZW50c1dpdGhFbnRyeSA9IGZyb21DYWNoZTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgaWYgKGlzQ29tcG9uZW50c1dpdGhFbnRyeSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgZml4ID0gdGhpcy5pbXBvcnRFbnRyeUZpbGVGaXhlcihcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRTdGFydCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnRGaWxlLmxlbmd0aCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLnByZWZpeCxcclxuICAgICAgICAgICAgICAgICAgICBpbXBvcnREZXRhaWxzLm1vZHVsZU5hbWUsXHJcbiAgICAgICAgICAgICAgICAgICAgaW1wb3J0RGV0YWlscy5mdWxsTW9kdWxlTmFtZSxcclxuICAgICAgICAgICAgICAgICAgICBxdW90ZVxyXG4gICAgICAgICAgICAgICAgKTtcclxuICAgICAgICAgICAgICAgIHRoaXMuYWRkRmFpbHVyZUF0KGltcG9ydFN0YXJ0LCBpbXBvcnRGaWxlLmxlbmd0aCwgUnVsZS5lbnRyeUZhaWx1cmVTdHJpbmcsIGZpeCk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKGZ1bGxUZXh0OiBzdHJpbmcsIHNvdXJjZUZpbGU6IHN0cmluZywgbm9kZTogdHMuU3RhdGVtZW50KTogdm9pZCB7XHJcbiAgICAgICAgY29uc3Qgc291cmNlRmlsZUlzRnJvbU1vZHVsZSA9IHNvdXJjZUZpbGUuaW5kZXhPZihSdWxlLnNlYXJjaE1vZHVsZVBhdGgpID4gLTE7XHJcbiAgICAgICAgaWYgKHNvdXJjZUZpbGVJc0Zyb21Nb2R1bGUgJiYgUnVsZS5yZWV4cG9ydEFsbFBhdGhSZWdleC50ZXN0KGZ1bGxUZXh0KSkge1xyXG4gICAgICAgICAgICB0aGlzLmFkZEZhaWx1cmVBdE5vZGUobm9kZSwgUnVsZS5mb3JiaWRkZW5SZWV4cG9ydEFsbEZhaWx1cmVTdHJpbmcpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFZpc2l0IG9uIGltcG9ydCBkZWNsYXJhdGlvbiBmb3VuZC5cclxuICAgICAqL1xyXG4gICAgcHVibGljIHZpc2l0SW1wb3J0RGVjbGFyYXRpb24obm9kZTogdHMuSW1wb3J0RGVjbGFyYXRpb24pOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5nZXRTb3VyY2VGaWxlKCkuZmlsZU5hbWU7XHJcbiAgICAgICAgY29uc3QgaW1wb3J0RmlsZSA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFRleHQoKTtcclxuICAgICAgICBjb25zdCBpbXBvcnRTdGFydCA9IG5vZGUubW9kdWxlU3BlY2lmaWVyLmdldFN0YXJ0KCk7XHJcbiAgICAgICAgY29uc3QgcXVvdGVTeW1ib2wgPSBpbXBvcnRGaWxlWzBdO1xyXG5cclxuICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCwgcXVvdGVTeW1ib2wpO1xyXG5cclxuICAgICAgICBzdXBlci52aXNpdEltcG9ydERlY2xhcmF0aW9uKG5vZGUpO1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogVmlzaXQgb24gYW55IHNvdXJjZSBmaWxlLlxyXG4gICAgICovXHJcbiAgICBwdWJsaWMgdmlzaXRTb3VyY2VGaWxlKG5vZGU6IHRzLlNvdXJjZUZpbGUpOiB2b2lkIHtcclxuICAgICAgICBjb25zdCBmdWxsVGV4dCA9IG5vZGUuZ2V0RnVsbFRleHQoKTtcclxuICAgICAgICBjb25zdCBzb3VyY2VGaWxlID0gbm9kZS5maWxlTmFtZTtcclxuXHJcbiAgICAgICAgaWYgKG5vZGUuc3RhdGVtZW50cy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIG5vZGUuc3RhdGVtZW50c1xyXG4gICAgICAgICAgICAgICAgLmZpbHRlcih4ID0+IHgua2luZCA9PT0gdHMuU3ludGF4S2luZC5FeHBvcnREZWNsYXJhdGlvbiAmJiB4LmdldEZ1bGxUZXh0KCkuaW5kZXhPZihcImZyb21cIikgPiAtMSlcclxuICAgICAgICAgICAgICAgIC5mb3JFYWNoKHN0YXRlbWVudCA9PiB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgdGV4dCA9IHN0YXRlbWVudC5nZXRGdWxsVGV4dCgpO1xyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWdleFJlc3VsdCA9IFJ1bGUucmVleHBvcnRQYXRoUmVnZXguZXhlYyh0ZXh0KTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocmVnZXhSZXN1bHQgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICBjb25zdCBpbXBvcnRGaWxlID0gcmVnZXhSZXN1bHRbMV07XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKGltcG9ydEZpbGUgPT0gbnVsbCkge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZ1JlRXhwb3J0QWxsKHRleHQsIHNvdXJjZUZpbGUsIHN0YXRlbWVudCk7XHJcblxyXG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IGltcG9ydFN0YXJ0ID0gZnVsbFRleHQuaW5kZXhPZihpbXBvcnRGaWxlKTtcclxuICAgICAgICAgICAgICAgICAgICB0aGlzLnN0YXJ0VmFsaWRhdGluZyhzb3VyY2VGaWxlLCBpbXBvcnRGaWxlLCBpbXBvcnRTdGFydCk7XHJcbiAgICAgICAgICAgICAgICB9KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHN1cGVyLnZpc2l0U291cmNlRmlsZShub2RlKTtcclxuICAgIH1cclxufVxyXG4iXX0=