Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

tslint-immutable

Package Overview
Dependencies
Maintainers
1
Versions
56
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

tslint-immutable - npm Package Compare versions

Comparing version 3.1.2 to 3.2.0

10

CHANGELOG.md

@@ -9,2 +9,9 @@ # Change Log

## [v3.2.0] - 2017-04-10
### Fixed
- readonly-array does not check shorthand syntax in return types with ignore-local option [#21](https://github.com/jonaskello/tslint-immutable/issues/21)
### Added
- Fixer for the `readonly-array` rule.
## [v3.1.2] - 2017-04-09

@@ -69,3 +76,4 @@ ### Fixed

[Unreleased]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.2...master
[Unreleased]: https://github.com/jonaskello/tslint-immutable/compare/v3.2.0...master
[v3.2.0]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.2...v3.2.0
[v3.1.2]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.1...v3.1.2

@@ -72,0 +80,0 @@ [v3.1.1]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.0...v3.1.1

2

package.json
{
"name": "tslint-immutable",
"version": "3.1.2",
"version": "3.2.0",
"description": "TSLint rules to disable mutation in TypeScript.",

@@ -5,0 +5,0 @@ "main": "index.js",

@@ -113,7 +113,10 @@ # tslint-immutable

Options:
##### Has Fixer
Yes
##### Options:
- [ignore-local](#using-the-ignore-local-option)
- [ignore-prefix](#using-the-ignore-prefix-option)
Example config:
##### Example config:
```javascript

@@ -120,0 +123,0 @@ "readonly-array": true

@@ -35,4 +35,5 @@ "use strict";

var myOptions = getMyOptions(this.getOptions());
if (!myOptions)
if (!myOptions) {
return;
}
var containmentPath = myOptions.containmentPath, allowedExternalFileNames = myOptions.allowedExternalFileNames, disallowedInternalFileNames = myOptions.disallowedInternalFileNames;

@@ -43,3 +44,3 @@ var sourceFileRelativePath = getSourceFilePathRelativeToContainmentPath(this.getSourceFile().path, containmentPath);

// Remove the file name to get the path
var sourceDirRelativePath = sourceFileRelativePath.substring(0, sourceFileRelativePath.lastIndexOf('/'));
var sourceDirRelativePath = sourceFileRelativePath.substring(0, sourceFileRelativePath.lastIndexOf("/"));
// Check that it is a sub directory under the containment path

@@ -52,3 +53,3 @@ if (sourceDirRelativePath.length > containmentPath.length) {

// Get the file name being imported
var importFileName = importRelativePath.substring(importRelativePath.lastIndexOf('/') + 1);
var importFileName = importRelativePath.substring(importRelativePath.lastIndexOf("/") + 1);
// Get how many levels below the containment path the file resides

@@ -61,6 +62,9 @@ var levelsBelowPath = getLevelsBelowPath(containmentPath, sourceDirRelativePath);

// Relative import paths are not allowed to reach up to the containment path
//throw Error("sourceDirPath: " + sourceDirRelativePath + ", importRelativePath: " + importRelativePath + ", highestParentLevel: " + highestParentLevel + ", levelsBelowPath: " + levelsBelowPath + ", sourceFileName" + sourceFileName);
//throw Error("sourceDirPath: " + sourceDirRelativePath + ", importRelativePath: "
//+ importRelativePath + ", highestParentLevel: " + highestParentLevel + ", levelsBelowPath: " +
//levelsBelowPath + ", sourceFileName" + sourceFileName);
// create a failure at the current position
if (allowedExternalFileNames.indexOf(importFileName) === -1)
if (allowedExternalFileNames.indexOf(importFileName) === -1) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING));
}
}

@@ -70,4 +74,5 @@ else {

// are not allowed to import certain file names
if (disallowedInternalFileNames.indexOf(importFileName) !== -1)
if (disallowedInternalFileNames.indexOf(importFileName) !== -1) {
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING2));
}
}

@@ -96,7 +101,9 @@ }

var myOptions = options[0]; // "src/app";
if (!myOptions)
if (!myOptions) {
return undefined;
}
var containmentPath = myOptions.containmentPath, allowedExternalFileNames = myOptions.allowedExternalFileNames, disallowedInternalFileNames = myOptions.disallowedInternalFileNames;
if (!containmentPath)
if (!containmentPath) {
return undefined;
}
return {

@@ -103,0 +110,0 @@ containmentPath: containmentPath,

@@ -29,2 +29,5 @@ "use strict";

var OPTION_IGNORE_PREFIX = "ignore-prefix";
function createInvalidNode(node, replacement) {
return { node: node, replacement: replacement };
}
function parseOptions(options) {

@@ -35,3 +38,3 @@ var ignoreLocal = options.indexOf(OPTION_IGNORE_LOCAL) !== -1;

var o = options_1[_i];
if (typeof o === "object" && o[OPTION_IGNORE_PREFIX] != null) {
if (typeof o === "object" && o[OPTION_IGNORE_PREFIX] !== null) {
ignorePrefix = o[OPTION_IGNORE_PREFIX];

@@ -50,9 +53,9 @@ break;

var functionNode = node; //tslint:disable-line
checkFunctionNode(functionNode, ctx);
var invalidNodes = checkIgnoreLocalFunctionNode(functionNode, ctx);
invalidNodes.forEach(function (n) { return reportInvalidNode(n, ctx); });
// Now skip this whole branch
return;
}
// Check the node
checkArrayTypeReference(node, ctx);
checkArrayType(node, ctx);
checkArrayLiteralExpression(node, ctx);
reportInvalidNode(checkNode(node, ctx), ctx);
// Use return becuase performance hints docs say it optimizes the function using tail-call recursion

@@ -62,64 +65,96 @@ return ts.forEachChild(node, cb);

}
function checkFunctionNode(node, ctx) {
// Check the parameters
for (var _i = 0, _a = node.parameters; _i < _a.length; _i++) {
var parameter = _a[_i];
if (parameter.type) {
checkArrayTypeReference(parameter.type, ctx);
checkArrayType(parameter.type, ctx);
function checkNode(node, ctx) {
return checkArrayTypeOrReference(node, ctx) || checkVariableOrParameterImplicitType(node, ctx);
}
function reportInvalidNode(invalidNode, ctx) {
if (invalidNode) {
ctx.addFailureAtNode(invalidNode.node, Rule.FAILURE_STRING, invalidNode.replacement);
}
}
function checkIgnoreLocalFunctionNode(functionNode, ctx) {
var invalidNodes = [];
// Check either the parameter's explicit type if it has one, or itself for implict 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];
var invalidNode = checkNode(n, ctx);
if (invalidNode) {
invalidNodes.push(invalidNode);
}
else if (parameter.initializer) {
checkArrayLiteralExpression(parameter.initializer, ctx);
}
}
// Check the return type
if (node.type) {
checkArrayTypeReference(node.type, ctx);
if (functionNode.type) {
var invalidNode = checkNode(functionNode.type, ctx);
if (invalidNode) {
invalidNodes.push(invalidNode);
}
}
return invalidNodes;
}
function checkArrayType(node, ctx) {
if (node.kind === ts.SyntaxKind.ArrayType) {
if (ctx.options.ignorePrefix) {
var variableDeclarationNode = node.parent;
if (variableDeclarationNode.name.getText(ctx.sourceFile).substr(0, ctx.options.ignorePrefix.length) === ctx.options.ignorePrefix) {
return;
function checkArrayTypeOrReference(node, ctx) {
// We need to check both shorthand syntax "number[]" and type reference "Array<number>"
if (node.kind === ts.SyntaxKind.ArrayType
|| (node.kind === ts.SyntaxKind.TypeReference && node.typeName.getText(ctx.sourceFile) === "Array")) {
if (node.parent && shouldIgnorePrefix(node.parent, ctx.options, ctx.sourceFile)) {
return undefined;
}
var typeArgument = "T";
if (node.kind === ts.SyntaxKind.ArrayType) {
var typeNode = node;
typeArgument = typeNode.elementType.getFullText(ctx.sourceFile).trim();
}
else if (node.kind === ts.SyntaxKind.TypeReference) {
var typeNode = node;
if (typeNode.typeArguments) {
typeArgument = typeNode.typeArguments[0].getFullText(ctx.sourceFile).trim();
}
}
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
return;
var length_1 = node.getWidth(ctx.sourceFile);
return createInvalidNode(node, new Lint.Replacement(node.end - length_1, length_1, "ReadonlyArray<" + typeArgument + ">"));
}
return undefined;
}
function checkArrayTypeReference(node, ctx) {
if (node.kind === ts.SyntaxKind.TypeReference) {
var typeRefNode = node;
if (typeRefNode.typeName.getText(ctx.sourceFile) === "Array") {
if (ctx.options.ignorePrefix) {
var variableDeclarationNode = node.parent;
if (variableDeclarationNode.name.getText(ctx.sourceFile).substr(0, ctx.options.ignorePrefix.length) === ctx.options.ignorePrefix) {
return;
}
function checkVariableOrParameterImplicitType(node, ctx) {
if (node.kind === ts.SyntaxKind.VariableDeclaration || node.kind === ts.SyntaxKind.Parameter) {
// The initializer is used to set and implicit type
var varOrParamNode = node;
if (shouldIgnorePrefix(node, ctx.options, ctx.sourceFile)) {
return undefined;
}
if (!varOrParamNode.type) {
if (varOrParamNode.initializer && varOrParamNode.initializer.kind === ts.SyntaxKind.ArrayLiteralExpression) {
var length_2 = varOrParamNode.name.getWidth(ctx.sourceFile);
var nameText = varOrParamNode.name.getText(ctx.sourceFile);
var typeArgument = "any";
// Not sure it is a good idea to guess what the element types are...
// const arrayLiteralNode = varOrParamNode.initializer as ts.ArrayLiteralExpression;
// if (arrayLiteralNode.elements.length > 0) {
// const element = arrayLiteralNode.elements[0];
// if (element.kind === ts.SyntaxKind.NumericLiteral) {
// typeArgument = "number";
// } else if (element.kind === ts.SyntaxKind.StringLiteral) {
// typeArgument = "string";
// } else if (element.kind === ts.SyntaxKind.TrueKeyword || element.kind === ts.SyntaxKind.FalseKeyword) {
// typeArgument = "boolean";
// }
// }
return createInvalidNode(varOrParamNode.name, new Lint.Replacement(varOrParamNode.name.end - length_2, length_2, nameText + ": ReadonlyArray<" + typeArgument + ">"));
}
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
}
return;
}
return undefined;
}
function checkArrayLiteralExpression(node, ctx) {
if (node.kind === ts.SyntaxKind.ArrayLiteralExpression) {
// If the array literal is used in a variable declaration, the variable
// must have a type spcecified, otherwise it will implicitly be of mutable Array type
// It could also be a function parameter that has an array literal as default value
if (node.parent && (node.parent.kind === ts.SyntaxKind.VariableDeclaration || node.parent.kind === ts.SyntaxKind.Parameter)) {
var parent_1 = node.parent;
if (!parent_1.type) {
if (ctx.options.ignorePrefix &&
parent_1.name.getText(ctx.sourceFile).substr(0, ctx.options.ignorePrefix.length) === ctx.options.ignorePrefix) {
return;
}
var variableDeclarationNode = node.parent;
ctx.addFailureAtNode(variableDeclarationNode.name, Rule.FAILURE_STRING);
function shouldIgnorePrefix(node, options, sourceFile) {
// Check ignore-prefix for VariableDeclaration, PropertySignature, TypeAliasDeclaration, Parameter
if (options.ignorePrefix) {
if (node && (node.kind === ts.SyntaxKind.VariableDeclaration
|| node.kind === ts.SyntaxKind.Parameter
|| node.kind === ts.SyntaxKind.PropertySignature
|| node.kind === ts.SyntaxKind.TypeAliasDeclaration)) {
var variableDeclarationNode = node;
if (variableDeclarationNode.name.getText(sourceFile).substr(0, options.ignorePrefix.length) === options.ignorePrefix) {
return true;
}
}
return;
}
return false;
}
{
"rules": {
"no-any": true
"no-any": true,
"no-internal-module": true,
"no-namespace": true,
"no-reference": true,
"no-var-requires": true,
"typedef": [
true,
"call-signature",
"parameter",
"property-declaration"
],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
},
{
"call-signature": "onespace",
"index-signature": "onespace",
"parameter": "onespace",
"property-declaration": "onespace",
"variable-declaration": "onespace"
}
],
"curly": true,
"forin": true,
"label-position": true,
"no-arg": true,
"no-bitwise": true,
"no-conditional-assignment": true,
// "no-console": [
// true,
// "log"
// ],
"no-construct": true,
"no-debugger": true,
"no-duplicate-variable": true,
"no-empty": true,
"no-eval": true,
"no-invalid-this": true,
"no-null-keyword": true,
"no-shadowed-variable": true,
// "no-string-literal": true,
"no-switch-case-fall-through": true,
"no-unsafe-finally": true,
"no-unused-expression": true,
"no-var-keyword": true,
"radix": true,
"switch-default": true,
"triple-equals": true,
"use-isnan": true,
"eofline": true,
"indent": [
true,
"spaces"
],
"max-file-line-count": [
true,
500
],
"max-line-length": [
true,
160
],
"no-default-export": true,
"no-mergeable-namespace": true,
"no-require-imports": true,
"align": [
true,
"statements"
],
"arrow-parens": true,
"class-name": true,
"jsdoc-format": true,
"new-parens": true,
"no-angle-bracket-type-assertion": true,
"no-consecutive-blank-lines": [
true,
1
],
"no-parameter-properties": true,
// "object-literal-key-quotes": [
// true,
// "as-needed"
// ],
"one-line": [
true,
"check-catch",
"check-finally",
"check-else",
"check-open-brace",
"check-whitespace"
],
"one-variable-per-declaration": [true],
"quotemark": [
true,
"double",
"avoid-escape"
],
"semicolon": [
true,
"always",
"ignore-interfaces"
],
"variable-name": [
true,
"ban-keywords",
"check-format"
],
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-module",
"check-separator",
"check-type",
"check-typecast"
]
}
}
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc