Skip to content

Commit

Permalink
Merge branch 'master' into no-misused-promises
Browse files Browse the repository at this point in the history
  • Loading branch information
princjef committed Jul 2, 2019
2 parents fd562a4 + af70a59 commit 68cda9b
Show file tree
Hide file tree
Showing 13 changed files with 1,396 additions and 7 deletions.
3 changes: 2 additions & 1 deletion packages/eslint-plugin/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,6 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/no-parameter-properties`](./docs/rules/no-parameter-properties.md) | Disallow the use of parameter properties in class constructors | :heavy_check_mark: | | |
| [`@typescript-eslint/no-require-imports`](./docs/rules/no-require-imports.md) | Disallows invocation of `require()` | | | |
| [`@typescript-eslint/no-this-alias`](./docs/rules/no-this-alias.md) | Disallow aliasing `this` | | | |
| [`@typescript-eslint/no-triple-slash-reference`](./docs/rules/no-triple-slash-reference.md) | Disallow `/// <reference path="" />` comments | :heavy_check_mark: | | |
| [`@typescript-eslint/no-type-alias`](./docs/rules/no-type-alias.md) | Disallow the use of type aliases | | | |
| [`@typescript-eslint/no-unnecessary-qualifier`](./docs/rules/no-unnecessary-qualifier.md) | Warns when a namespace qualifier is unnecessary | | :wrench: | :thought_balloon: |
| [`@typescript-eslint/no-unnecessary-type-assertion`](./docs/rules/no-unnecessary-type-assertion.md) | Warns if a type assertion does not change the type of an expression | | :wrench: | :thought_balloon: |
Expand All @@ -179,6 +178,8 @@ Then you should add `airbnb` (or `airbnb-base`) to your `extends` section of `.e
| [`@typescript-eslint/require-array-sort-compare`](./docs/rules/require-array-sort-compare.md) | Enforce giving `compare` argument to `Array#sort` | | | :thought_balloon: |
| [`@typescript-eslint/restrict-plus-operands`](./docs/rules/restrict-plus-operands.md) | When adding two variables, operands must both be of type number or of type string | | | :thought_balloon: |
| [`@typescript-eslint/semi`](./docs/rules/semi.md) | Require or disallow semicolons instead of ASI | | :wrench: | |
| [`@typescript-eslint/strict-boolean-expressions`](./docs/rules/strict-boolean-expressions.md) | Restricts the types allowed in boolean expressions | | | :thought_balloon: |
| [`@typescript-eslint/triple-slash-reference`](./docs/rules/triple-slash-reference.md) | Sets preference level for triple slash directives versus ES6-style import declarations | | | |
| [`@typescript-eslint/type-annotation-spacing`](./docs/rules/type-annotation-spacing.md) | Require consistent spacing around type annotations | :heavy_check_mark: | :wrench: | |
| [`@typescript-eslint/unbound-method`](./docs/rules/unbound-method.md) | Enforces unbound methods are called with their expected scope | | | :thought_balloon: |
| [`@typescript-eslint/unified-signatures`](./docs/rules/unified-signatures.md) | Warns for any two overloads that could be unified into one by using a union or an optional/rest parameter | | | |
Expand Down
2 changes: 1 addition & 1 deletion packages/eslint-plugin/ROADMAP.md
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@
| [`prefer-object-spread`] | 🌟 | [`prefer-object-spread`][prefer-object-spread] |
| [`radix`] | 🌟 | [`radix`][radix] |
| [`restrict-plus-operands`] || [`@typescript-eslint/restrict-plus-operands`] |
| [`strict-boolean-expressions`] | 🛑 | N/A |
| [`strict-boolean-expressions`] | | [`@typescript-eslint/strict-boolean-expressions`] |
| [`strict-type-predicates`] | 🛑 | N/A |
| [`switch-default`] | 🌟 | [`default-case`][default-case] |
| [`triple-equals`] | 🌟 | [`eqeqeq`][eqeqeq] |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ A triple-slash reference directive is a comment beginning with three slashes fol
ES6 Modules handle this now:
`import animal from "./Animal"`

## DEPRECATED - this rule has been deprecated in favour of [`triple-slash-reference`](./triple-slash-reference.md)

## Rule Details

Does not allow the use of `/// <reference />` comments.
Expand Down
57 changes: 57 additions & 0 deletions packages/eslint-plugin/docs/rules/strict-boolean-expressions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Boolean expressions are limited to booleans (strict-boolean-expressions)

Requires that any boolean expression is limited to true booleans rather than
casting another primitive to a boolean at runtime.

It is useful to be explicit, for example, if you were trying to check if a
number was defined. Doing `if (number)` would evaluate to `false` if `number`
was defined and `0`. This rule forces these expressions to be explicit and to
strictly use booleans.

The following nodes are checked:

- Arguments to the `!`, `&&`, and `||` operators
- The condition in a conditional expression `(cond ? x : y)`
- Conditions for `if`, `for`, `while`, and `do-while` statements.

Examples of **incorrect** code for this rule:

```ts
const number = 0;
if (number) {
return;
}

let foo = bar || 'foobar';

let undefinedItem;
let foo = undefinedItem ? 'foo' : 'bar';

let str = 'foo';
while (str) {
break;
}
```

Examples of **correct** code for this rule:

```ts
const number = 0;
if (typeof number !== 'undefined') {
return;
}

let foo = typeof bar !== 'undefined' ? bar : 'foobar';

let undefinedItem;
let foo = typeof undefinedItem !== 'undefined' ? 'foo' : 'bar';

let str = 'foo';
while (typeof str !== 'undefined') {
break;
}
```

## Related To

- TSLint: [strict-boolean-expressions](https://palantir.github.io/tslint/rules/strict-boolean-expressions)
58 changes: 58 additions & 0 deletions packages/eslint-plugin/docs/rules/triple-slash-reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
# Sets preference level for triple slash directives versus ES6-style import declarations. (triple-slash-reference)

Use of triple-slash reference type directives is discouraged in favor of the newer `import` style. This rule allows you to ban use of `/// <reference path="" />`, `/// <reference types="" />`, or `/// <reference lib="" />` directives.

Consider using this rule in place of [`no-triple-slash-reference`](./no-triple-slash-reference.md) which has been deprecated.

## Rule Details

With `{ "path": "never", "types": "never", "lib": "never" }` options set, the following will all be **incorrect** usage:

```ts
/// <reference path="foo" />
/// <reference types="bar" />
/// <reference lib="baz" />
```

Examples of **incorrect** code for the `{ "types": "prefer-import" }` option. Note that these are only errors when **both** stlyes are used for the **same** module:

```ts
/// <reference types="foo" />
import * as foo from 'foo';
```

```ts
/// <reference types="foo" />
import foo = require('foo');
```

With `{ "path": "always", "types": "always", "lib": "always" }` options set, the following will all be **correct** usage:

```ts
/// <reference path="foo" />
/// <reference types="bar" />
/// <reference lib="baz" />
```

Examples of **correct** code for the `{ "types": "prefer-import" }` option:

```ts
import * as foo from 'foo';
```

```ts
import foo = require('foo');
```

## When To Use It

If you want to ban use of one or all of the triple slash reference directives, or any time you might use triple-slash type reference directives and ES6 import declarations in the same file.

## When Not To Use It

If you want to use all flavors of triple slash reference directives.

## Compatibility

- TSLint: [no-reference](http://palantir.github.io/tslint/rules/no-reference/)
- TSLint: [no-reference-import](https://palantir.github.io/tslint/rules/no-reference-import/)
2 changes: 1 addition & 1 deletion packages/eslint-plugin/src/configs/all.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@
"@typescript-eslint/no-parameter-properties": "error",
"@typescript-eslint/no-require-imports": "error",
"@typescript-eslint/no-this-alias": "error",
"@typescript-eslint/no-triple-slash-reference": "error",
"@typescript-eslint/no-type-alias": "error",
"@typescript-eslint/no-unnecessary-qualifier": "error",
"@typescript-eslint/no-unnecessary-type-assertion": "error",
Expand All @@ -65,6 +64,7 @@
"@typescript-eslint/restrict-plus-operands": "error",
"semi": "off",
"@typescript-eslint/semi": "error",
"@typescript-eslint/triple-slash-reference": "error",
"@typescript-eslint/type-annotation-spacing": "error",
"@typescript-eslint/unbound-method": "error",
"@typescript-eslint/unified-signatures": "error"
Expand Down
4 changes: 4 additions & 0 deletions packages/eslint-plugin/src/rules/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ import promiseFunctionAsync from './promise-function-async';
import requireArraySortCompare from './require-array-sort-compare';
import restrictPlusOperands from './restrict-plus-operands';
import semi from './semi';
import strictBooleanExpressions from './strict-boolean-expressions';
import tripleSlashReference from './triple-slash-reference';
import typeAnnotationSpacing from './type-annotation-spacing';
import unboundMethod from './unbound-method';
import unifiedSignatures from './unified-signatures';
Expand Down Expand Up @@ -115,6 +117,8 @@ export default {
'require-array-sort-compare': requireArraySortCompare,
'restrict-plus-operands': restrictPlusOperands,
semi: semi,
'strict-boolean-expressions': strictBooleanExpressions,
'triple-slash-reference': tripleSlashReference,
'type-annotation-spacing': typeAnnotationSpacing,
'unbound-method': unboundMethod,
'unified-signatures': unifiedSignatures,
Expand Down
6 changes: 4 additions & 2 deletions packages/eslint-plugin/src/rules/no-triple-slash-reference.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@ export default util.createRule({
recommended: 'error',
},
schema: [],
deprecated: true,
replacedBy: ['triple-slash-reference'],
messages: {
tripleSlashReference: 'Do not use a triple slash reference.',
noTripleSlashReference: 'Do not use a triple slash reference.',
},
},
defaultOptions: [],
Expand All @@ -30,7 +32,7 @@ export default util.createRule({
if (referenceRegExp.test(comment.value)) {
context.report({
node: comment,
messageId: 'tripleSlashReference',
messageId: 'noTripleSlashReference',
});
}
});
Expand Down
101 changes: 101 additions & 0 deletions packages/eslint-plugin/src/rules/strict-boolean-expressions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import {
TSESTree,
AST_NODE_TYPES,
} from '@typescript-eslint/experimental-utils';
import ts from 'typescript';
import * as tsutils from 'tsutils';
import * as util from '../util';

type ExpressionWithTest =
| TSESTree.ConditionalExpression
| TSESTree.DoWhileStatement
| TSESTree.ForStatement
| TSESTree.IfStatement
| TSESTree.WhileStatement;

export default util.createRule({
name: 'strict-boolean-expressions',
meta: {
type: 'suggestion',
docs: {
description: 'Restricts the types allowed in boolean expressions',
category: 'Best Practices',
recommended: false,
},
schema: [],
messages: {
strictBooleanExpression: 'Unexpected non-boolean in conditional.',
},
},
defaultOptions: [],
create(context) {
const service = util.getParserServices(context);
const checker = service.program.getTypeChecker();

/**
* Determines if the node has a boolean type.
*/
function isBooleanType(node: TSESTree.Node): boolean {
const tsNode = service.esTreeNodeToTSNodeMap.get<ts.ExpressionStatement>(
node,
);
const type = util.getConstrainedTypeAtLocation(checker, tsNode);
return tsutils.isTypeFlagSet(type, ts.TypeFlags.BooleanLike);
}

/**
* Asserts that a testable expression contains a boolean, reports otherwise.
* Filters all LogicalExpressions to prevent some duplicate reports.
*/
function assertTestExpressionContainsBoolean(
node: ExpressionWithTest,
): void {
if (
node.test !== null &&
node.test.type !== AST_NODE_TYPES.LogicalExpression &&
!isBooleanType(node.test)
) {
reportNode(node.test);
}
}

/**
* Asserts that a logical expression contains a boolean, reports otherwise.
*/
function assertLocalExpressionContainsBoolean(
node: TSESTree.LogicalExpression,
): void {
if (!isBooleanType(node.left) || !isBooleanType(node.right)) {
reportNode(node);
}
}

/**
* Asserts that a unary expression contains a boolean, reports otherwise.
*/
function assertUnaryExpressionContainsBoolean(
node: TSESTree.UnaryExpression,
): void {
if (!isBooleanType(node.argument)) {
reportNode(node.argument);
}
}

/**
* Reports an offending node in context.
*/
function reportNode(node: TSESTree.Node): void {
context.report({ node, messageId: 'strictBooleanExpression' });
}

return {
ConditionalExpression: assertTestExpressionContainsBoolean,
DoWhileStatement: assertTestExpressionContainsBoolean,
ForStatement: assertTestExpressionContainsBoolean,
IfStatement: assertTestExpressionContainsBoolean,
WhileStatement: assertTestExpressionContainsBoolean,
LogicalExpression: assertLocalExpressionContainsBoolean,
'UnaryExpression[operator="!"]': assertUnaryExpressionContainsBoolean,
};
},
});

0 comments on commit 68cda9b

Please sign in to comment.