diff --git a/CHANGELOG.md b/CHANGELOG.md index 852f9309825d..230c2a24659f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,24 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + + +### Bug Fixes + +* **typescript-estree:** fix handling of range/loc removal ([#2028](https://github.com/typescript-eslint/typescript-eslint/issues/2028)) ([ce344d9](https://github.com/typescript-eslint/typescript-eslint/commit/ce344d90e7c78b0c4b4b823494a3e78190f45c64)) + + +### Features + +* **eslint-plugin:** [no-invalid-void-type] allow union of void and `allowInGenericTypeArguments` ([#1960](https://github.com/typescript-eslint/typescript-eslint/issues/1960)) ([1bc105a](https://github.com/typescript-eslint/typescript-eslint/commit/1bc105a2c6ae3fde9596f0419fed0de699dc57c7)) +* **eslint-plugin:** [restrict-template-expressions] improve error message ([#1926](https://github.com/typescript-eslint/typescript-eslint/issues/1926)) ([1af59ba](https://github.com/typescript-eslint/typescript-eslint/commit/1af59ba8ac0ceabb008d9c61556acf7db0a1d352)) +* **experimental-utils:** add `suggestion` property for rule modules ([#2033](https://github.com/typescript-eslint/typescript-eslint/issues/2033)) ([f42a5b0](https://github.com/typescript-eslint/typescript-eslint/commit/f42a5b09ebfa173f418a99c552b0cbe221567194)) + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) diff --git a/lerna.json b/lerna.json index 9b49112153a9..b498274759cd 100644 --- a/lerna.json +++ b/lerna.json @@ -1,5 +1,5 @@ { - "version": "2.33.0", + "version": "2.34.0", "npmClient": "yarn", "useWorkspaces": true, "stream": true diff --git a/packages/eslint-plugin-internal/CHANGELOG.md b/packages/eslint-plugin-internal/CHANGELOG.md index 3ab8ba8c3965..6adb3ced3669 100644 --- a/packages/eslint-plugin-internal/CHANGELOG.md +++ b/packages/eslint-plugin-internal/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + + +### Features + +* **experimental-utils:** add `suggestion` property for rule modules ([#2033](https://github.com/typescript-eslint/typescript-eslint/issues/2033)) ([f42a5b0](https://github.com/typescript-eslint/typescript-eslint/commit/f42a5b09ebfa173f418a99c552b0cbe221567194)) + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-internal diff --git a/packages/eslint-plugin-internal/package.json b/packages/eslint-plugin-internal/package.json index cfd4cb84b862..13abe6554f82 100644 --- a/packages/eslint-plugin-internal/package.json +++ b/packages/eslint-plugin-internal/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-internal", - "version": "2.33.0", + "version": "2.34.0", "private": true, "main": "dist/index.js", "scripts": { @@ -12,7 +12,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.33.0", + "@typescript-eslint/experimental-utils": "2.34.0", "prettier": "*" } } diff --git a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts index a1485e2435fd..b769e05d9265 100644 --- a/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts +++ b/packages/eslint-plugin-internal/src/rules/no-poorly-typed-ts-props.ts @@ -39,6 +39,7 @@ export default createRule({ "Enforces rules don't use TS API properties with known bad type definitions", category: 'Possible Errors', recommended: 'error', + suggestion: true, requiresTypeChecking: true, }, fixable: 'code', diff --git a/packages/eslint-plugin-tslint/CHANGELOG.md b/packages/eslint-plugin-tslint/CHANGELOG.md index 9ac201fc16b2..0d49360362f8 100644 --- a/packages/eslint-plugin-tslint/CHANGELOG.md +++ b/packages/eslint-plugin-tslint/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + +**Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) **Note:** Version bump only for package @typescript-eslint/eslint-plugin-tslint diff --git a/packages/eslint-plugin-tslint/package.json b/packages/eslint-plugin-tslint/package.json index a476b622aeee..16d0949f2f48 100644 --- a/packages/eslint-plugin-tslint/package.json +++ b/packages/eslint-plugin-tslint/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin-tslint", - "version": "2.33.0", + "version": "2.34.0", "main": "dist/index.js", "typings": "src/index.ts", "description": "TSLint wrapper plugin for ESLint", @@ -31,7 +31,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.33.0", + "@typescript-eslint/experimental-utils": "2.34.0", "lodash": "^4.17.15" }, "peerDependencies": { @@ -41,6 +41,6 @@ }, "devDependencies": { "@types/lodash": "^4.14.149", - "@typescript-eslint/parser": "2.33.0" + "@typescript-eslint/parser": "2.34.0" } } diff --git a/packages/eslint-plugin/CHANGELOG.md b/packages/eslint-plugin/CHANGELOG.md index b0d008382fd4..8b336d6e5df5 100644 --- a/packages/eslint-plugin/CHANGELOG.md +++ b/packages/eslint-plugin/CHANGELOG.md @@ -3,6 +3,19 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + + +### Features + +* **eslint-plugin:** [no-invalid-void-type] allow union of void and `allowInGenericTypeArguments` ([#1960](https://github.com/typescript-eslint/typescript-eslint/issues/1960)) ([1bc105a](https://github.com/typescript-eslint/typescript-eslint/commit/1bc105a2c6ae3fde9596f0419fed0de699dc57c7)) +* **eslint-plugin:** [restrict-template-expressions] improve error message ([#1926](https://github.com/typescript-eslint/typescript-eslint/issues/1926)) ([1af59ba](https://github.com/typescript-eslint/typescript-eslint/commit/1af59ba8ac0ceabb008d9c61556acf7db0a1d352)) +* **experimental-utils:** add `suggestion` property for rule modules ([#2033](https://github.com/typescript-eslint/typescript-eslint/issues/2033)) ([f42a5b0](https://github.com/typescript-eslint/typescript-eslint/commit/f42a5b09ebfa173f418a99c552b0cbe221567194)) + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) diff --git a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md index 5e60f29eac22..3cafe4224eb8 100644 --- a/packages/eslint-plugin/docs/rules/explicit-function-return-type.md +++ b/packages/eslint-plugin/docs/rules/explicit-function-return-type.md @@ -77,6 +77,7 @@ const defaults = { allowExpressions: false, allowTypedFunctionExpressions: true, allowHigherOrderFunctions: true, + allowConciseArrowFunctionExpressionsStartingWithVoid: true, }; ``` diff --git a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md index 9cc9808852f7..f1607478a0d8 100644 --- a/packages/eslint-plugin/docs/rules/no-invalid-void-type.md +++ b/packages/eslint-plugin/docs/rules/no-invalid-void-type.md @@ -1,13 +1,14 @@ # Disallows usage of `void` type outside of generic or return types (`no-invalid-void-type`) Disallows usage of `void` type outside of return types or generic type arguments. -If `void` is used as return type, it shouldn’t be a part of intersection/union type. +If `void` is used as return type, it shouldn’t be a part of intersection/union type with most other types. ## Rationale The `void` type means “nothing” or that a function does not return any value, in contrast with implicit `undefined` type which means that a function returns a value `undefined`. -So “nothing” cannot be mixed with any other types. If you need this - use the `undefined` type instead. +So “nothing” cannot be mixed with any other types, other than `never`, which accepts all types. +If you need this - use the `undefined` type instead. ## Rule Details @@ -44,6 +45,8 @@ function noop(): void {} let trulyUndefined = void 0; async function promiseMeSomething(): Promise {} + +type stillVoid = void | never; ``` ### Options @@ -64,6 +67,8 @@ This option lets you control if `void` can be used as a valid value for generic Alternatively, you can provide an array of strings which whitelist which types may accept `void` as a generic type parameter. +Any types considered valid by this option will be considered valid as part of a union type with `void`. + This option is `true` by default. The following patterns are considered warnings with `{ allowInGenericTypeArguments: false }`: @@ -88,7 +93,8 @@ type NotAllowedVoid3 = Promise; The following patterns are not considered warnings with `{ allowInGenericTypeArguments: ['Ex.Mx.Tx'] }`: ```ts -type AllowedVoid = Ex.MX.Tx; +type AllowedVoid = Ex.Mx.Tx; +type AllowedVoidUnion = void | Ex.Mx.Tx; ``` ## When Not To Use It diff --git a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md index 816a0b0f9d65..4bb2a062ad94 100644 --- a/packages/eslint-plugin/docs/rules/restrict-template-expressions.md +++ b/packages/eslint-plugin/docs/rules/restrict-template-expressions.md @@ -40,6 +40,7 @@ type Options = { const defaults = { allowNumber: false, allowBoolean: false, + allowAny: false, allowNullable: false, }; ``` diff --git a/packages/eslint-plugin/package.json b/packages/eslint-plugin/package.json index d4dee743c021..a08286a3c634 100644 --- a/packages/eslint-plugin/package.json +++ b/packages/eslint-plugin/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/eslint-plugin", - "version": "2.33.0", + "version": "2.34.0", "description": "TypeScript plugin for ESLint", "keywords": [ "eslint", @@ -41,7 +41,7 @@ "typecheck": "tsc -p tsconfig.json --noEmit" }, "dependencies": { - "@typescript-eslint/experimental-utils": "2.33.0", + "@typescript-eslint/experimental-utils": "2.34.0", "functional-red-black-tree": "^1.0.1", "regexpp": "^3.0.0", "tsutils": "^3.17.1" diff --git a/packages/eslint-plugin/src/rules/no-empty-interface.ts b/packages/eslint-plugin/src/rules/no-empty-interface.ts index d279e9bd4f61..817d1232be2b 100644 --- a/packages/eslint-plugin/src/rules/no-empty-interface.ts +++ b/packages/eslint-plugin/src/rules/no-empty-interface.ts @@ -19,6 +19,7 @@ export default util.createRule({ description: 'Disallow the declaration of empty interfaces', category: 'Best Practices', recommended: 'error', + suggestion: true, }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/no-explicit-any.ts b/packages/eslint-plugin/src/rules/no-explicit-any.ts index 795dae017253..4e6b8c34fc1d 100644 --- a/packages/eslint-plugin/src/rules/no-explicit-any.ts +++ b/packages/eslint-plugin/src/rules/no-explicit-any.ts @@ -21,6 +21,7 @@ export default util.createRule({ description: 'Disallow usage of the `any` type', category: 'Best Practices', recommended: 'warn', + suggestion: true, }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/no-floating-promises.ts b/packages/eslint-plugin/src/rules/no-floating-promises.ts index 04da1a9b8c49..615f88f25df3 100644 --- a/packages/eslint-plugin/src/rules/no-floating-promises.ts +++ b/packages/eslint-plugin/src/rules/no-floating-promises.ts @@ -24,6 +24,7 @@ export default util.createRule({ description: 'Requires Promise-like values to be handled appropriately', category: 'Best Practices', recommended: false, + suggestion: true, requiresTypeChecking: true, }, messages: { diff --git a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts index 7d5dea300338..b78107bac650 100644 --- a/packages/eslint-plugin/src/rules/no-invalid-void-type.ts +++ b/packages/eslint-plugin/src/rules/no-invalid-void-type.ts @@ -60,11 +60,81 @@ export default util.createRule<[Options], MessageIds>({ AST_NODE_TYPES.ClassProperty, AST_NODE_TYPES.Identifier, ]; + const validUnionMembers: AST_NODE_TYPES[] = [ + AST_NODE_TYPES.TSVoidKeyword, + AST_NODE_TYPES.TSNeverKeyword, + ]; if (allowInGenericTypeArguments === true) { validParents.push(AST_NODE_TYPES.TSTypeParameterInstantiation); } + /** + * @brief check if the given void keyword is used as a valid generic type + * + * reports if the type parametrized by void is not in the whitelist, or + * allowInGenericTypeArguments is false. + * no-op if the given void keyword is not used as generic type + */ + function checkGenericTypeArgument(node: TSESTree.TSVoidKeyword): void { + // only matches T<..., void, ...> + // extra check for precaution + /* istanbul ignore next */ + if ( + node.parent?.type !== AST_NODE_TYPES.TSTypeParameterInstantiation || + node.parent.parent?.type !== AST_NODE_TYPES.TSTypeReference + ) { + return; + } + + // check whitelist + if (Array.isArray(allowInGenericTypeArguments)) { + const sourceCode = context.getSourceCode(); + const fullyQualifiedName = sourceCode + .getText(node.parent.parent.typeName) + .replace(/ /gu, ''); + + if ( + !allowInGenericTypeArguments + .map(s => s.replace(/ /gu, '')) + .includes(fullyQualifiedName) + ) { + context.report({ + messageId: 'invalidVoidForGeneric', + data: { generic: fullyQualifiedName }, + node, + }); + } + return; + } + + if (!allowInGenericTypeArguments) { + context.report({ + messageId: 'invalidVoidNotReturn', + node, + }); + } + } + + /** + * @brief checks that a union containing void is valid + * @return true if every member of the union is specified as a valid type in + * validUnionMembers, or is a valid generic type parametrized by void + */ + function isValidUnionType(node: TSESTree.TSUnionType): boolean { + return node.types.every( + member => + validUnionMembers.includes(member.type) || + // allows any T<..., void, ...> here, checked by checkGenericTypeArgument + (member.type === AST_NODE_TYPES.TSTypeReference && + member.typeParameters?.type === + AST_NODE_TYPES.TSTypeParameterInstantiation && + member.typeParameters?.params + .map(param => param.type) + .includes(AST_NODE_TYPES.TSVoidKeyword)), + ); + } + return { TSVoidKeyword(node: TSESTree.TSVoidKeyword): void { /* istanbul ignore next */ @@ -72,35 +142,28 @@ export default util.createRule<[Options], MessageIds>({ return; } + // checks T<..., void, ...> against specification of allowInGenericArguments option if ( - validParents.includes(node.parent.type) && - !invalidGrandParents.includes(node.parent.parent.type) + node.parent.type === AST_NODE_TYPES.TSTypeParameterInstantiation && + node.parent.parent.type === AST_NODE_TYPES.TSTypeReference ) { + checkGenericTypeArgument(node); return; } + // union w/ void must contain types from validUnionMembers, or a valid generic void type if ( - node.parent.type === AST_NODE_TYPES.TSTypeParameterInstantiation && - node.parent.parent.type === AST_NODE_TYPES.TSTypeReference && - Array.isArray(allowInGenericTypeArguments) + node.parent.type === AST_NODE_TYPES.TSUnionType && + isValidUnionType(node.parent) ) { - const sourceCode = context.getSourceCode(); - const fullyQualifiedName = sourceCode - .getText(node.parent.parent.typeName) - .replace(/ /gu, ''); - - if ( - !allowInGenericTypeArguments - .map(s => s.replace(/ /gu, '')) - .includes(fullyQualifiedName) - ) { - context.report({ - messageId: 'invalidVoidForGeneric', - data: { generic: fullyQualifiedName }, - node, - }); - } + return; + } + // default cases + if ( + validParents.includes(node.parent.type) && + !invalidGrandParents.includes(node.parent.parent.type) + ) { return; } diff --git a/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts b/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts index 2487c975df48..b3704b8d5dd2 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-asserted-optional-chain.ts @@ -12,6 +12,7 @@ export default util.createRule<[], MessageIds>({ 'Disallows using a non-null assertion after an optional chain expression', category: 'Possible Errors', recommended: false, + suggestion: true, }, messages: { noNonNullOptionalChain: diff --git a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts index ef268d7a4e2f..143b889b17c4 100644 --- a/packages/eslint-plugin/src/rules/no-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-non-null-assertion.ts @@ -15,6 +15,7 @@ export default util.createRule<[], MessageIds>({ 'Disallows non-null assertions using the `!` postfix operator', category: 'Stylistic Issues', recommended: 'warn', + suggestion: true, }, messages: { noNonNull: 'Forbidden non-null assertion.', diff --git a/packages/eslint-plugin/src/rules/prefer-as-const.ts b/packages/eslint-plugin/src/rules/prefer-as-const.ts index cbce99462d19..9fb619b74b52 100644 --- a/packages/eslint-plugin/src/rules/prefer-as-const.ts +++ b/packages/eslint-plugin/src/rules/prefer-as-const.ts @@ -13,6 +13,7 @@ export default util.createRule({ description: 'Prefer usage of `as const` over literal type', category: 'Best Practices', recommended: false, + suggestion: true, }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts index d5b35e8dd136..3c616ded75d6 100644 --- a/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts +++ b/packages/eslint-plugin/src/rules/prefer-nullish-coalescing.ts @@ -24,6 +24,7 @@ export default util.createRule({ 'Enforce the usage of the nullish coalescing operator instead of logical chaining', category: 'Best Practices', recommended: false, + suggestion: true, requiresTypeChecking: true, }, fixable: 'code', diff --git a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts index 7c8580089849..6adc3f1d9c89 100644 --- a/packages/eslint-plugin/src/rules/prefer-optional-chain.ts +++ b/packages/eslint-plugin/src/rules/prefer-optional-chain.ts @@ -48,6 +48,7 @@ export default util.createRule({ 'Prefer using concise optional chain expressions instead of chained logical ands', category: 'Best Practices', recommended: false, + suggestion: true, }, fixable: 'code', messages: { diff --git a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts index 90dd363f8204..6ba846ed5980 100644 --- a/packages/eslint-plugin/src/rules/restrict-template-expressions.ts +++ b/packages/eslint-plugin/src/rules/restrict-template-expressions.ts @@ -27,7 +27,7 @@ export default util.createRule({ requiresTypeChecking: true, }, messages: { - invalidType: 'Invalid type of template literal expression.', + invalidType: 'Invalid type "{{type}}" of template literal expression.', }, schema: [ { @@ -90,46 +90,44 @@ export default util.createRule({ } for (const expression of node.expressions) { + const expressionType = util.getConstrainedTypeAtLocation( + typeChecker, + service.esTreeNodeToTSNodeMap.get(expression), + ); + if ( - !isUnderlyingExpressionTypeConfirmingTo( - expression, + !isInnerUnionOrIntersectionConformingTo( + expressionType, isUnderlyingTypePrimitive, ) ) { context.report({ node: expression, messageId: 'invalidType', + data: { type: typeChecker.typeToString(expressionType) }, }); } } }, }; - function isUnderlyingExpressionTypeConfirmingTo( - expression: TSESTree.Expression, + function isInnerUnionOrIntersectionConformingTo( + type: ts.Type, predicate: (underlyingType: ts.Type) => boolean, ): boolean { - return rec(getExpressionNodeType(expression)); + return rec(type); - function rec(type: ts.Type): boolean { - if (type.isUnion()) { - return type.types.every(rec); + function rec(innerType: ts.Type): boolean { + if (innerType.isUnion()) { + return innerType.types.every(rec); } - if (type.isIntersection()) { - return type.types.some(rec); + if (innerType.isIntersection()) { + return innerType.types.some(rec); } - return predicate(type); + return predicate(innerType); } } - - /** - * Helper function to extract the TS type of an TSESTree expression. - */ - function getExpressionNodeType(node: TSESTree.Expression): ts.Type { - const tsNode = service.esTreeNodeToTSNodeMap.get(node); - return util.getConstrainedTypeAtLocation(typeChecker, tsNode); - } }, }); diff --git a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts index c559fc71cc91..d9e14bcf3316 100644 --- a/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts +++ b/packages/eslint-plugin/src/rules/switch-exhaustiveness-check.ts @@ -17,6 +17,7 @@ export default createRule({ description: 'Exhaustiveness checking in switch with union type', category: 'Best Practices', recommended: false, + suggestion: true, requiresTypeChecking: true, }, schema: [], diff --git a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts index 057da9b7e84a..31771c561c0e 100644 --- a/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts +++ b/packages/eslint-plugin/tests/rules/no-invalid-void-type.test.ts @@ -11,6 +11,23 @@ ruleTester.run('allowInGenericTypeArguments: false', rule, { code: 'type Generic = [T];', options: [{ allowInGenericTypeArguments: false }], }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/1946 + code: ` +function foo(): void | never { + throw new Error('Test'); +} + `, + options: [{ allowInGenericTypeArguments: false }], + }, + { + code: 'type voidNeverUnion = void | never;', + options: [{ allowInGenericTypeArguments: false }], + }, + { + code: 'type neverVoidUnion = never | void;', + options: [{ allowInGenericTypeArguments: false }], + }, ], invalid: [ { @@ -67,6 +84,17 @@ ruleTester.run('allowInGenericTypeArguments: false', rule, { }, ], }, + { + code: 'type invalidVoidUnion = void | number;', + options: [{ allowInGenericTypeArguments: false }], + errors: [ + { + messageId: 'invalidVoidNotReturn', + line: 1, + column: 25, + }, + ], + }, ], }); @@ -89,6 +117,8 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { 'type UnionType = string | number;', 'type GenericVoid = Generic;', 'type Generic = [T];', + 'type voidPromiseUnion = void | Promise;', + 'type promiseNeverUnion = Promise | never;', ], invalid: [ { @@ -315,7 +345,6 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { { code: ` type VoidType = void; - class OtherClassName { private propName: VoidType; } @@ -406,6 +435,16 @@ ruleTester.run('allowInGenericTypeArguments: true', rule, { }, ], }, + { + code: 'type invalidVoidUnion = void | Map;', + errors: [ + { + messageId: 'invalidVoidNotReturnOrGeneric', + line: 1, + column: 25, + }, + ], + }, ], }); @@ -435,6 +474,31 @@ ruleTester.run('allowInGenericTypeArguments: whitelist', rule, { code: 'type AllowedVoid = Ex.Mx.Tx;', options: [{ allowInGenericTypeArguments: ['Ex . Mx . Tx'] }], }, + { + code: 'type voidPromiseUnion = void | Promise;', + options: [{ allowInGenericTypeArguments: ['Promise'] }], + }, + { + code: 'type promiseVoidUnion = Promise | void;', + options: [{ allowInGenericTypeArguments: ['Promise'] }], + }, + { + // https://github.com/typescript-eslint/typescript-eslint/issues/1956 + code: ` +async function foo(bar: () => void | Promise) { + await bar(); +} + `, + options: [{ allowInGenericTypeArguments: ['Promise'] }], + }, + { + code: 'type promiseNeverUnion = Promise | never;', + options: [{ allowInGenericTypeArguments: ['Promise'] }], + }, + { + code: 'type voidPromiseNeverUnion = void | Promise | never;', + options: [{ allowInGenericTypeArguments: ['Promise'] }], + }, ], invalid: [ { diff --git a/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts b/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts index 2f5900f3d2ac..9b991053dcb2 100644 --- a/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts +++ b/packages/eslint-plugin/tests/rules/restrict-template-expressions.test.ts @@ -214,33 +214,68 @@ ruleTester.run('restrict-template-expressions', rule, { code: ` const msg = \`arg = \${123}\`; `, - errors: [{ messageId: 'invalidType', line: 2, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: '123' }, + line: 2, + column: 30, + }, + ], }, { code: ` const msg = \`arg = \${false}\`; `, - errors: [{ messageId: 'invalidType', line: 2, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: 'false' }, + line: 2, + column: 30, + }, + ], }, { code: ` const msg = \`arg = \${null}\`; `, - errors: [{ messageId: 'invalidType', line: 2, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: 'null' }, + line: 2, + column: 30, + }, + ], }, { code: ` declare const arg: number; const msg = \`arg = \${arg}\`; `, - errors: [{ messageId: 'invalidType', line: 3, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: 'number' }, + line: 3, + column: 30, + }, + ], }, { code: ` declare const arg: boolean; const msg = \`arg = \${arg}\`; `, - errors: [{ messageId: 'invalidType', line: 3, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: 'boolean' }, + line: 3, + column: 30, + }, + ], }, { options: [{ allowNumber: true, allowBoolean: true, allowNullable: true }], @@ -248,14 +283,23 @@ ruleTester.run('restrict-template-expressions', rule, { const arg = {}; const msg = \`arg = \${arg}\`; `, - errors: [{ messageId: 'invalidType', line: 3, column: 30 }], + errors: [ + { messageId: 'invalidType', data: { type: '{}' }, line: 3, column: 30 }, + ], }, { code: ` declare const arg: { a: string } & { b: string }; const msg = \`arg = \${arg}\`; `, - errors: [{ messageId: 'invalidType', line: 3, column: 30 }], + errors: [ + { + messageId: 'invalidType', + data: { type: '{ a: string; } & { b: string; }' }, + line: 3, + column: 30, + }, + ], }, { options: [{ allowNumber: true, allowBoolean: true, allowNullable: true }], @@ -264,7 +308,25 @@ ruleTester.run('restrict-template-expressions', rule, { return \`arg = \${arg}\`; } `, - errors: [{ messageId: 'invalidType', line: 3, column: 27 }], + errors: [ + { messageId: 'invalidType', data: { type: '{}' }, line: 3, column: 27 }, + ], + }, + { + options: [{ allowNumber: true, allowBoolean: true, allowNullable: true }], + code: ` + function test(arg: T) { + return \`arg = \${arg}\`; + } + `, + errors: [ + { + messageId: 'invalidType', + data: { type: 'any' }, + line: 3, + column: 27, + }, + ], }, { options: [{ allowNumber: true, allowBoolean: true, allowNullable: true }], @@ -273,7 +335,14 @@ ruleTester.run('restrict-template-expressions', rule, { return \`arg = \${arg}\`; } `, - errors: [{ messageId: 'invalidType', line: 3, column: 27 }], + errors: [ + { + messageId: 'invalidType', + data: { type: 'any' }, + line: 3, + column: 27, + }, + ], }, ], }); diff --git a/packages/experimental-utils/CHANGELOG.md b/packages/experimental-utils/CHANGELOG.md index 132a0d2f1f61..35689c4465cb 100644 --- a/packages/experimental-utils/CHANGELOG.md +++ b/packages/experimental-utils/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + + +### Features + +* **experimental-utils:** add `suggestion` property for rule modules ([#2033](https://github.com/typescript-eslint/typescript-eslint/issues/2033)) ([f42a5b0](https://github.com/typescript-eslint/typescript-eslint/commit/f42a5b09ebfa173f418a99c552b0cbe221567194)) + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) diff --git a/packages/experimental-utils/package.json b/packages/experimental-utils/package.json index 6ef323773aff..c6b35d0f1cc5 100644 --- a/packages/experimental-utils/package.json +++ b/packages/experimental-utils/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/experimental-utils", - "version": "2.33.0", + "version": "2.34.0", "description": "(Experimental) Utilities for working with TypeScript + ESLint together", "keywords": [ "eslint", @@ -37,7 +37,7 @@ }, "dependencies": { "@types/json-schema": "^7.0.3", - "@typescript-eslint/typescript-estree": "2.33.0", + "@typescript-eslint/typescript-estree": "2.34.0", "eslint-scope": "^5.0.0", "eslint-utils": "^2.0.0" }, diff --git a/packages/experimental-utils/src/ts-eslint/Rule.ts b/packages/experimental-utils/src/ts-eslint/Rule.ts index 61f9cd7611e9..12a3bed1f75f 100644 --- a/packages/experimental-utils/src/ts-eslint/Rule.ts +++ b/packages/experimental-utils/src/ts-eslint/Rule.ts @@ -28,6 +28,10 @@ interface RuleMetaDataDocs { * The URL of the rule's docs */ url: string; + /** + * Specifies whether the rule can return suggestions. + */ + suggestion?: boolean; /** * Does the rule require us to create a full TypeScript Program in order for it * to type-check code. This is only used for documentation purposes. diff --git a/packages/parser/CHANGELOG.md b/packages/parser/CHANGELOG.md index 503271e506ab..60c7c399d3bb 100644 --- a/packages/parser/CHANGELOG.md +++ b/packages/parser/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + +**Note:** Version bump only for package @typescript-eslint/parser + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) **Note:** Version bump only for package @typescript-eslint/parser diff --git a/packages/parser/package.json b/packages/parser/package.json index f0ff21651ff1..c28df64833cb 100644 --- a/packages/parser/package.json +++ b/packages/parser/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/parser", - "version": "2.33.0", + "version": "2.34.0", "description": "An ESLint custom parser which leverages TypeScript ESTree", "main": "dist/parser.js", "types": "dist/parser.d.ts", @@ -43,13 +43,13 @@ }, "dependencies": { "@types/eslint-visitor-keys": "^1.0.0", - "@typescript-eslint/experimental-utils": "2.33.0", - "@typescript-eslint/typescript-estree": "2.33.0", + "@typescript-eslint/experimental-utils": "2.34.0", + "@typescript-eslint/typescript-estree": "2.34.0", "eslint-visitor-keys": "^1.1.0" }, "devDependencies": { "@types/glob": "^7.1.1", - "@typescript-eslint/shared-fixtures": "2.33.0", + "@typescript-eslint/shared-fixtures": "2.34.0", "glob": "*" }, "peerDependenciesMeta": { diff --git a/packages/shared-fixtures/CHANGELOG.md b/packages/shared-fixtures/CHANGELOG.md index 5fd667bd2cae..3c9b56119594 100644 --- a/packages/shared-fixtures/CHANGELOG.md +++ b/packages/shared-fixtures/CHANGELOG.md @@ -3,6 +3,14 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + +**Note:** Version bump only for package @typescript-eslint/shared-fixtures + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) **Note:** Version bump only for package @typescript-eslint/shared-fixtures diff --git a/packages/shared-fixtures/package.json b/packages/shared-fixtures/package.json index 70175b4675a0..1cbdc49e86b6 100644 --- a/packages/shared-fixtures/package.json +++ b/packages/shared-fixtures/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/shared-fixtures", - "version": "2.33.0", + "version": "2.34.0", "private": true, "scripts": { "build": "tsc -b tsconfig.build.json", diff --git a/packages/typescript-estree/CHANGELOG.md b/packages/typescript-estree/CHANGELOG.md index 3f9012b9b694..bc06b6d34f19 100644 --- a/packages/typescript-estree/CHANGELOG.md +++ b/packages/typescript-estree/CHANGELOG.md @@ -3,6 +3,17 @@ All notable changes to this project will be documented in this file. See [Conventional Commits](https://conventionalcommits.org) for commit guidelines. +# [2.34.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.33.0...v2.34.0) (2020-05-18) + + +### Bug Fixes + +* **typescript-estree:** fix handling of range/loc removal ([#2028](https://github.com/typescript-eslint/typescript-eslint/issues/2028)) ([ce344d9](https://github.com/typescript-eslint/typescript-eslint/commit/ce344d90e7c78b0c4b4b823494a3e78190f45c64)) + + + + + # [2.33.0](https://github.com/typescript-eslint/typescript-eslint/compare/v2.32.0...v2.33.0) (2020-05-12) **Note:** Version bump only for package @typescript-eslint/typescript-estree diff --git a/packages/typescript-estree/package.json b/packages/typescript-estree/package.json index 100895b994a1..5568f20ff8f2 100644 --- a/packages/typescript-estree/package.json +++ b/packages/typescript-estree/package.json @@ -1,6 +1,6 @@ { "name": "@typescript-eslint/typescript-estree", - "version": "2.33.0", + "version": "2.34.0", "description": "A parser that converts TypeScript source code into an ESTree compatible form", "main": "dist/parser.js", "types": "dist/parser.d.ts", @@ -58,7 +58,7 @@ "@types/lodash": "^4.14.149", "@types/semver": "^7.1.0", "@types/tmp": "^0.2.0", - "@typescript-eslint/shared-fixtures": "2.33.0", + "@typescript-eslint/shared-fixtures": "2.34.0", "tmp": "^0.2.1", "typescript": "*" }, diff --git a/packages/typescript-estree/src/ast-converter.ts b/packages/typescript-estree/src/ast-converter.ts index 270d50dde3f7..54f325429dff 100644 --- a/packages/typescript-estree/src/ast-converter.ts +++ b/packages/typescript-estree/src/ast-converter.ts @@ -36,7 +36,7 @@ export function astConverter( /** * Optionally remove range and loc if specified */ - if (extra.range || extra.loc) { + if (!extra.range || !extra.loc) { simpleTraverse(estree, { enter: node => { if (!extra.range) {