tslint-filter
Version:
Suppress and extend TSLint linting errors, before they get returned to the console or your code editor
138 lines (137 loc) • 5.18 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const toRegexRange = require("to-regex-range");
const Lint = require("tslint");
function addFilter(ruleFile, options = {}) {
const linterOrError = getLinter(ruleFile);
if (linterOrError instanceof Error) {
const error = linterOrError;
class Rule extends Lint.Rules.AbstractRule {
apply(sourceFile) {
return [getFailureByError(error, ruleFile, this.ruleName, sourceFile)];
}
}
Rule.metadata = {
ruleName: getRuleNameByFileName(ruleFile),
type: 'functionality',
description: `Error while loading '${ruleFile}'.`,
optionsDescription: 'Not configurable.',
options: null,
typescriptOnly: false
};
return { Rule };
}
const linter = linterOrError;
const RulePrototype = linter.Rule.prototype;
if (Lint.isTypedRule(RulePrototype)) {
RulePrototype.applyWithProgram = applyWithFilter(linter, RulePrototype.applyWithProgram, ruleFile, options);
}
else {
RulePrototype.apply = applyWithFilter(linter, RulePrototype.apply, ruleFile, options);
}
return linter;
}
addFilter.rulesDirectory = '../rules';
module.exports = addFilter;
function getLinter(ruleFile) {
try {
return require(ruleFile);
}
catch (error) {
if (error instanceof Error) {
return error;
}
return new Error(`Unable to load ${ruleFile}.`);
}
}
function applyWithFilter(linter, originalApplyMethod, ruleFile, options) {
const ruleName = linter.Rule.metadata.ruleName;
return function (sourceFile, program) {
this.options.ruleName = ruleName;
this.ruleName = ruleName;
const ignorePatternsOrFailure = extractIgnorePatterns(this, sourceFile);
let failures;
try {
if (program === undefined) {
failures = originalApplyMethod.call(this, sourceFile);
}
else {
failures = originalApplyMethod.call(this, sourceFile, program);
}
}
catch (error) {
failures = [getFailureByError(error, ruleFile, this.ruleName, sourceFile)];
}
if (typeof options.modifyFailure === 'function') {
const modifyFailure = options.modifyFailure.bind(this);
failures = failures
.map((failure) => updateFailure(sourceFile, failure, modifyFailure(failure, sourceFile, program)))
.filter(isFailure);
}
if (ignorePatternsOrFailure instanceof Lint.RuleFailure) {
failures.push(ignorePatternsOrFailure);
}
else if (ignorePatternsOrFailure !== undefined) {
failures = failures.filter((failure) => (!ignorePatternsOrFailure.some((regex) => regex.test(failure.getFailure()))));
}
return failures;
};
}
function getRuleNameByFileName(ruleFile) {
return ruleFile.replace(/^.*\/|Rule\.?.*$/g, '').replace(/([A-Z])/g, '-$1').toLowerCase();
}
function extractIgnorePatterns(rule, sourceFile) {
const ruleArguments = rule.getOptions().ruleArguments;
const lastRuleArgument = ruleArguments[ruleArguments.length - 1];
if (!Array.isArray(lastRuleArgument)) {
return undefined;
}
let ignorePatterns;
try {
ignorePatterns = lastRuleArgument.map(stringToRegExp);
}
catch (error) {
if (error instanceof Error) {
return new Lint.RuleFailure(sourceFile, 0, 1, `TSLint-Filter ignore pattern: ${error.message}`, rule.ruleName);
}
return undefined;
}
rule.ruleArguments = ruleArguments.slice(0, -1);
rule.options.ruleArguments = rule.ruleArguments;
return ignorePatterns;
}
function stringToRegExp(str) {
return new RegExp(str.replace(/\[(\d*)\.\.\.(\d*)\]/g, (_match, p1, p2) => toRegexRange(p1 !== '' ? p1 : -999999999999999, p2 !== '' ? p2 : 999999999999999, { shorthand: true })));
}
function getFailureByError(error, ruleFile, originalRuleName, sourceFile) {
let title;
let message;
if (error instanceof Error) {
title = error.name;
message = error.message.replace(/\n.+/g, '');
}
else if (typeof error === 'string') {
title = 'Error';
message = error;
}
else {
title = 'Unhandled error';
if (error !== null &&
error !== undefined) {
message = `Unknown error of type ${error.constructor.name}`;
}
else {
message = `Unknown error of type '${typeof error}'`;
}
}
return new Lint.RuleFailure(sourceFile, 0, 1, `${title} in '${ruleFile}': ${message}. Rule is disabled for this file`, originalRuleName);
}
function updateFailure(sourceFile, failure, newFailure) {
if (typeof newFailure === 'string') {
return new Lint.RuleFailure(sourceFile, failure.getStartPosition().getPosition(), failure.getEndPosition().getPosition(), newFailure, failure.getRuleName(), failure.getFix());
}
return newFailure;
}
function isFailure(failure) {
return failure !== undefined;
}