tslint-immutable
Version:
TSLint rules to disable mutation in TypeScript.
181 lines • 6.7 kB
JavaScript
"use strict";
/**
* This file has code that is shared for all the ignore options.
*/
Object.defineProperty(exports, "__esModule", { value: true });
var ts = require("typescript");
var utils_1 = require("tslint/lib/utils");
var utils = require("tsutils/typeguard/2.8");
var typeguard_1 = require("./typeguard");
function checkNodeWithIgnore(checkNode) {
return function (node, ctx) {
// Skip checking in functions if ignore-local is set
if (ctx.options.ignoreLocal && typeguard_1.isFunctionLikeDeclaration(node)) {
// We still need to check the parameters and return type
var invalidNodes = checkIgnoreLocalFunctionNode(node, ctx, checkNode);
// Now skip this whole branch
return { invalidNodes: invalidNodes, skipChildren: true };
}
// Skip checking in classes/interfaces if ignore-class/ignore-interface is set
if ((ctx.options.ignoreClass && utils.isPropertyDeclaration(node)) ||
(ctx.options.ignoreInterface && utils.isPropertySignature(node))) {
// Now skip this whole branch
return { invalidNodes: [], skipChildren: true };
}
// Forward to check node
return checkNode(node, ctx);
};
}
exports.checkNodeWithIgnore = checkNodeWithIgnore;
function checkIgnoreLocalFunctionNode(functionNode, ctx, checkNode) {
var myInvalidNodes = [];
var cb = function (node) {
// Check the node
var _a = checkNode(node, ctx), invalidNodes = _a.invalidNodes, skipChildren = _a.skipChildren;
if (invalidNodes) {
myInvalidNodes = myInvalidNodes.concat.apply(myInvalidNodes, invalidNodes);
}
if (skipChildren) {
return;
}
// Use return because performance hints docs say it optimizes the function using tail-call recursion
return ts.forEachChild(node, cb);
};
// Check either the parameter's explicit type if it has one, or itself for implicit type
for (var _i = 0, _a = functionNode.parameters.map(function (p) { return (p.type ? p.type : p); }); _i < _a.length; _i++) {
var n = _a[_i];
// Check the parameter node itself
var invalidCheckNodes = checkNode(n, ctx).invalidNodes;
if (invalidCheckNodes) {
myInvalidNodes = myInvalidNodes.concat.apply(myInvalidNodes, invalidCheckNodes);
}
// Check all children for the paramter node
ts.forEachChild(n, cb);
}
// Check the return type
var nt = functionNode.type;
if (nt) {
// Check the return type node itself
var invalidCheckNodes = checkNode(nt, ctx).invalidNodes;
if (invalidCheckNodes) {
myInvalidNodes = myInvalidNodes.concat.apply(myInvalidNodes, invalidCheckNodes);
}
// Check all children for the return type node
ts.forEachChild(nt, cb);
}
return myInvalidNodes;
}
function shouldIgnore(node, options, sourceFile) {
// Check ignore for VariableLikeDeclaration, TypeAliasDeclaration
if (node &&
(typeguard_1.isVariableLikeDeclaration(node) || utils.isTypeAliasDeclaration(node))) {
var variableText = node.name.getText(sourceFile);
if (isIgnoredPattern(variableText, options.ignorePattern)) {
return true;
}
if (isIgnoredPrefix(variableText, options.ignorePrefix)) {
return true;
}
if (isIgnoredSuffix(variableText, options.ignoreSuffix)) {
return true;
}
}
return false;
}
exports.shouldIgnore = shouldIgnore;
function isIgnored(node, ignorePattern, ignorePrefix, ignoreSuffix) {
var text = node.getText();
if (isIgnoredPrefix(text, ignorePrefix) ||
isIgnoredSuffix(text, ignoreSuffix) ||
isIgnoredPattern(node.getText(), ignorePattern)) {
return true;
}
if (typeguard_1.hasExpression(node)) {
return isIgnored(node.expression, undefined, ignorePrefix, ignoreSuffix);
}
return false;
}
exports.isIgnored = isIgnored;
function isIgnoredPrefix(text, ignorePrefix) {
if (!ignorePrefix) {
return false;
}
if (Array.isArray(ignorePrefix)) {
if (ignorePrefix.find(function (pfx) { return text.indexOf(pfx) === 0; })) {
return true;
}
}
else {
if (text.indexOf(ignorePrefix) === 0) {
return true;
}
}
return false;
}
function isIgnoredSuffix(text, ignoreSuffix) {
if (!ignoreSuffix) {
return false;
}
if (Array.isArray(ignoreSuffix)) {
if (ignoreSuffix.find(function (sfx) {
var indexToFindAt = text.length - sfx.length;
return indexToFindAt >= 0 && text.indexOf(sfx) === indexToFindAt;
})) {
return true;
}
}
else {
var indexToFindAt = text.length - ignoreSuffix.length;
if (indexToFindAt >= 0 && text.indexOf(ignoreSuffix) === indexToFindAt) {
return true;
}
}
return false;
}
function isIgnoredPattern(text, ignorePattern) {
if (!ignorePattern) {
return false;
}
var patterns = Array.isArray(ignorePattern)
? ignorePattern
: [ignorePattern];
var findMatch = function (patternParts, textParts) {
var index = 0;
for (; index < patternParts.length; index++) {
// Out of text?
if (index >= textParts.length) {
return false;
}
switch (patternParts[index]) {
// Match any depth (including 0)?
case "**":
var subpattern = patternParts.slice(index + 1);
for (var offset = index; offset < textParts.length; offset++) {
var submatch = findMatch(subpattern, textParts.slice(offset));
if (submatch) {
return submatch;
}
}
return false;
// Match anything?
case "*":
continue;
default:
break;
}
// textParts[i] matches patternParts[i]?
if (new RegExp("^" + utils_1.escapeRegExp(patternParts[index]).replace(/\\\*/g, ".*") + "$").test(textParts[index])) {
continue;
}
// No Match.
return false;
}
// Match.
return textParts.length === index;
};
// One or more patterns match?
return patterns.some(function (pattern) {
return findMatch(pattern.split("."), text.split("."));
});
}
//# sourceMappingURL=ignore.js.map