Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Overhaul of ignore-prefix #137

Merged
merged 5 commits into from Jun 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Expand Up @@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

* Overhaul ignore-prefix, adding in ignore-suffix and ignore-pattern.

## [v5.5.2] - 2019-03-25

* readonly-array rule with the option ignore-prefix set will now ignore nested arrays within an ignored variable. See [#132](https://github.com/jonaskello/tslint-immutable/issues/132). See PR [#133](https://github.com/jonaskello/tslint-immutable/pull/133)
Expand Down
33 changes: 33 additions & 0 deletions README.md
Expand Up @@ -119,6 +119,8 @@ Yes
* [ignore-class](#using-the-ignore-class-option)
* [ignore-interface](#using-the-ignore-interface-option)
* [ignore-prefix](#using-the-ignore-prefix-option)
* [ignore-suffix](#using-the-ignore-suffix-option)
* [ignore-pattern](#using-the-ignore-pattern-option)

#### Example config

Expand Down Expand Up @@ -173,6 +175,8 @@ Yes

* [ignore-local](#using-the-ignore-local-option)
* [ignore-prefix](#using-the-ignore-prefix-option)
* [ignore-suffix](#using-the-ignore-suffix-option)
* [ignore-pattern](#using-the-ignore-pattern-option)
* [ignore-return-type](#using-the-ignore-return-type-option)
* [ignore-rest-parameters](#using-the-ignore-rest-parameters-option)

Expand Down Expand Up @@ -219,6 +223,8 @@ Yes

* [ignore-local](#using-the-ignore-local-option)
* [ignore-prefix](#using-the-ignore-prefix-option)
* [ignore-suffix](#using-the-ignore-suffix-option)
* [ignore-pattern](#using-the-ignore-pattern-option)

#### Example config

Expand Down Expand Up @@ -255,6 +261,8 @@ No
#### Options

* [ignore-prefix](#using-the-ignore-prefix-option)
* [ignore-suffix](#using-the-ignore-suffix-option)
* [ignore-pattern](#using-the-ignore-pattern-option)
* [ignore-new-array](#using-the-ignore-new-array-option-with-no-array-mutation)
* ~~ignore-mutation-following-accessor~~ - _deprecated in favor of [ignore-new-array](#using-the-ignore-new-array-option-with-no-array-mutation)_

Expand Down Expand Up @@ -294,6 +302,8 @@ No
#### Options

* [ignore-prefix](#using-the-ignore-prefix-option)
* [ignore-suffix](#using-the-ignore-suffix-option)
* [ignore-pattern](#using-the-ignore-pattern-option)

#### Example config

Expand Down Expand Up @@ -544,6 +554,29 @@ type person = {

Yes, variable names like `mutableAge` are ugly, but then again mutation is an ugly business :-).

### Using the `ignore-suffix` option

Like ignore-prefix but with suffix matching instead of prefix matching.

### Using the `ignore-pattern` option

Like ignore-prefix and ignore-suffix but with more control.

This option allows you to specify dot seperated paths what should be ignored.

For example, the following config would ignore all object mutations for all properties that start with "mutable".

```json
{
"no-object-mutation": [true, { "ignore-pattern": "**.mutable*" }]
}
```

The following wildcards can be used when specifing a pattern:

* `**` - Match any depth (including zero). Can only be used as a full accessor.
* `*` - When used as a full accessor, match the next accessor. When used as part of an accessor, match any characters.

### Using the `ignore-prefix` option with `no-expression-statement`

Expression statements typically cause side effects, however not all side effects are undesirable. One example of a helpful side effect is logging. To not get warning of every log statement, we can configure the linter to ignore well known expression statement prefixes.
Expand Down
42 changes: 26 additions & 16 deletions src/noArrayMutationRule.ts
Expand Up @@ -12,7 +12,7 @@ import { isAccessExpression, AccessExpression } from "./shared/typeguard";

type Options = Ignore.IgnoreNewArrayOption &
Ignore.IgnoreMutationFollowingAccessorOption &
Ignore.IgnorePrefixOption;
Ignore.IgnoreOption;

type ArrayType = ts.Type & {
symbol: {
Expand Down Expand Up @@ -124,9 +124,11 @@ function checkBinaryExpression(
checker: ts.TypeChecker
): CheckNodeResult {
if (
!Ignore.isIgnoredPrefix(
node.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.left,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
isAssignmentKind(node.operatorToken.kind) &&
isAccessExpression(node.left)
Expand All @@ -151,9 +153,11 @@ function checkDeleteExpression(
checker: ts.TypeChecker
): CheckNodeResult {
if (
!Ignore.isIgnoredPrefix(
node.expression.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.expression,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
isAccessExpression(node.expression)
) {
Expand All @@ -177,9 +181,11 @@ function checkPrefixUnaryExpression(
checker: ts.TypeChecker
): CheckNodeResult {
if (
!Ignore.isIgnoredPrefix(
node.operand.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.operand,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
isAccessExpression(node.operand) &&
forbidUnaryOps.some(o => o === node.operator)
Expand All @@ -204,9 +210,11 @@ function checkPostfixUnaryExpression(
checker: ts.TypeChecker
): CheckNodeResult {
if (
!Ignore.isIgnoredPrefix(
node.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.operand,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
isAccessExpression(node.operand) &&
forbidUnaryOps.some(o => o === node.operator)
Expand All @@ -231,9 +239,11 @@ function checkCallExpression(
checker: ts.TypeChecker
): CheckNodeResult {
if (
!Ignore.isIgnoredPrefix(
node.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.expression,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
utils.isPropertyAccessExpression(node.expression) &&
(!(
Expand Down
17 changes: 8 additions & 9 deletions src/noExpressionStatementRule.ts
Expand Up @@ -8,7 +8,7 @@ import {
} from "./shared/check-node";
import * as Ignore from "./shared/ignore";

type Options = Ignore.IgnorePrefixOption;
type Options = Ignore.IgnoreOption;

// tslint:disable-next-line:variable-name
export const Rule = createCheckNodeRule(
Expand All @@ -25,14 +25,13 @@ function checkNode(
const isYield = children.every(
n => n.kind === ts.SyntaxKind.YieldExpression
);
let text = node.getText(node.getSourceFile());
if (utils.isAwaitExpression(node.expression)) {
text = node.expression.expression.getText(
node.expression.getSourceFile()
);
}
const isIgnored2 = Ignore.isIgnoredPrefix(text, ctx.options.ignorePrefix);
if (!isYield && !isIgnored2) {
const isIgnored = Ignore.isIgnored(
node.expression,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
);
if (!isYield && !isIgnored) {
return { invalidNodes: [createInvalidNode(node, [])] };
}
}
Expand Down
4 changes: 2 additions & 2 deletions src/noLetRule.ts
Expand Up @@ -8,7 +8,7 @@ import {
createCheckNodeRule
} from "./shared/check-node";

type Options = Ignore.IgnoreLocalOption & Ignore.IgnorePrefixOption;
type Options = Ignore.IgnoreLocalOption & Ignore.IgnoreOption;

// tslint:disable-next-line:variable-name
export const Rule = createCheckNodeRule(
Expand Down Expand Up @@ -77,7 +77,7 @@ function checkDeclarationList(
let addFix = true;
for (const variableDeclarationNode of declarationList.declarations) {
if (
!Ignore.shouldIgnorePrefix(
!Ignore.shouldIgnore(
variableDeclarationNode,
ctx.options,
ctx.sourceFile
Expand Down
42 changes: 26 additions & 16 deletions src/noObjectMutationRule.ts
Expand Up @@ -11,7 +11,7 @@ import {
import * as Ignore from "./shared/ignore";
import { isAccessExpression } from "./shared/typeguard";

type Options = Ignore.IgnorePrefixOption;
type Options = Ignore.IgnoreOption;

// tslint:disable-next-line:variable-name
export const Rule = createCheckNodeTypedRule(
Expand Down Expand Up @@ -42,9 +42,11 @@ function checkNode(
utils.isBinaryExpression(node) &&
isAccessExpression(node.left) &&
isAssignmentKind(node.operatorToken.kind) &&
!Ignore.isIgnoredPrefix(
node.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.left,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
!inConstructor(node)
) {
Expand All @@ -55,9 +57,11 @@ function checkNode(
if (
utils.isDeleteExpression(node) &&
isAccessExpression(node.expression) &&
!Ignore.isIgnoredPrefix(
node.expression.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.expression,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
)
) {
invalidNodes = [...invalidNodes, createInvalidNode(node, [])];
Expand All @@ -68,9 +72,11 @@ function checkNode(
utils.isPrefixUnaryExpression(node) &&
isAccessExpression(node.operand) &&
forbidUnaryOps.some(o => o === node.operator) &&
!Ignore.isIgnoredPrefix(
node.operand.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.operand,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
)
) {
invalidNodes = [...invalidNodes, createInvalidNode(node, [])];
Expand All @@ -81,9 +87,11 @@ function checkNode(
utils.isPostfixUnaryExpression(node) &&
isAccessExpression(node.operand) &&
forbidUnaryOps.some(o => o === node.operator) &&
!Ignore.isIgnoredPrefix(
node.getText(node.getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.operand,
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
)
) {
invalidNodes = [...invalidNodes, createInvalidNode(node, [])];
Expand All @@ -98,9 +106,11 @@ function checkNode(
node.arguments.length >= 2 &&
(utils.isIdentifier(node.arguments[0]) ||
utils.isPropertyAccessExpression(node.arguments[0])) &&
!Ignore.isIgnoredPrefix(
node.arguments[0].getText(node.arguments[0].getSourceFile()),
ctx.options.ignorePrefix
!Ignore.isIgnored(
node.arguments[0],
ctx.options.ignorePattern,
ctx.options.ignorePrefix,
ctx.options.ignoreSuffix
) &&
// Do type checking as late as possible as it is expensive.
isObjectConstructorType(
Expand Down
8 changes: 4 additions & 4 deletions src/readonlyArrayRule.ts
Expand Up @@ -13,7 +13,7 @@ import {
} from "./shared/typeguard";

type Options = Ignore.IgnoreLocalOption &
Ignore.IgnorePrefixOption &
Ignore.IgnoreOption &
Ignore.IgnoreRestParametersOption &
Ignore.IgnoreReturnType;

Expand Down Expand Up @@ -60,7 +60,7 @@ function checkArrayType(

if (
node.parent &&
Ignore.shouldIgnorePrefix(node.parent, ctx.options, ctx.sourceFile)
Ignore.shouldIgnore(node.parent, ctx.options, ctx.sourceFile)
) {
return {
invalidNodes: [],
Expand Down Expand Up @@ -110,7 +110,7 @@ function checkTypeReference(
) {
if (
node.parent &&
Ignore.shouldIgnorePrefix(node.parent, ctx.options, ctx.sourceFile)
Ignore.shouldIgnore(node.parent, ctx.options, ctx.sourceFile)
) {
return {
invalidNodes: [],
Expand All @@ -137,7 +137,7 @@ export function checkImplicitType(
node: ts.Node,
ctx: Lint.WalkContext<Options>
): CheckNodeResult {
if (Ignore.shouldIgnorePrefix(node, ctx.options, ctx.sourceFile)) {
if (Ignore.shouldIgnore(node, ctx.options, ctx.sourceFile)) {
return {
invalidNodes: [],
skipChildren: true
Expand Down
4 changes: 2 additions & 2 deletions src/readonlyKeywordRule.ts
Expand Up @@ -9,7 +9,7 @@ import {
} from "./shared/check-node";

type Options = Ignore.IgnoreLocalOption &
Ignore.IgnorePrefixOption &
Ignore.IgnoreOption &
Ignore.IgnoreClassOption &
Ignore.IgnoreInterfaceOption;

Expand Down Expand Up @@ -45,7 +45,7 @@ function checkPropertySignatureAndIndexSignature(
)
) {
// Check if ignore-prefix applies
if (Ignore.shouldIgnorePrefix(node, ctx.options, ctx.sourceFile)) {
if (Ignore.shouldIgnore(node, ctx.options, ctx.sourceFile)) {
return { invalidNodes: [] };
}

Expand Down