tslint-immutable
Advanced tools
Comparing version 3.1.1 to 3.1.2
@@ -8,4 +8,11 @@ # Change Log | ||
## [Unreleased] | ||
### Added | ||
## [v3.1.2] - 2017-04-09 | ||
### Fixed | ||
- readonly-array does not check return type when ignore-local is enabled [#16](https://github.com/jonaskello/tslint-immutable/issues/16) | ||
- readonly-array does not check shorthand syntax [#20](https://github.com/jonaskello/tslint-immutable/issues/20). | ||
## Changed | ||
- Impicit return type is not checked in readonly-array [#18](https://github.com/jonaskello/tslint-immutable/issues/18). | ||
## [v3.1.1] - 2017-04-05 | ||
@@ -62,3 +69,4 @@ ### Fixed | ||
[Unreleased]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.1...master | ||
[Unreleased]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.2...master | ||
[v3.1.2]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.1...v3.1.2 | ||
[v3.1.1]: https://github.com/jonaskello/tslint-immutable/compare/v3.1.0...v3.1.1 | ||
@@ -65,0 +73,0 @@ [v3.1.0]: https://github.com/jonaskello/tslint-immutable/compare/v3.0.0...v3.1.0 |
{ | ||
"name": "tslint-immutable", | ||
"version": "3.1.1", | ||
"version": "3.1.2", | ||
"description": "TSLint rules to disable mutation in TypeScript.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -247,3 +247,3 @@ # tslint-immutable | ||
Typescript is not immutable by default but it can be if you use this package. So in order to create an escape hatch similar to how it is done in reason the `ignore-mutable` option can be used. For example if you configure it to ignore variables with names that has the prefix "mutable" you can emulate the above example in typescript like this: | ||
Typescript is not immutable by default but it can be if you use this package. So in order to create an escape hatch similar to how it is done in reason the `ignore-prefix` option can be used. For example if you configure it to ignore variables with names that has the prefix "mutable" you can emulate the above example in typescript like this: | ||
@@ -259,2 +259,24 @@ ```typescript | ||
## Recommended built-in rules | ||
### [no-var-keyword](https://palantir.github.io/tslint/rules/no-var-keyword/) | ||
Without this rule, it is still possible to create `var` variables that are mutable. | ||
### [typedef](https://palantir.github.io/tslint/rules/typedef/) with call-signature option | ||
For performance reasons, tslint-immutable does not check implicit return types. So for example this function will return an mutable array but will not be detected (see [#18](https://github.com/jonaskello/tslint-immutable/issues/18) for more info): | ||
```javascript | ||
function foo() { | ||
return [1, 2, 3]; | ||
} | ||
``` | ||
To avoid this situation you can enable the built in typedef rule like this: | ||
`"typedef": [true, "call-signature"]` | ||
Now the above function is forced to declare the return type becomes this and will be detected. | ||
## Sample Configuration File | ||
@@ -269,2 +291,6 @@ | ||
// Recommended built-in rules | ||
"no-var-keyword": true, | ||
"typedef": [true, "call-signature"], | ||
// Immutability rules | ||
@@ -275,3 +301,2 @@ "readonly-interface": true, | ||
"no-let": true, | ||
"no-var-keyword": true, // built-in tslint rule | ||
@@ -300,2 +325,11 @@ // Functional style rules | ||
## How to contribute | ||
For new features file an issue. For bugs, file an issue and optionally file a PR with a failing test. Tests are really easy to do, you just have to edit the `*.ts.lint` files under the test directory. Read more here about [tslint testing](https://palantir.github.io/tslint/develop/testing-rules/). | ||
## How to develop | ||
To execute the tests run `yarn test`. | ||
To release a new package version run `yarn publish:patch`, `yarn publish:minor`, or `yarn publish:major`. | ||
## Prior work | ||
@@ -302,0 +336,0 @@ |
@@ -46,23 +46,11 @@ "use strict"; | ||
if (ctx.options.ignoreLocal && (node.kind === ts.SyntaxKind.FunctionDeclaration || node.kind === ts.SyntaxKind.ArrowFunction)) { | ||
// We still need to check the parameters which resides in the SyntaxList node | ||
for (var _i = 0, _a = node.getChildren(ctx.sourceFile); _i < _a.length; _i++) { | ||
var child1 = _a[_i]; | ||
if (child1.kind === ts.SyntaxKind.SyntaxList) { | ||
for (var _b = 0, _c = child1.getChildren(ctx.sourceFile); _b < _c.length; _b++) { | ||
var child2 = _c[_b]; | ||
if (child2.kind === ts.SyntaxKind.Parameter) { | ||
for (var _d = 0, _e = child2.getChildren(ctx.sourceFile).filter(function (child) { | ||
return child.kind === ts.SyntaxKind.ArrayLiteralExpression || child.kind === ts.SyntaxKind.TypeReference; | ||
}); _d < _e.length; _d++) { | ||
var child3 = _e[_d]; | ||
checkNode(child3, ctx); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
// We still need to check the parameters and return type | ||
var functionNode = node; //tslint:disable-line | ||
checkFunctionNode(functionNode, ctx); | ||
return; | ||
} | ||
// Check the node | ||
checkNode(node, ctx); | ||
checkArrayTypeReference(node, ctx); | ||
checkArrayType(node, ctx); | ||
checkArrayLiteralExpression(node, ctx); | ||
// Use return becuase performance hints docs say it optimizes the function using tail-call recursion | ||
@@ -72,38 +60,64 @@ return ts.forEachChild(node, cb); | ||
} | ||
function checkNode(node, ctx) { | ||
if (node.kind === ts.SyntaxKind.TypeReference && isInvalidArrayTypeReference(node, ctx)) { | ||
ctx.addFailureAtNode(node, Rule.FAILURE_STRING); | ||
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); | ||
} | ||
else if (parameter.initializer) { | ||
checkArrayLiteralExpression(parameter.initializer, ctx); | ||
} | ||
} | ||
if (node.kind === ts.SyntaxKind.ArrayLiteralExpression && isInvalidArrayLiteralExpression(node, ctx)) { | ||
var variableDeclarationNode = node.parent; | ||
ctx.addFailureAt(variableDeclarationNode.name.getStart(ctx.sourceFile), variableDeclarationNode.name.getWidth(ctx.sourceFile), Rule.FAILURE_STRING); | ||
// Check the return type | ||
if (node.type) { | ||
checkArrayTypeReference(node.type, ctx); | ||
} | ||
} | ||
function isInvalidArrayTypeReference(node, ctx) { | ||
if (node.typeName.getText(ctx.sourceFile) === "Array") { | ||
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 false; | ||
return; | ||
} | ||
} | ||
return true; | ||
ctx.addFailureAtNode(node, Rule.FAILURE_STRING); | ||
return; | ||
} | ||
return false; | ||
} | ||
function isInvalidArrayLiteralExpression(node, ctx) { | ||
// 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 false; | ||
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; | ||
} | ||
} | ||
return true; | ||
ctx.addFailureAtNode(node, Rule.FAILURE_STRING); | ||
} | ||
return; | ||
} | ||
return false; | ||
} | ||
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); | ||
} | ||
} | ||
return; | ||
} | ||
} |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
340
61186
22
814