@typescript-eslint/eslint-plugin
Advanced tools
Comparing version 5.57.0 to 6.15.0
"use strict"; | ||
// THIS CODE WAS AUTOMATICALLY GENERATED | ||
// DO NOT EDIT THIS CODE BY HAND | ||
// YOU CAN REGENERATE IT USING yarn generate:configs | ||
// SEE https://typescript-eslint.io/linting/configs | ||
// | ||
// For developers working in the typescript-eslint monorepo: | ||
// You can regenerate it using `yarn generate:configs` | ||
module.exports = { | ||
@@ -19,2 +22,4 @@ extends: ['./configs/base', './configs/eslint-recommended'], | ||
'@typescript-eslint/class-literal-property-style': 'error', | ||
'class-methods-use-this': 'off', | ||
'@typescript-eslint/class-methods-use-this': 'error', | ||
'comma-dangle': 'off', | ||
@@ -51,2 +56,4 @@ '@typescript-eslint/comma-dangle': 'error', | ||
'@typescript-eslint/lines-between-class-members': 'error', | ||
'max-params': 'off', | ||
'@typescript-eslint/max-params': 'error', | ||
'@typescript-eslint/member-delimiter-style': 'error', | ||
@@ -110,3 +117,2 @@ '@typescript-eslint/member-ordering': 'error', | ||
'@typescript-eslint/no-throw-literal': 'error', | ||
'@typescript-eslint/no-type-alias': 'error', | ||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'error', | ||
@@ -122,4 +128,6 @@ '@typescript-eslint/no-unnecessary-condition': 'error', | ||
'@typescript-eslint/no-unsafe-declaration-merging': 'error', | ||
'@typescript-eslint/no-unsafe-enum-comparison': 'error', | ||
'@typescript-eslint/no-unsafe-member-access': 'error', | ||
'@typescript-eslint/no-unsafe-return': 'error', | ||
'@typescript-eslint/no-unsafe-unary-minus': 'error', | ||
'no-unused-expressions': 'off', | ||
@@ -134,2 +142,3 @@ '@typescript-eslint/no-unused-expressions': 'error', | ||
'@typescript-eslint/no-useless-empty-export': 'error', | ||
'@typescript-eslint/no-useless-template-literals': 'error', | ||
'@typescript-eslint/no-var-requires': 'error', | ||
@@ -143,2 +152,4 @@ '@typescript-eslint/non-nullable-type-assertion-style': 'error', | ||
'@typescript-eslint/prefer-as-const': 'error', | ||
'prefer-destructuring': 'off', | ||
'@typescript-eslint/prefer-destructuring': 'error', | ||
'@typescript-eslint/prefer-enum-initializers': 'error', | ||
@@ -145,0 +156,0 @@ '@typescript-eslint/prefer-for-of': 'error', |
"use strict"; | ||
// THIS CODE WAS AUTOMATICALLY GENERATED | ||
// DO NOT EDIT THIS CODE BY HAND | ||
// YOU CAN REGENERATE IT USING yarn generate:configs | ||
// SEE https://typescript-eslint.io/linting/configs | ||
// | ||
// For developers working in the typescript-eslint monorepo: | ||
// You can regenerate it using `yarn generate:configs` | ||
module.exports = { | ||
@@ -6,0 +9,0 @@ parser: '@typescript-eslint/parser', |
@@ -7,23 +7,22 @@ "use strict"; | ||
rules: { | ||
'constructor-super': 'off', | ||
'getter-return': 'off', | ||
'no-const-assign': 'off', | ||
'no-dupe-args': 'off', | ||
'no-dupe-class-members': 'off', | ||
'no-dupe-keys': 'off', | ||
'no-func-assign': 'off', | ||
'no-import-assign': 'off', | ||
'no-new-symbol': 'off', | ||
'no-obj-calls': 'off', | ||
'no-redeclare': 'off', | ||
'no-setter-return': 'off', | ||
'no-this-before-super': 'off', | ||
'no-undef': 'off', | ||
'no-unreachable': 'off', | ||
'no-unsafe-negation': 'off', | ||
'no-var': 'error', | ||
'prefer-const': 'error', | ||
'prefer-rest-params': 'error', | ||
'prefer-spread': 'error', | ||
'valid-typeof': 'off', // ts(2367) | ||
'constructor-super': 'off', // ts(2335) & ts(2377) | ||
'getter-return': 'off', // ts(2378) | ||
'no-const-assign': 'off', // ts(2588) | ||
'no-dupe-args': 'off', // ts(2300) | ||
'no-dupe-class-members': 'off', // ts(2393) & ts(2300) | ||
'no-dupe-keys': 'off', // ts(1117) | ||
'no-func-assign': 'off', // ts(2630) | ||
'no-import-assign': 'off', // ts(2632) & ts(2540) | ||
'no-new-symbol': 'off', // ts(7009) | ||
'no-obj-calls': 'off', // ts(2349) | ||
'no-redeclare': 'off', // ts(2451) | ||
'no-setter-return': 'off', // ts(2408) | ||
'no-this-before-super': 'off', // ts(2376) & ts(17009) | ||
'no-undef': 'off', // ts(2304) & ts(2552) | ||
'no-unreachable': 'off', // ts(7027) | ||
'no-unsafe-negation': 'off', // ts(2365) & ts(2322) & ts(2358) | ||
'no-var': 'error', // ts transpiles let/const to var, so no need for vars any more | ||
'prefer-const': 'error', // ts provides better types with const | ||
'prefer-rest-params': 'error', // ts provides better types with rest args over arguments | ||
'prefer-spread': 'error', // ts transpiles spread to apply, so no need for manual apply | ||
}, | ||
@@ -30,0 +29,0 @@ }, |
"use strict"; | ||
// THIS CODE WAS AUTOMATICALLY GENERATED | ||
// DO NOT EDIT THIS CODE BY HAND | ||
// YOU CAN REGENERATE IT USING yarn generate:configs | ||
// SEE https://typescript-eslint.io/linting/configs | ||
// | ||
// For developers working in the typescript-eslint monorepo: | ||
// You can regenerate it using `yarn generate:configs` | ||
module.exports = { | ||
extends: ['./configs/base', './configs/eslint-recommended'], | ||
rules: { | ||
'@typescript-eslint/adjacent-overload-signatures': 'error', | ||
'@typescript-eslint/ban-ts-comment': 'error', | ||
@@ -13,10 +15,5 @@ '@typescript-eslint/ban-types': 'error', | ||
'@typescript-eslint/no-array-constructor': 'error', | ||
'no-empty-function': 'off', | ||
'@typescript-eslint/no-empty-function': 'error', | ||
'@typescript-eslint/no-empty-interface': 'error', | ||
'@typescript-eslint/no-explicit-any': 'warn', | ||
'@typescript-eslint/no-duplicate-enum-values': 'error', | ||
'@typescript-eslint/no-explicit-any': 'error', | ||
'@typescript-eslint/no-extra-non-null-assertion': 'error', | ||
'no-extra-semi': 'off', | ||
'@typescript-eslint/no-extra-semi': 'error', | ||
'@typescript-eslint/no-inferrable-types': 'error', | ||
'no-loss-of-precision': 'off', | ||
@@ -27,10 +24,9 @@ '@typescript-eslint/no-loss-of-precision': 'error', | ||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error', | ||
'@typescript-eslint/no-non-null-assertion': 'warn', | ||
'@typescript-eslint/no-this-alias': 'error', | ||
'@typescript-eslint/no-unnecessary-type-constraint': 'error', | ||
'@typescript-eslint/no-unsafe-declaration-merging': 'error', | ||
'no-unused-vars': 'off', | ||
'@typescript-eslint/no-unused-vars': 'warn', | ||
'@typescript-eslint/no-unused-vars': 'error', | ||
'@typescript-eslint/no-var-requires': 'error', | ||
'@typescript-eslint/prefer-as-const': 'error', | ||
'@typescript-eslint/prefer-namespace-keyword': 'error', | ||
'@typescript-eslint/triple-slash-reference': 'error', | ||
@@ -37,0 +33,0 @@ }, |
"use strict"; | ||
// THIS CODE WAS AUTOMATICALLY GENERATED | ||
// DO NOT EDIT THIS CODE BY HAND | ||
// YOU CAN REGENERATE IT USING yarn generate:configs | ||
// SEE https://typescript-eslint.io/linting/configs | ||
// | ||
// For developers working in the typescript-eslint monorepo: | ||
// You can regenerate it using `yarn generate:configs` | ||
module.exports = { | ||
extends: ['./configs/base', './configs/eslint-recommended'], | ||
rules: { | ||
'@typescript-eslint/array-type': 'warn', | ||
'@typescript-eslint/ban-tslint-comment': 'warn', | ||
'@typescript-eslint/class-literal-property-style': 'warn', | ||
'@typescript-eslint/consistent-generic-constructors': 'warn', | ||
'@typescript-eslint/consistent-indexed-object-style': 'warn', | ||
'@typescript-eslint/consistent-type-assertions': 'warn', | ||
'@typescript-eslint/consistent-type-definitions': 'warn', | ||
'dot-notation': 'off', | ||
'@typescript-eslint/dot-notation': 'warn', | ||
'@typescript-eslint/no-base-to-string': 'warn', | ||
'@typescript-eslint/no-confusing-non-null-assertion': 'warn', | ||
'@typescript-eslint/no-duplicate-enum-values': 'warn', | ||
'@typescript-eslint/no-dynamic-delete': 'warn', | ||
'@typescript-eslint/no-extraneous-class': 'warn', | ||
'@typescript-eslint/no-invalid-void-type': 'warn', | ||
'@typescript-eslint/no-meaningless-void-operator': 'warn', | ||
'@typescript-eslint/no-mixed-enums': 'warn', | ||
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'warn', | ||
'no-throw-literal': 'off', | ||
'@typescript-eslint/no-throw-literal': 'warn', | ||
'@typescript-eslint/no-unnecessary-boolean-literal-compare': 'warn', | ||
'@typescript-eslint/no-unnecessary-condition': 'warn', | ||
'@typescript-eslint/no-unnecessary-type-arguments': 'warn', | ||
'@typescript-eslint/no-unsafe-declaration-merging': 'warn', | ||
'@typescript-eslint/ban-ts-comment': 'error', | ||
'@typescript-eslint/ban-types': 'error', | ||
'no-array-constructor': 'off', | ||
'@typescript-eslint/no-array-constructor': 'error', | ||
'@typescript-eslint/no-duplicate-enum-values': 'error', | ||
'@typescript-eslint/no-dynamic-delete': 'error', | ||
'@typescript-eslint/no-explicit-any': 'error', | ||
'@typescript-eslint/no-extra-non-null-assertion': 'error', | ||
'@typescript-eslint/no-extraneous-class': 'error', | ||
'@typescript-eslint/no-invalid-void-type': 'error', | ||
'no-loss-of-precision': 'off', | ||
'@typescript-eslint/no-loss-of-precision': 'error', | ||
'@typescript-eslint/no-misused-new': 'error', | ||
'@typescript-eslint/no-namespace': 'error', | ||
'@typescript-eslint/no-non-null-asserted-nullish-coalescing': 'error', | ||
'@typescript-eslint/no-non-null-asserted-optional-chain': 'error', | ||
'@typescript-eslint/no-non-null-assertion': 'error', | ||
'@typescript-eslint/no-this-alias': 'error', | ||
'@typescript-eslint/no-unnecessary-type-constraint': 'error', | ||
'@typescript-eslint/no-unsafe-declaration-merging': 'error', | ||
'no-unused-vars': 'off', | ||
'@typescript-eslint/no-unused-vars': 'error', | ||
'no-useless-constructor': 'off', | ||
'@typescript-eslint/no-useless-constructor': 'warn', | ||
'@typescript-eslint/non-nullable-type-assertion-style': 'warn', | ||
'@typescript-eslint/prefer-for-of': 'warn', | ||
'@typescript-eslint/prefer-function-type': 'warn', | ||
'@typescript-eslint/prefer-includes': 'warn', | ||
'@typescript-eslint/prefer-literal-enum-member': 'warn', | ||
'@typescript-eslint/prefer-nullish-coalescing': 'warn', | ||
'@typescript-eslint/prefer-optional-chain': 'warn', | ||
'@typescript-eslint/prefer-reduce-type-parameter': 'warn', | ||
'@typescript-eslint/prefer-return-this-type': 'warn', | ||
'@typescript-eslint/prefer-string-starts-ends-with': 'warn', | ||
'@typescript-eslint/prefer-ts-expect-error': 'warn', | ||
'@typescript-eslint/unified-signatures': 'warn', | ||
'@typescript-eslint/no-useless-constructor': 'error', | ||
'@typescript-eslint/no-var-requires': 'error', | ||
'@typescript-eslint/prefer-as-const': 'error', | ||
'@typescript-eslint/prefer-literal-enum-member': 'error', | ||
'@typescript-eslint/prefer-ts-expect-error': 'error', | ||
'@typescript-eslint/triple-slash-reference': 'error', | ||
'@typescript-eslint/unified-signatures': 'error', | ||
}, | ||
}; | ||
//# sourceMappingURL=strict.js.map |
@@ -7,18 +7,28 @@ "use strict"; | ||
const base_1 = __importDefault(require("./configs/base")); | ||
const disable_type_checked_1 = __importDefault(require("./configs/disable-type-checked")); | ||
const eslint_recommended_1 = __importDefault(require("./configs/eslint-recommended")); | ||
const recommended_1 = __importDefault(require("./configs/recommended")); | ||
const recommended_requiring_type_checking_1 = __importDefault(require("./configs/recommended-requiring-type-checking")); | ||
const recommended_type_checked_1 = __importDefault(require("./configs/recommended-type-checked")); | ||
const strict_1 = __importDefault(require("./configs/strict")); | ||
const strict_type_checked_1 = __importDefault(require("./configs/strict-type-checked")); | ||
const stylistic_1 = __importDefault(require("./configs/stylistic")); | ||
const stylistic_type_checked_1 = __importDefault(require("./configs/stylistic-type-checked")); | ||
const rules_1 = __importDefault(require("./rules")); | ||
module.exports = { | ||
rules: rules_1.default, | ||
configs: { | ||
all: all_1.default, | ||
base: base_1.default, | ||
'disable-type-checked': disable_type_checked_1.default, | ||
'eslint-recommended': eslint_recommended_1.default, | ||
recommended: recommended_1.default, | ||
'eslint-recommended': eslint_recommended_1.default, | ||
'recommended-requiring-type-checking': recommended_requiring_type_checking_1.default, | ||
/** @deprecated - please use "recommended-type-checked" instead. */ | ||
'recommended-requiring-type-checking': recommended_type_checked_1.default, | ||
'recommended-type-checked': recommended_type_checked_1.default, | ||
strict: strict_1.default, | ||
'strict-type-checked': strict_type_checked_1.default, | ||
stylistic: stylistic_1.default, | ||
'stylistic-type-checked': stylistic_type_checked_1.default, | ||
}, | ||
rules: rules_1.default, | ||
}; | ||
//# sourceMappingURL=index.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'adjacent-overload-signatures', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Require that function overload signatures be consecutive', | ||
recommended: 'error', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -44,3 +22,3 @@ schema: [], | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
/** | ||
@@ -52,6 +30,2 @@ * Gets the name and attribute of the member being processed. | ||
function getMemberMethod(member) { | ||
var _a, _b; | ||
if (!member) { | ||
return null; | ||
} | ||
const isStatic = 'static' in member && !!member.static; | ||
@@ -70,3 +44,3 @@ switch (member.type) { | ||
case utils_1.AST_NODE_TYPES.FunctionDeclaration: { | ||
const name = (_b = (_a = member.id) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : null; | ||
const name = member.id?.name ?? null; | ||
if (name == null) { | ||
@@ -79,7 +53,11 @@ return null; | ||
callSignature: false, | ||
type: util.MemberNameType.Normal, | ||
type: util_1.MemberNameType.Normal, | ||
}; | ||
} | ||
case utils_1.AST_NODE_TYPES.TSMethodSignature: | ||
return Object.assign(Object.assign({}, util.getNameFromMember(member, sourceCode)), { static: isStatic, callSignature: false }); | ||
return { | ||
...(0, util_1.getNameFromMember)(member, sourceCode), | ||
static: isStatic, | ||
callSignature: false, | ||
}; | ||
case utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration: | ||
@@ -90,3 +68,3 @@ return { | ||
callSignature: true, | ||
type: util.MemberNameType.Normal, | ||
type: util_1.MemberNameType.Normal, | ||
}; | ||
@@ -98,6 +76,10 @@ case utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration: | ||
callSignature: false, | ||
type: util.MemberNameType.Normal, | ||
type: util_1.MemberNameType.Normal, | ||
}; | ||
case utils_1.AST_NODE_TYPES.MethodDefinition: | ||
return Object.assign(Object.assign({}, util.getNameFromMember(member, sourceCode)), { static: isStatic, callSignature: false }); | ||
return { | ||
...(0, util_1.getNameFromMember)(member, sourceCode), | ||
static: isStatic, | ||
callSignature: false, | ||
}; | ||
} | ||
@@ -131,27 +113,25 @@ return null; | ||
const members = getMembers(node); | ||
if (members) { | ||
let lastMethod = null; | ||
const seenMethods = []; | ||
members.forEach(member => { | ||
const method = getMemberMethod(member); | ||
if (method == null) { | ||
lastMethod = null; | ||
return; | ||
} | ||
const index = seenMethods.findIndex(seenMethod => isSameMethod(method, seenMethod)); | ||
if (index > -1 && !isSameMethod(method, lastMethod)) { | ||
context.report({ | ||
node: member, | ||
messageId: 'adjacentSignature', | ||
data: { | ||
name: `${method.static ? 'static ' : ''}${method.name}`, | ||
}, | ||
}); | ||
} | ||
else if (index === -1) { | ||
seenMethods.push(method); | ||
} | ||
lastMethod = method; | ||
}); | ||
} | ||
let lastMethod = null; | ||
const seenMethods = []; | ||
members.forEach(member => { | ||
const method = getMemberMethod(member); | ||
if (method == null) { | ||
lastMethod = null; | ||
return; | ||
} | ||
const index = seenMethods.findIndex(seenMethod => isSameMethod(method, seenMethod)); | ||
if (index > -1 && !isSameMethod(method, lastMethod)) { | ||
context.report({ | ||
node: member, | ||
messageId: 'adjacentSignature', | ||
data: { | ||
name: `${method.static ? 'static ' : ''}${method.name}`, | ||
}, | ||
}); | ||
} | ||
else if (index === -1) { | ||
seenMethods.push(method); | ||
} | ||
lastMethod = method; | ||
}); | ||
} | ||
@@ -158,0 +138,0 @@ return { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
/** | ||
@@ -52,14 +30,13 @@ * Check whatever node can be considered as simple | ||
case utils_1.AST_NODE_TYPES.TSTypeReference: | ||
if (node.typeName && | ||
node.typeName.type === utils_1.AST_NODE_TYPES.Identifier && | ||
if (node.typeName.type === utils_1.AST_NODE_TYPES.Identifier && | ||
node.typeName.name === 'Array') { | ||
if (!node.typeParameters) { | ||
if (!node.typeArguments) { | ||
return true; | ||
} | ||
if (node.typeParameters.params.length === 1) { | ||
return isSimpleType(node.typeParameters.params[0]); | ||
if (node.typeArguments.params.length === 1) { | ||
return isSimpleType(node.typeArguments.params[0]); | ||
} | ||
} | ||
else { | ||
if (node.typeParameters) { | ||
if (node.typeArguments) { | ||
return false; | ||
@@ -95,3 +72,3 @@ } | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'array-type', | ||
@@ -102,3 +79,3 @@ meta: { | ||
description: 'Require consistently using either `T[]` or `Array<T>` for arrays', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -112,25 +89,24 @@ fixable: 'code', | ||
}, | ||
schema: { | ||
$defs: { | ||
arrayOption: { | ||
enum: ['array', 'generic', 'array-simple'], | ||
schema: [ | ||
{ | ||
$defs: { | ||
arrayOption: { | ||
type: 'string', | ||
enum: ['array', 'generic', 'array-simple'], | ||
}, | ||
}, | ||
}, | ||
prefixItems: [ | ||
{ | ||
properties: { | ||
default: { | ||
$ref: '#/$defs/arrayOption', | ||
description: 'The array type expected for mutable cases...', | ||
}, | ||
readonly: { | ||
$ref: '#/$defs/arrayOption', | ||
description: 'The array type expected for readonly cases. If omitted, the value for `default` will be used.', | ||
}, | ||
additionalProperties: false, | ||
properties: { | ||
default: { | ||
$ref: '#/items/0/$defs/arrayOption', | ||
description: 'The array type expected for mutable cases.', | ||
}, | ||
type: 'object', | ||
readonly: { | ||
$ref: '#/items/0/$defs/arrayOption', | ||
description: 'The array type expected for readonly cases. If omitted, the value for `default` will be used.', | ||
}, | ||
}, | ||
], | ||
type: 'array', | ||
}, | ||
type: 'object', | ||
}, | ||
], | ||
}, | ||
@@ -143,6 +119,5 @@ defaultOptions: [ | ||
create(context, [options]) { | ||
var _a; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const defaultOption = options.default; | ||
const readonlyOption = (_a = options.readonly) !== null && _a !== void 0 ? _a : defaultOption; | ||
const readonlyOption = options.readonly ?? defaultOption; | ||
/** | ||
@@ -152,3 +127,3 @@ * @param node the node to be evaluated. | ||
function getMessageType(node) { | ||
if (node && isSimpleType(node)) { | ||
if (isSimpleType(node)) { | ||
return sourceCode.getText(node); | ||
@@ -160,4 +135,3 @@ } | ||
TSArrayType(node) { | ||
const isReadonly = node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.TSTypeOperator && | ||
const isReadonly = node.parent.type === utils_1.AST_NODE_TYPES.TSTypeOperator && | ||
node.parent.operator === 'readonly'; | ||
@@ -192,3 +166,2 @@ const currentOption = isReadonly ? readonlyOption : defaultOption; | ||
TSTypeReference(node) { | ||
var _a, _b; | ||
if (node.typeName.type !== utils_1.AST_NODE_TYPES.Identifier || | ||
@@ -207,3 +180,3 @@ !(node.typeName.name === 'Array' || | ||
const readonlyPrefix = isReadonlyArrayType ? 'readonly ' : ''; | ||
const typeParams = (_a = node.typeParameters) === null || _a === void 0 ? void 0 : _a.params; | ||
const typeParams = node.typeArguments?.params; | ||
const messageId = currentOption === 'array' | ||
@@ -235,4 +208,4 @@ ? 'errorStringArray' | ||
const parentParens = readonlyPrefix && | ||
((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSArrayType && | ||
!util.isParenthesized(node.parent.elementType, sourceCode); | ||
node.parent.type === utils_1.AST_NODE_TYPES.TSArrayType && | ||
!(0, util_1.isParenthesized)(node.parent.elementType, sourceCode); | ||
const start = `${parentParens ? '(' : ''}${readonlyPrefix}${typeParens ? '(' : ''}`; | ||
@@ -239,0 +212,0 @@ const end = `${typeParens ? ')' : ''}[]${parentParens ? ')' : ''}`; |
@@ -26,5 +26,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'await-thenable', | ||
@@ -34,7 +35,9 @@ meta: { | ||
description: 'Disallow awaiting a value that is not a Thenable', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
}, | ||
hasSuggestions: true, | ||
messages: { | ||
await: 'Unexpected `await` of a non-Promise (non-"Thenable") value.', | ||
removeAwait: 'Remove unnecessary `await`.', | ||
}, | ||
@@ -46,14 +49,25 @@ schema: [], | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
return { | ||
AwaitExpression(node) { | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = checker.getTypeAtLocation(originalNode.expression); | ||
if (!util.isTypeAnyType(type) && | ||
!util.isTypeUnknownType(type) && | ||
!tsutils.isThenableType(checker, originalNode.expression, type)) { | ||
const type = services.getTypeAtLocation(node.argument); | ||
if ((0, util_1.isTypeAnyType)(type) || (0, util_1.isTypeUnknownType)(type)) { | ||
return; | ||
} | ||
const originalNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (!tsutils.isThenableType(checker, originalNode.expression, type)) { | ||
context.report({ | ||
messageId: 'await', | ||
node, | ||
suggest: [ | ||
{ | ||
messageId: 'removeAwait', | ||
fix(fixer) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const awaitKeyword = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isAwaitKeyword), util_1.NullThrowsReasons.MissingToken('await', 'await expression')); | ||
return fixer.remove(awaitKeyword); | ||
}, | ||
}, | ||
], | ||
}); | ||
@@ -60,0 +74,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.defaultMinimumDescriptionLength = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.defaultMinimumDescriptionLength = 3; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'ban-ts-comment', | ||
@@ -36,48 +14,49 @@ meta: { | ||
description: 'Disallow `@ts-<directive>` comments or require descriptions after directives', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
messages: { | ||
tsDirectiveComment: 'Do not use "@ts-{{directive}}" because it alters compilation errors.', | ||
tsIgnoreInsteadOfExpectError: 'Use "@ts-expect-error" instead of "@ts-ignore", as "@ts-ignore" will do nothing if the following line is error-free.', | ||
tsDirectiveCommentRequiresDescription: 'Include a description after the "@ts-{{directive}}" directive to explain why the @ts-{{directive}} is necessary. The description must be {{minimumDescriptionLength}} characters or longer.', | ||
tsDirectiveCommentDescriptionNotMatchPattern: 'The description for the "@ts-{{directive}}" directive must match the {{format}} format.', | ||
replaceTsIgnoreWithTsExpectError: 'Replace "@ts-ignore" with "@ts-expect-error".', | ||
}, | ||
schema: { | ||
$defs: { | ||
directiveConfigSchema: { | ||
oneOf: [ | ||
{ | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
{ | ||
enum: ['allow-with-description'], | ||
}, | ||
{ | ||
type: 'object', | ||
properties: { | ||
descriptionFormat: { type: 'string' }, | ||
hasSuggestions: true, | ||
schema: [ | ||
{ | ||
$defs: { | ||
directiveConfigSchema: { | ||
oneOf: [ | ||
{ | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
}, | ||
], | ||
{ | ||
type: 'string', | ||
enum: ['allow-with-description'], | ||
}, | ||
{ | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
descriptionFormat: { type: 'string' }, | ||
}, | ||
}, | ||
], | ||
}, | ||
}, | ||
}, | ||
prefixItems: [ | ||
{ | ||
properties: { | ||
'ts-expect-error': { | ||
$ref: '#/$defs/directiveConfigSchema', | ||
}, | ||
'ts-ignore': { $ref: '#/$defs/directiveConfigSchema' }, | ||
'ts-nocheck': { $ref: '#/$defs/directiveConfigSchema' }, | ||
'ts-check': { $ref: '#/$defs/directiveConfigSchema' }, | ||
minimumDescriptionLength: { | ||
type: 'number', | ||
default: exports.defaultMinimumDescriptionLength, | ||
}, | ||
properties: { | ||
'ts-expect-error': { $ref: '#/items/0/$defs/directiveConfigSchema' }, | ||
'ts-ignore': { $ref: '#/items/0/$defs/directiveConfigSchema' }, | ||
'ts-nocheck': { $ref: '#/items/0/$defs/directiveConfigSchema' }, | ||
'ts-check': { $ref: '#/items/0/$defs/directiveConfigSchema' }, | ||
minimumDescriptionLength: { | ||
type: 'number', | ||
default: exports.defaultMinimumDescriptionLength, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
type: 'array', | ||
}, | ||
type: 'object', | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
@@ -100,3 +79,3 @@ defaultOptions: [ | ||
const commentDirectiveRegExMultiLine = /^\s*(?:\/|\*)*\s*@ts-(?<directive>expect-error|ignore|check|nocheck)(?<description>.*)/; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const descriptionFormats = new Map(); | ||
@@ -129,7 +108,27 @@ for (const directive of [ | ||
if (option === true) { | ||
context.report({ | ||
data: { directive }, | ||
node: comment, | ||
messageId: 'tsDirectiveComment', | ||
}); | ||
if (directive === 'ignore') { | ||
// Special case to suggest @ts-expect-error instead of @ts-ignore | ||
context.report({ | ||
node: comment, | ||
messageId: 'tsIgnoreInsteadOfExpectError', | ||
suggest: [ | ||
{ | ||
messageId: 'replaceTsIgnoreWithTsExpectError', | ||
fix(fixer) { | ||
const commentText = comment.value.replace(/@ts-ignore/, '@ts-expect-error'); | ||
return fixer.replaceText(comment, comment.type === utils_1.AST_TOKEN_TYPES.Line | ||
? `//${commentText}` | ||
: `/*${commentText}*/`); | ||
}, | ||
}, | ||
], | ||
}); | ||
} | ||
else { | ||
context.report({ | ||
data: { directive }, | ||
node: comment, | ||
messageId: 'tsDirectiveComment', | ||
}); | ||
} | ||
} | ||
@@ -140,4 +139,3 @@ if (option === 'allow-with-description' || | ||
const format = descriptionFormats.get(fullDirective); | ||
if (util.getStringLength(description.trim()) < | ||
minimumDescriptionLength) { | ||
if ((0, util_1.getStringLength)(description.trim()) < minimumDescriptionLength) { | ||
context.report({ | ||
@@ -144,0 +142,0 @@ data: { directive, minimumDescriptionLength }, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
// tslint regex | ||
@@ -34,3 +12,3 @@ // https://github.com/palantir/tslint/blob/95d9d958833fd9dc0002d18cbe34db20d0fbf437/src/enableDisableRules.ts#L32 | ||
: ['/*', text.trim(), '*/'].join(' '); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'ban-tslint-comment', | ||
@@ -41,3 +19,3 @@ meta: { | ||
description: 'Disallow `// tslint:<rule-flag>` comments', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -52,3 +30,3 @@ messages: { | ||
create: context => { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
@@ -55,0 +33,0 @@ Program() { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.TYPE_KEYWORDS = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
function removeSpaces(str) { | ||
@@ -36,3 +14,3 @@ return str.replace(/\s/g, ''); | ||
function getCustomMessage(bannedType) { | ||
if (bannedType == null) { | ||
if (bannedType == null || bannedType === true) { | ||
return ''; | ||
@@ -83,3 +61,5 @@ } | ||
'- If you want a type meaning "any value", you probably want `unknown` instead.', | ||
'- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.', | ||
].join('\n'), | ||
suggest: ['object', 'unknown', 'NonNullable<unknown>'], | ||
}, | ||
@@ -92,3 +72,10 @@ '{}': { | ||
'- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.', | ||
'- If you really want a type meaning "any non-nullish value", you probably want `NonNullable<unknown>` instead.', | ||
].join('\n'), | ||
suggest: [ | ||
'object', | ||
'unknown', | ||
'Record<string, never>', | ||
'NonNullable<unknown>', | ||
], | ||
}, | ||
@@ -109,3 +96,3 @@ }; | ||
}; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'ban-types', | ||
@@ -116,10 +103,57 @@ meta: { | ||
description: 'Disallow certain types', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
fixable: 'code', | ||
hasSuggestions: true, | ||
messages: { | ||
bannedTypeMessage: "Don't use `{{name}}` as a type.{{customMessage}}", | ||
bannedTypeReplacement: 'Replace `{{name}}` with `{{replacement}}`.', | ||
}, | ||
schema: [ | ||
{ | ||
$defs: { | ||
banConfig: { | ||
oneOf: [ | ||
{ | ||
type: 'null', | ||
description: 'Bans the type with the default message', | ||
}, | ||
{ | ||
type: 'boolean', | ||
enum: [false], | ||
description: 'Un-bans the type (useful when paired with `extendDefaults`)', | ||
}, | ||
{ | ||
type: 'boolean', | ||
enum: [true], | ||
description: 'Bans the type with the default message', | ||
}, | ||
{ | ||
type: 'string', | ||
description: 'Bans the type with a custom message', | ||
}, | ||
{ | ||
type: 'object', | ||
description: 'Bans a type', | ||
properties: { | ||
message: { | ||
type: 'string', | ||
description: 'Custom error message', | ||
}, | ||
fixWith: { | ||
type: 'string', | ||
description: 'Type to autofix replace with. Note that autofixers can be applied automatically - so you need to be careful with this option.', | ||
}, | ||
suggest: { | ||
type: 'array', | ||
items: { type: 'string' }, | ||
description: 'Types to suggest replacing with.', | ||
additionalItems: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
}, | ||
type: 'object', | ||
@@ -130,15 +164,3 @@ properties: { | ||
additionalProperties: { | ||
oneOf: [ | ||
{ type: 'null' }, | ||
{ type: 'boolean' }, | ||
{ type: 'string' }, | ||
{ | ||
type: 'object', | ||
properties: { | ||
message: { type: 'string' }, | ||
fixWith: { type: 'string' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
$ref: '#/items/0/$defs/banConfig', | ||
}, | ||
@@ -156,8 +178,7 @@ }, | ||
create(context, [options]) { | ||
var _a, _b; | ||
const extendDefaults = (_a = options.extendDefaults) !== null && _a !== void 0 ? _a : true; | ||
const customTypes = (_b = options.types) !== null && _b !== void 0 ? _b : {}; | ||
const extendDefaults = options.extendDefaults ?? true; | ||
const customTypes = options.types ?? {}; | ||
const types = Object.assign({}, extendDefaults ? defaultTypes : {}, customTypes); | ||
const bannedTypes = new Map(Object.entries(types).map(([type, data]) => [removeSpaces(type), data])); | ||
function checkBannedTypes(typeNode, name = stringifyNode(typeNode, context.getSourceCode())) { | ||
function checkBannedTypes(typeNode, name = stringifyNode(typeNode, (0, eslint_utils_1.getSourceCode)(context))) { | ||
const bannedType = bannedTypes.get(name); | ||
@@ -169,2 +190,5 @@ if (bannedType === undefined || bannedType === false) { | ||
const fixWith = bannedType && typeof bannedType === 'object' && bannedType.fixWith; | ||
const suggest = bannedType && typeof bannedType === 'object' | ||
? bannedType.suggest | ||
: undefined; | ||
context.report({ | ||
@@ -180,5 +204,13 @@ node: typeNode, | ||
: null, | ||
suggest: suggest?.map(replacement => ({ | ||
messageId: 'bannedTypeReplacement', | ||
data: { | ||
name, | ||
replacement, | ||
}, | ||
fix: (fixer) => fixer.replaceText(typeNode, replacement), | ||
})), | ||
}); | ||
} | ||
const keywordSelectors = util.objectReduceKey(exports.TYPE_KEYWORDS, (acc, keyword) => { | ||
const keywordSelectors = (0, util_1.objectReduceKey)(exports.TYPE_KEYWORDS, (acc, keyword) => { | ||
if (bannedTypes.has(keyword)) { | ||
@@ -189,3 +221,5 @@ acc[exports.TYPE_KEYWORDS[keyword]] = (node) => checkBannedTypes(node, keyword); | ||
}, {}); | ||
return Object.assign(Object.assign({}, keywordSelectors), { TSTypeLiteral(node) { | ||
return { | ||
...keywordSelectors, | ||
TSTypeLiteral(node) { | ||
if (node.members.length) { | ||
@@ -203,8 +237,15 @@ return; | ||
checkBannedTypes(node.typeName); | ||
if (node.typeParameters) { | ||
if (node.typeArguments) { | ||
checkBannedTypes(node); | ||
} | ||
} }); | ||
}, | ||
TSInterfaceHeritage(node) { | ||
checkBannedTypes(node); | ||
}, | ||
TSClassImplements(node) { | ||
checkBannedTypes(node); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=ban-types.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('block-spacing'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'block-spacing', | ||
@@ -36,3 +14,2 @@ meta: { | ||
description: 'Disallow or enforce spaces inside of blocks after opening block and before closing block', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -47,3 +24,3 @@ }, | ||
create(context, [whenToApplyOption]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const baseRules = baseRule.create(context); | ||
@@ -75,3 +52,3 @@ const always = whenToApplyOption !== 'never'; | ||
function isValid(left, right) { | ||
return (!util.isTokenOnSameLine(left, right) || | ||
return (!(0, util_1.isTokenOnSameLine)(left, right) || | ||
sourceCode.isSpaceBetween(left, right) === always); | ||
@@ -93,4 +70,3 @@ } | ||
// Skip if the node is invalid or empty. | ||
if (openBrace.type !== utils_1.AST_TOKEN_TYPES.Punctuator || | ||
openBrace.value !== '{' || | ||
if (openBrace.value !== '{' || | ||
closeBrace.type !== utils_1.AST_TOKEN_TYPES.Punctuator || | ||
@@ -154,3 +130,4 @@ closeBrace.value !== '}' || | ||
} | ||
return Object.assign(Object.assign({}, baseRules), { | ||
return { | ||
...baseRules, | ||
// This code worked "out of the box" for interface and type literal | ||
@@ -160,5 +137,8 @@ // Enums were very close to match as well, the only reason they are not is that was that enums don't have a body node in the parser | ||
// the base rule did not filter for the first opening brace punctuator | ||
TSInterfaceBody: baseRules.BlockStatement, TSTypeLiteral: baseRules.BlockStatement, TSEnumDeclaration: checkSpacingInsideBraces }); | ||
TSInterfaceBody: baseRules.BlockStatement, | ||
TSTypeLiteral: baseRules.BlockStatement, | ||
TSEnumDeclaration: checkSpacingInsideBraces, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=block-spacing.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -12,3 +13,2 @@ const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
description: 'Enforce consistent brace style for blocks', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -27,3 +27,3 @@ }, | ||
const isAllmanStyle = style === 'allman'; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const rules = baseRule.create(context); | ||
@@ -84,3 +84,5 @@ /** | ||
} | ||
return Object.assign(Object.assign({}, rules), { 'TSInterfaceBody, TSModuleBlock'(node) { | ||
return { | ||
...rules, | ||
'TSInterfaceBody, TSModuleBlock'(node) { | ||
const openingCurly = sourceCode.getFirstToken(node); | ||
@@ -94,5 +96,6 @@ const closingCurly = sourceCode.getLastToken(node); | ||
validateCurlyPair(openingCurly, closingCurly); | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=brace-style.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const printNodeModifiers = (node, final) => { | ||
var _a; | ||
return `${(_a = node.accessibility) !== null && _a !== void 0 ? _a : ''}${node.static ? ' static' : ''} ${final} `.trimStart(); | ||
}; | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const printNodeModifiers = (node, final) => `${node.accessibility ?? ''}${node.static ? ' static' : ''} ${final} `.trimStart(); | ||
const isSupportedLiteral = (node) => { | ||
@@ -42,3 +17,3 @@ if (node.type === utils_1.AST_NODE_TYPES.Literal) { | ||
}; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'class-literal-property-style', | ||
@@ -49,68 +24,88 @@ meta: { | ||
description: 'Enforce that literals on classes are exposed in a consistent style', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
fixable: 'code', | ||
hasSuggestions: true, | ||
messages: { | ||
preferFieldStyle: 'Literals should be exposed using readonly fields.', | ||
preferFieldStyleSuggestion: 'Replace the literals with readonly fields.', | ||
preferGetterStyle: 'Literals should be exposed using getters.', | ||
preferGetterStyleSuggestion: 'Replace the literals with getters.', | ||
}, | ||
schema: [{ enum: ['fields', 'getters'] }], | ||
schema: [ | ||
{ | ||
type: 'string', | ||
enum: ['fields', 'getters'], | ||
}, | ||
], | ||
}, | ||
defaultOptions: ['fields'], | ||
create(context, [style]) { | ||
return Object.assign(Object.assign({}, (style === 'fields' && { | ||
MethodDefinition(node) { | ||
if (node.kind !== 'get' || | ||
!node.value.body || | ||
!node.value.body.body.length) { | ||
return; | ||
} | ||
const [statement] = node.value.body.body; | ||
if (statement.type !== utils_1.AST_NODE_TYPES.ReturnStatement) { | ||
return; | ||
} | ||
const { argument } = statement; | ||
if (!argument || !isSupportedLiteral(argument)) { | ||
return; | ||
} | ||
context.report({ | ||
node: node.key, | ||
messageId: 'preferFieldStyle', | ||
fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
const name = sourceCode.getText(node.key); | ||
let text = ''; | ||
text += printNodeModifiers(node, 'readonly'); | ||
text += node.computed ? `[${name}]` : name; | ||
text += ` = ${sourceCode.getText(argument)};`; | ||
return fixer.replaceText(node, text); | ||
}, | ||
}); | ||
}, | ||
})), (style === 'getters' && { | ||
PropertyDefinition(node) { | ||
if (!node.readonly || node.declare) { | ||
return; | ||
} | ||
const { value } = node; | ||
if (!value || !isSupportedLiteral(value)) { | ||
return; | ||
} | ||
context.report({ | ||
node: node.key, | ||
messageId: 'preferGetterStyle', | ||
fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
const name = sourceCode.getText(node.key); | ||
let text = ''; | ||
text += printNodeModifiers(node, 'get'); | ||
text += node.computed ? `[${name}]` : name; | ||
text += `() { return ${sourceCode.getText(value)}; }`; | ||
return fixer.replaceText(node, text); | ||
}, | ||
}); | ||
}, | ||
})); | ||
return { | ||
...(style === 'fields' && { | ||
MethodDefinition(node) { | ||
if (node.kind !== 'get' || | ||
!node.value.body || | ||
node.value.body.body.length === 0) { | ||
return; | ||
} | ||
const [statement] = node.value.body.body; | ||
if (statement.type !== utils_1.AST_NODE_TYPES.ReturnStatement) { | ||
return; | ||
} | ||
const { argument } = statement; | ||
if (!argument || !isSupportedLiteral(argument)) { | ||
return; | ||
} | ||
context.report({ | ||
node: node.key, | ||
messageId: 'preferFieldStyle', | ||
suggest: [ | ||
{ | ||
messageId: 'preferFieldStyleSuggestion', | ||
fix(fixer) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const name = sourceCode.getText(node.key); | ||
let text = ''; | ||
text += printNodeModifiers(node, 'readonly'); | ||
text += node.computed ? `[${name}]` : name; | ||
text += ` = ${sourceCode.getText(argument)};`; | ||
return fixer.replaceText(node, text); | ||
}, | ||
}, | ||
], | ||
}); | ||
}, | ||
}), | ||
...(style === 'getters' && { | ||
PropertyDefinition(node) { | ||
if (!node.readonly || node.declare) { | ||
return; | ||
} | ||
const { value } = node; | ||
if (!value || !isSupportedLiteral(value)) { | ||
return; | ||
} | ||
context.report({ | ||
node: node.key, | ||
messageId: 'preferGetterStyle', | ||
suggest: [ | ||
{ | ||
messageId: 'preferGetterStyleSuggestion', | ||
fix(fixer) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const name = sourceCode.getText(node.key); | ||
let text = ''; | ||
text += printNodeModifiers(node, 'get'); | ||
text += node.computed ? `[${name}]` : name; | ||
text += `() { return ${sourceCode.getText(value)}; }`; | ||
return fixer.replaceText(node, text); | ||
}, | ||
}, | ||
], | ||
}); | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=class-literal-property-style.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -38,3 +16,2 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('comma-dangle'); | ||
function normalizeOptions(options) { | ||
var _a, _b, _c; | ||
if (typeof options === 'string') { | ||
@@ -48,8 +25,8 @@ return { | ||
return { | ||
enums: (_a = options.enums) !== null && _a !== void 0 ? _a : DEFAULT_OPTION_VALUE, | ||
generics: (_b = options.generics) !== null && _b !== void 0 ? _b : DEFAULT_OPTION_VALUE, | ||
tuples: (_c = options.tuples) !== null && _c !== void 0 ? _c : DEFAULT_OPTION_VALUE, | ||
enums: options.enums ?? DEFAULT_OPTION_VALUE, | ||
generics: options.generics ?? DEFAULT_OPTION_VALUE, | ||
tuples: options.tuples ?? DEFAULT_OPTION_VALUE, | ||
}; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'comma-dangle', | ||
@@ -60,3 +37,2 @@ meta: { | ||
description: 'Require or disallow trailing commas', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -67,5 +43,7 @@ }, | ||
value: { | ||
type: 'string', | ||
enum: OPTION_VALUE_SCHEME, | ||
}, | ||
valueWithIgnore: { | ||
type: 'string', | ||
enum: [...OPTION_VALUE_SCHEME, 'ignore'], | ||
@@ -98,3 +76,3 @@ }, | ||
], | ||
additionalProperties: false, | ||
additionalItems: false, | ||
}, | ||
@@ -108,3 +86,3 @@ fixable: 'code', | ||
const rules = baseRule.create(context); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const normalizedOptions = normalizeOptions(options); | ||
@@ -116,7 +94,8 @@ const predicate = { | ||
never: forbidComma, | ||
// https://github.com/typescript-eslint/typescript-eslint/issues/7220 | ||
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type, @typescript-eslint/no-empty-function | ||
ignore: () => { }, | ||
}; | ||
function last(nodes) { | ||
var _a; | ||
return (_a = nodes[nodes.length - 1]) !== null && _a !== void 0 ? _a : null; | ||
return nodes[nodes.length - 1] ?? null; | ||
} | ||
@@ -143,3 +122,3 @@ function getLastItem(node) { | ||
const lastToken = sourceCode.getLastToken(node); | ||
return (last === null || last === void 0 ? void 0 : last.loc.end.line) !== (lastToken === null || lastToken === void 0 ? void 0 : lastToken.loc.end.line); | ||
return last?.loc.end.line !== lastToken?.loc.end.line; | ||
} | ||
@@ -149,3 +128,3 @@ function forbidComma(node) { | ||
const trailing = getTrailingToken(node); | ||
if (last && trailing && util.isCommaToken(trailing)) { | ||
if (last && trailing && (0, util_1.isCommaToken)(trailing)) { | ||
context.report({ | ||
@@ -163,3 +142,3 @@ node, | ||
const trailing = getTrailingToken(node); | ||
if (last && trailing && !util.isCommaToken(trailing)) { | ||
if (last && trailing && !(0, util_1.isCommaToken)(trailing)) { | ||
context.report({ | ||
@@ -187,5 +166,10 @@ node, | ||
} | ||
return Object.assign(Object.assign({}, rules), { TSEnumDeclaration: predicate[normalizedOptions.enums], TSTypeParameterDeclaration: predicate[normalizedOptions.generics], TSTupleType: predicate[normalizedOptions.tuples] }); | ||
return { | ||
...rules, | ||
TSEnumDeclaration: predicate[normalizedOptions.enums], | ||
TSTypeParameterDeclaration: predicate[normalizedOptions.generics], | ||
TSTupleType: predicate[normalizedOptions.tuples], | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=comma-dangle.js.map |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -11,3 +12,2 @@ exports.default = (0, util_1.createRule)({ | ||
description: 'Enforce consistent spacing before and after commas', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -44,3 +44,3 @@ }, | ||
create(context, [{ before: spaceBefore, after: spaceAfter }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const tokensAndComments = sourceCode.tokensAndComments; | ||
@@ -107,2 +107,7 @@ const ignoredTokens = new Set(); | ||
} | ||
if (spaceAfter && | ||
nextToken && | ||
((0, util_1.isClosingBraceToken)(nextToken) || (0, util_1.isClosingBracketToken)(nextToken))) { | ||
return; | ||
} | ||
if (!spaceAfter && nextToken && nextToken.type === utils_1.AST_TOKEN_TYPES.Line) { | ||
@@ -137,3 +142,3 @@ return; | ||
const prevToken = tokensAndComments[i - 1]; | ||
const nextToken = tokensAndComments[i + 1]; | ||
const nextToken = tokensAndComments.at(i + 1); | ||
validateCommaSpacing(token, (0, util_1.isCommaToken)(prevToken) || ignoredTokens.has(token) | ||
@@ -143,3 +148,3 @@ ? null | ||
? null | ||
: nextToken); | ||
: nextToken ?? null); | ||
}); | ||
@@ -146,0 +151,0 @@ }, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -11,3 +12,3 @@ exports.default = (0, util_1.createRule)({ | ||
description: 'Enforce specifying generic type arguments on type annotation or constructor name of a constructor call', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -21,2 +22,3 @@ messages: { | ||
{ | ||
type: 'string', | ||
enum: ['type-annotation', 'constructor'], | ||
@@ -28,6 +30,5 @@ }, | ||
create(context, [mode]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
'VariableDeclarator,PropertyDefinition,:matches(FunctionDeclaration,FunctionExpression) > AssignmentPattern'(node) { | ||
var _a, _b; | ||
function getLHSRHS() { | ||
@@ -46,3 +47,3 @@ switch (node.type) { | ||
const [lhsName, rhs] = getLHSRHS(); | ||
const lhs = (_a = lhsName.typeAnnotation) === null || _a === void 0 ? void 0 : _a.typeAnnotation; | ||
const lhs = lhsName.typeAnnotation?.typeAnnotation; | ||
if (!rhs || | ||
@@ -60,5 +61,5 @@ rhs.type !== utils_1.AST_NODE_TYPES.NewExpression || | ||
if (mode === 'type-annotation') { | ||
if (!lhs && rhs.typeParameters) { | ||
const { typeParameters, callee } = rhs; | ||
const typeAnnotation = sourceCode.getText(callee) + sourceCode.getText(typeParameters); | ||
if (!lhs && rhs.typeArguments) { | ||
const { typeArguments, callee } = rhs; | ||
const typeAnnotation = sourceCode.getText(callee) + sourceCode.getText(typeArguments); | ||
context.report({ | ||
@@ -80,3 +81,3 @@ node, | ||
return [ | ||
fixer.remove(typeParameters), | ||
fixer.remove(typeArguments), | ||
fixer.insertTextAfter(getIDToAttachAnnotation(), ': ' + typeAnnotation), | ||
@@ -89,24 +90,22 @@ ]; | ||
} | ||
if (mode === 'constructor') { | ||
if ((lhs === null || lhs === void 0 ? void 0 : lhs.typeParameters) && !rhs.typeParameters) { | ||
const hasParens = ((_b = sourceCode.getTokenAfter(rhs.callee)) === null || _b === void 0 ? void 0 : _b.value) === '('; | ||
const extraComments = new Set(sourceCode.getCommentsInside(lhs.parent)); | ||
sourceCode | ||
.getCommentsInside(lhs.typeParameters) | ||
.forEach(c => extraComments.delete(c)); | ||
context.report({ | ||
node, | ||
messageId: 'preferConstructor', | ||
*fix(fixer) { | ||
yield fixer.remove(lhs.parent); | ||
for (const comment of extraComments) { | ||
yield fixer.insertTextAfter(rhs.callee, sourceCode.getText(comment)); | ||
} | ||
yield fixer.insertTextAfter(rhs.callee, sourceCode.getText(lhs.typeParameters)); | ||
if (!hasParens) { | ||
yield fixer.insertTextAfter(rhs.callee, '()'); | ||
} | ||
}, | ||
}); | ||
} | ||
if (lhs?.typeArguments && !rhs.typeArguments) { | ||
const hasParens = sourceCode.getTokenAfter(rhs.callee)?.value === '('; | ||
const extraComments = new Set(sourceCode.getCommentsInside(lhs.parent)); | ||
sourceCode | ||
.getCommentsInside(lhs.typeArguments) | ||
.forEach(c => extraComments.delete(c)); | ||
context.report({ | ||
node, | ||
messageId: 'preferConstructor', | ||
*fix(fixer) { | ||
yield fixer.remove(lhs.parent); | ||
for (const comment of extraComments) { | ||
yield fixer.insertTextAfter(rhs.callee, sourceCode.getText(comment)); | ||
} | ||
yield fixer.insertTextAfter(rhs.callee, sourceCode.getText(lhs.typeArguments)); | ||
if (!hasParens) { | ||
yield fixer.insertTextAfter(rhs.callee, '()'); | ||
} | ||
}, | ||
}); | ||
} | ||
@@ -113,0 +112,0 @@ }, |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -11,3 +12,3 @@ exports.default = (0, util_1.createRule)({ | ||
description: 'Require or disallow the `Record` type', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -21,2 +22,3 @@ messages: { | ||
{ | ||
type: 'string', | ||
enum: ['record', 'index-signature'], | ||
@@ -28,3 +30,3 @@ }, | ||
create(context, [mode]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function checkMembers(members, node, parentId, prefix, postfix, safeFix = true) { | ||
@@ -38,9 +40,6 @@ if (members.length !== 1) { | ||
} | ||
const [parameter] = member.parameters; | ||
if (!parameter) { | ||
const parameter = member.parameters.at(0); | ||
if (parameter?.type !== utils_1.AST_NODE_TYPES.Identifier) { | ||
return; | ||
} | ||
if (parameter.type !== utils_1.AST_NODE_TYPES.Identifier) { | ||
return; | ||
} | ||
const keyType = parameter.typeAnnotation; | ||
@@ -55,3 +54,3 @@ if (!keyType) { | ||
if (parentId) { | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
const superVar = utils_1.ASTUtils.findVariable(scope, parentId.name); | ||
@@ -82,40 +81,43 @@ if (superVar) { | ||
} | ||
return Object.assign(Object.assign({}, (mode === 'index-signature' && { | ||
TSTypeReference(node) { | ||
var _a; | ||
const typeName = node.typeName; | ||
if (typeName.type !== utils_1.AST_NODE_TYPES.Identifier) { | ||
return; | ||
} | ||
if (typeName.name !== 'Record') { | ||
return; | ||
} | ||
const params = (_a = node.typeParameters) === null || _a === void 0 ? void 0 : _a.params; | ||
if ((params === null || params === void 0 ? void 0 : params.length) !== 2) { | ||
return; | ||
} | ||
context.report({ | ||
node, | ||
messageId: 'preferIndexSignature', | ||
fix(fixer) { | ||
const key = sourceCode.getText(params[0]); | ||
const type = sourceCode.getText(params[1]); | ||
return fixer.replaceText(node, `{ [key: ${key}]: ${type} }`); | ||
}, | ||
}); | ||
}, | ||
})), (mode === 'record' && { | ||
TSTypeLiteral(node) { | ||
const parent = findParentDeclaration(node); | ||
checkMembers(node.members, node, parent === null || parent === void 0 ? void 0 : parent.id, '', ''); | ||
}, | ||
TSInterfaceDeclaration(node) { | ||
var _a, _b, _c, _d; | ||
let genericTypes = ''; | ||
if (((_b = (_a = node.typeParameters) === null || _a === void 0 ? void 0 : _a.params) !== null && _b !== void 0 ? _b : []).length > 0) { | ||
genericTypes = `<${(_c = node.typeParameters) === null || _c === void 0 ? void 0 : _c.params.map(p => sourceCode.getText(p)).join(', ')}>`; | ||
} | ||
checkMembers(node.body.body, node, node.id, `type ${node.id.name}${genericTypes} = `, ';', !((_d = node.extends) === null || _d === void 0 ? void 0 : _d.length)); | ||
}, | ||
})); | ||
return { | ||
...(mode === 'index-signature' && { | ||
TSTypeReference(node) { | ||
const typeName = node.typeName; | ||
if (typeName.type !== utils_1.AST_NODE_TYPES.Identifier) { | ||
return; | ||
} | ||
if (typeName.name !== 'Record') { | ||
return; | ||
} | ||
const params = node.typeArguments?.params; | ||
if (params?.length !== 2) { | ||
return; | ||
} | ||
context.report({ | ||
node, | ||
messageId: 'preferIndexSignature', | ||
fix(fixer) { | ||
const key = sourceCode.getText(params[0]); | ||
const type = sourceCode.getText(params[1]); | ||
return fixer.replaceText(node, `{ [key: ${key}]: ${type} }`); | ||
}, | ||
}); | ||
}, | ||
}), | ||
...(mode === 'record' && { | ||
TSTypeLiteral(node) { | ||
const parent = findParentDeclaration(node); | ||
checkMembers(node.members, node, parent?.id, '', ''); | ||
}, | ||
TSInterfaceDeclaration(node) { | ||
let genericTypes = ''; | ||
if (node.typeParameters?.params.length) { | ||
genericTypes = `<${node.typeParameters.params | ||
.map(p => sourceCode.getText(p)) | ||
.join(', ')}>`; | ||
} | ||
checkMembers(node.body.body, node, node.id, `type ${node.id.name}${genericTypes} = `, ';', !node.extends.length); | ||
}, | ||
}), | ||
}; | ||
}, | ||
@@ -122,0 +124,0 @@ }); |
@@ -27,4 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const ts = __importStar(require("typescript")); | ||
const util_1 = require("../util"); | ||
const getWrappedCode_1 = require("../util/getWrappedCode"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'consistent-type-assertions', | ||
@@ -37,3 +40,3 @@ meta: { | ||
description: 'Enforce consistent usage of type assertions', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -55,2 +58,3 @@ messages: { | ||
assertionStyle: { | ||
type: 'string', | ||
enum: ['never'], | ||
@@ -66,5 +70,7 @@ }, | ||
assertionStyle: { | ||
type: 'string', | ||
enum: ['as', 'angle-bracket'], | ||
}, | ||
objectLiteralTypeAssertions: { | ||
type: 'string', | ||
enum: ['allow', 'allow-as-parameter', 'never'], | ||
@@ -87,3 +93,4 @@ }, | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const parserServices = (0, util_1.getParserServices)(context, true); | ||
function isConst(node) { | ||
@@ -100,5 +107,5 @@ if (node.type !== utils_1.AST_NODE_TYPES.TSTypeReference) { | ||
let afterCount = 0; | ||
if (util.isParenthesized(node, sourceCode)) { | ||
const bodyOpeningParen = sourceCode.getTokenBefore(node, util.isOpeningParenToken); | ||
const bodyClosingParen = sourceCode.getTokenAfter(node, util.isClosingParenToken); | ||
if ((0, util_1.isParenthesized)(node, sourceCode)) { | ||
const bodyOpeningParen = sourceCode.getTokenBefore(node, util_1.isOpeningParenToken); | ||
const bodyClosingParen = sourceCode.getTokenAfter(node, util_1.isClosingParenToken); | ||
beforeCount = node.range[0] - bodyOpeningParen.range[0]; | ||
@@ -122,6 +129,22 @@ afterCount = bodyClosingParen.range[1] - node.range[1]; | ||
fix: messageId === 'as' | ||
? (fixer) => [ | ||
fixer.replaceText(node, getTextWithParentheses(node.expression)), | ||
fixer.insertTextAfter(node, ` as ${getTextWithParentheses(node.typeAnnotation)}`), | ||
] | ||
? (fixer) => { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
/** | ||
* AsExpression has lower precedence than TypeAssertionExpression, | ||
* so we don't need to wrap expression and typeAnnotation in parens. | ||
*/ | ||
const expressionCode = sourceCode.getText(node.expression); | ||
const typeAnnotationCode = sourceCode.getText(node.typeAnnotation); | ||
const asPrecedence = (0, util_1.getOperatorPrecedence)(ts.SyntaxKind.AsExpression, ts.SyntaxKind.Unknown); | ||
const parentPrecedence = (0, util_1.getOperatorPrecedence)(tsNode.parent.kind, ts.isBinaryExpression(tsNode.parent) | ||
? tsNode.parent.operatorToken.kind | ||
: ts.SyntaxKind.Unknown, ts.isNewExpression(tsNode.parent) | ||
? tsNode.parent.arguments != null && | ||
tsNode.parent.arguments.length > 0 | ||
: undefined); | ||
const text = `${expressionCode} as ${typeAnnotationCode}`; | ||
return fixer.replaceText(node, (0, util_1.isParenthesized)(node, sourceCode) | ||
? text | ||
: (0, getWrappedCode_1.getWrappedCode)(text, asPrecedence, parentPrecedence)); | ||
} | ||
: undefined, | ||
@@ -146,3 +169,2 @@ }); | ||
function checkExpression(node) { | ||
var _a; | ||
if (options.assertionStyle === 'never' || | ||
@@ -154,3 +176,2 @@ options.objectLiteralTypeAssertions === 'allow' || | ||
if (options.objectLiteralTypeAssertions === 'allow-as-parameter' && | ||
node.parent && | ||
(node.parent.type === utils_1.AST_NODE_TYPES.NewExpression || | ||
@@ -163,6 +184,5 @@ node.parent.type === utils_1.AST_NODE_TYPES.CallExpression || | ||
} | ||
if (checkType(node.typeAnnotation) && | ||
node.expression.type === utils_1.AST_NODE_TYPES.ObjectExpression) { | ||
if (checkType(node.typeAnnotation)) { | ||
const suggest = []; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.VariableDeclarator && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.VariableDeclarator && | ||
!node.parent.id.typeAnnotation) { | ||
@@ -184,5 +204,3 @@ const { parent } = node; | ||
fixer.replaceText(node, getTextWithParentheses(node.expression)), | ||
fixer.insertTextAfter(node, ` satisfies ${context | ||
.getSourceCode() | ||
.getText(node.typeAnnotation)}`), | ||
fixer.insertTextAfter(node, ` satisfies ${(0, eslint_utils_1.getSourceCode)(context).getText(node.typeAnnotation)}`), | ||
], | ||
@@ -189,0 +207,0 @@ }); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'consistent-type-definitions', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Enforce type definitions to consistently use either `interface` or `type`', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -43,2 +21,3 @@ messages: { | ||
{ | ||
type: 'string', | ||
enum: ['interface', 'type'], | ||
@@ -51,3 +30,3 @@ }, | ||
create(context, [option]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
/** | ||
@@ -58,46 +37,43 @@ * Iterates from the highest parent to the currently traversed node | ||
function isCurrentlyTraversedNodeWithinModuleDeclaration() { | ||
return context | ||
.getAncestors() | ||
.some(node => node.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration && | ||
return (0, eslint_utils_1.getAncestors)(context).some(node => node.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration && | ||
node.declare && | ||
node.global); | ||
} | ||
return Object.assign(Object.assign({}, (option === 'interface' && { | ||
"TSTypeAliasDeclaration[typeAnnotation.type='TSTypeLiteral']"(node) { | ||
context.report({ | ||
node: node.id, | ||
messageId: 'interfaceOverType', | ||
fix(fixer) { | ||
var _a; | ||
const typeNode = (_a = node.typeParameters) !== null && _a !== void 0 ? _a : node.id; | ||
const fixes = []; | ||
const firstToken = sourceCode.getTokenBefore(node.id); | ||
if (firstToken) { | ||
fixes.push(fixer.replaceText(firstToken, 'interface')); | ||
fixes.push(fixer.replaceTextRange([typeNode.range[1], node.typeAnnotation.range[0]], ' ')); | ||
} | ||
const afterToken = sourceCode.getTokenAfter(node.typeAnnotation); | ||
if (afterToken && | ||
afterToken.type === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
afterToken.value === ';') { | ||
fixes.push(fixer.remove(afterToken)); | ||
} | ||
return fixes; | ||
}, | ||
}); | ||
}, | ||
})), (option === 'type' && { | ||
TSInterfaceDeclaration(node) { | ||
const fix = isCurrentlyTraversedNodeWithinModuleDeclaration() | ||
? null | ||
: (fixer) => { | ||
var _a, _b; | ||
const typeNode = (_a = node.typeParameters) !== null && _a !== void 0 ? _a : node.id; | ||
const fixes = []; | ||
const firstToken = sourceCode.getTokenBefore(node.id); | ||
if (firstToken) { | ||
fixes.push(fixer.replaceText(firstToken, 'type')); | ||
fixes.push(fixer.replaceTextRange([typeNode.range[1], node.body.range[0]], ' = ')); | ||
} | ||
if (node.extends) { | ||
return { | ||
...(option === 'interface' && { | ||
"TSTypeAliasDeclaration[typeAnnotation.type='TSTypeLiteral']"(node) { | ||
context.report({ | ||
node: node.id, | ||
messageId: 'interfaceOverType', | ||
fix(fixer) { | ||
const typeNode = node.typeParameters ?? node.id; | ||
const fixes = []; | ||
const firstToken = sourceCode.getTokenBefore(node.id); | ||
if (firstToken) { | ||
fixes.push(fixer.replaceText(firstToken, 'interface')); | ||
fixes.push(fixer.replaceTextRange([typeNode.range[1], node.typeAnnotation.range[0]], ' ')); | ||
} | ||
const afterToken = sourceCode.getTokenAfter(node.typeAnnotation); | ||
if (afterToken && | ||
afterToken.type === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
afterToken.value === ';') { | ||
fixes.push(fixer.remove(afterToken)); | ||
} | ||
return fixes; | ||
}, | ||
}); | ||
}, | ||
}), | ||
...(option === 'type' && { | ||
TSInterfaceDeclaration(node) { | ||
const fix = isCurrentlyTraversedNodeWithinModuleDeclaration() | ||
? null | ||
: (fixer) => { | ||
const typeNode = node.typeParameters ?? node.id; | ||
const fixes = []; | ||
const firstToken = sourceCode.getTokenBefore(node.id); | ||
if (firstToken) { | ||
fixes.push(fixer.replaceText(firstToken, 'type')); | ||
fixes.push(fixer.replaceTextRange([typeNode.range[1], node.body.range[0]], ' = ')); | ||
} | ||
node.extends.forEach(heritage => { | ||
@@ -107,21 +83,21 @@ const typeIdentifier = sourceCode.getText(heritage); | ||
}); | ||
} | ||
if (((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
fixes.push(fixer.removeRange([node.parent.range[0], node.range[0]]), fixer.insertTextAfter(node.body, `\nexport default ${node.id.name}`)); | ||
} | ||
return fixes; | ||
}; | ||
context.report({ | ||
node: node.id, | ||
messageId: 'typeOverInterface', | ||
/** | ||
* remove automatically fix when the interface is within a declare global | ||
* @see {@link https://github.com/typescript-eslint/typescript-eslint/issues/2707} | ||
*/ | ||
fix, | ||
}); | ||
}, | ||
})); | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
fixes.push(fixer.removeRange([node.parent.range[0], node.range[0]]), fixer.insertTextAfter(node.body, `\nexport default ${node.id.name}`)); | ||
} | ||
return fixes; | ||
}; | ||
context.report({ | ||
node: node.id, | ||
messageId: 'typeOverInterface', | ||
/** | ||
* remove automatically fix when the interface is within a declare global | ||
* @see {@link https://github.com/typescript-eslint/typescript-eslint/issues/2707} | ||
*/ | ||
fix, | ||
}); | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=consistent-type-definitions.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const typescript_1 = require("typescript"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'consistent-type-exports', | ||
@@ -35,3 +13,2 @@ meta: { | ||
description: 'Enforce consistent usage of type exports', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -63,11 +40,31 @@ }, | ||
create(context, [{ fixMixedExportsWithInlineTypeSpecifier }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const sourceExportsMap = {}; | ||
const parserServices = util.getParserServices(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
/** | ||
* Helper for identifying if an export specifier resolves to a | ||
* JavaScript value or a TypeScript type. | ||
* | ||
* @returns True/false if is a type or not, or undefined if the specifier | ||
* can't be resolved. | ||
*/ | ||
function isSpecifierTypeBased(specifier) { | ||
const checker = services.program.getTypeChecker(); | ||
const symbol = services.getSymbolAtLocation(specifier.exported); | ||
if (!symbol) { | ||
return undefined; | ||
} | ||
const aliasedSymbol = checker.getAliasedSymbol(symbol); | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison | ||
if (aliasedSymbol.escapedName === 'unknown') { | ||
return undefined; | ||
} | ||
return !(aliasedSymbol.flags & typescript_1.SymbolFlags.Value); | ||
} | ||
return { | ||
ExportNamedDeclaration(node) { | ||
var _a; | ||
// Coerce the source into a string for use as a lookup entry. | ||
const source = (_a = getSourceFromExport(node)) !== null && _a !== void 0 ? _a : 'undefined'; | ||
const sourceExports = (sourceExportsMap[source] || (sourceExportsMap[source] = { | ||
const source = getSourceFromExport(node) ?? 'undefined'; | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
const sourceExports = (sourceExportsMap[source] ||= { | ||
source, | ||
@@ -77,3 +74,3 @@ reportValueExports: [], | ||
valueOnlyNamedExport: null, | ||
})); | ||
}); | ||
// Cache the first encountered exports for the package. We will need to come | ||
@@ -103,3 +100,3 @@ // back to these later when fixing the problems. | ||
} | ||
const isTypeBased = isSpecifierTypeBased(parserServices, specifier); | ||
const isTypeBased = isSpecifierTypeBased(specifier); | ||
if (isTypeBased === true) { | ||
@@ -143,3 +140,3 @@ typeBasedSpecifiers.push(specifier); | ||
// We have both type and value violations. | ||
const allExportNames = report.typeBasedSpecifiers.map(specifier => `${specifier.local.name}`); | ||
const allExportNames = report.typeBasedSpecifiers.map(specifier => specifier.local.name); | ||
if (allExportNames.length === 1) { | ||
@@ -162,3 +159,3 @@ const exportNames = allExportNames[0]; | ||
else { | ||
const exportNames = util.formatWordList(allExportNames); | ||
const exportNames = (0, util_1.formatWordList)(allExportNames); | ||
context.report({ | ||
@@ -185,19 +182,2 @@ node: report.node, | ||
/** | ||
* Helper for identifying if an export specifier resolves to a | ||
* JavaScript value or a TypeScript type. | ||
* | ||
* @returns True/false if is a type or not, or undefined if the specifier | ||
* can't be resolved. | ||
*/ | ||
function isSpecifierTypeBased(parserServices, specifier) { | ||
const checker = parserServices.program.getTypeChecker(); | ||
const node = parserServices.esTreeNodeToTSNodeMap.get(specifier.exported); | ||
const symbol = checker.getSymbolAtLocation(node); | ||
const aliasedSymbol = checker.getAliasedSymbol(symbol); | ||
if (!aliasedSymbol || aliasedSymbol.escapedName === 'unknown') { | ||
return undefined; | ||
} | ||
return !(aliasedSymbol.flags & typescript_1.SymbolFlags.Value); | ||
} | ||
/** | ||
* Inserts "type" into an export. | ||
@@ -211,8 +191,8 @@ * | ||
function* fixExportInsertType(fixer, sourceCode, node) { | ||
const exportToken = util.nullThrows(sourceCode.getFirstToken(node), util.NullThrowsReasons.MissingToken('export', node.type)); | ||
const exportToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node), util_1.NullThrowsReasons.MissingToken('export', node.type)); | ||
yield fixer.insertTextAfter(exportToken, ' type'); | ||
for (const specifier of node.specifiers) { | ||
if (specifier.exportKind === 'type') { | ||
const kindToken = util.nullThrows(sourceCode.getFirstToken(specifier), util.NullThrowsReasons.MissingToken('export', specifier.type)); | ||
const firstTokenAfter = util.nullThrows(sourceCode.getTokenAfter(kindToken, { | ||
const kindToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(specifier), util_1.NullThrowsReasons.MissingToken('export', specifier.type)); | ||
const firstTokenAfter = (0, util_1.nullThrows)(sourceCode.getTokenAfter(kindToken, { | ||
includeComments: true, | ||
@@ -234,3 +214,3 @@ }), 'Missing token following the export kind.'); | ||
const specifierNames = typeSpecifiers.map(getSpecifierText).join(', '); | ||
const exportToken = util.nullThrows(sourceCode.getFirstToken(node), util.NullThrowsReasons.MissingToken('export', node.type)); | ||
const exportToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node), util_1.NullThrowsReasons.MissingToken('export', node.type)); | ||
// Filter the bad exports from the current line. | ||
@@ -240,4 +220,4 @@ const filteredSpecifierNames = valueSpecifiers | ||
.join(', '); | ||
const openToken = util.nullThrows(sourceCode.getFirstToken(node, util.isOpeningBraceToken), util.NullThrowsReasons.MissingToken('{', node.type)); | ||
const closeToken = util.nullThrows(sourceCode.getLastToken(node, util.isClosingBraceToken), util.NullThrowsReasons.MissingToken('}', node.type)); | ||
const openToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isOpeningBraceToken), util_1.NullThrowsReasons.MissingToken('{', node.type)); | ||
const closeToken = (0, util_1.nullThrows)(sourceCode.getLastToken(node, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', node.type)); | ||
// Remove exports from the current line which we're going to re-insert. | ||
@@ -260,4 +240,3 @@ yield fixer.replaceTextRange([openToken.range[1], closeToken.range[0]], ` ${filteredSpecifierNames} `); | ||
function getSourceFromExport(node) { | ||
var _a; | ||
if (((_a = node.source) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Literal && | ||
if (node.source?.type === utils_1.AST_NODE_TYPES.Literal && | ||
typeof node.source.value === 'string') { | ||
@@ -264,0 +243,0 @@ return node.source.value; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'consistent-type-imports', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Enforce consistent usage of type imports', | ||
recommended: false, | ||
}, | ||
@@ -51,2 +28,3 @@ messages: { | ||
prefer: { | ||
type: 'string', | ||
enum: ['type-imports', 'no-type-imports'], | ||
@@ -58,2 +36,3 @@ }, | ||
fixStyle: { | ||
type: 'string', | ||
enum: ['separate-type-imports', 'inline-type-imports'], | ||
@@ -75,166 +54,173 @@ }, | ||
create(context, [option]) { | ||
var _a, _b; | ||
const prefer = (_a = option.prefer) !== null && _a !== void 0 ? _a : 'type-imports'; | ||
const prefer = option.prefer ?? 'type-imports'; | ||
const disallowTypeAnnotations = option.disallowTypeAnnotations !== false; | ||
const fixStyle = (_b = option.fixStyle) !== null && _b !== void 0 ? _b : 'separate-type-imports'; | ||
const sourceCode = context.getSourceCode(); | ||
const fixStyle = option.fixStyle ?? 'separate-type-imports'; | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const sourceImportsMap = {}; | ||
return Object.assign(Object.assign({}, (prefer === 'type-imports' | ||
? { | ||
// prefer type imports | ||
ImportDeclaration(node) { | ||
var _a; | ||
const source = node.source.value; | ||
// sourceImports is the object containing all the specifics for a particular import source, type or value | ||
const sourceImports = (_a = sourceImportsMap[source]) !== null && _a !== void 0 ? _a : (sourceImportsMap[source] = { | ||
source, | ||
reportValueImports: [], | ||
typeOnlyNamedImport: null, | ||
valueOnlyNamedImport: null, | ||
valueImport: null, // if only value imports | ||
}); | ||
if (node.importKind === 'type') { | ||
if (!sourceImports.typeOnlyNamedImport && | ||
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) { | ||
// definitely import type { TypeX } | ||
sourceImports.typeOnlyNamedImport = node; | ||
return { | ||
...(prefer === 'type-imports' | ||
? { | ||
// prefer type imports | ||
ImportDeclaration(node) { | ||
const source = node.source.value; | ||
// sourceImports is the object containing all the specifics for a particular import source, type or value | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
sourceImportsMap[source] ??= { | ||
source, | ||
reportValueImports: [], // if there is a mismatch where type importKind but value specifiers | ||
typeOnlyNamedImport: null, // if only type imports | ||
valueOnlyNamedImport: null, // if only value imports with named specifiers | ||
valueImport: null, // if only value imports | ||
}; | ||
const sourceImports = sourceImportsMap[source]; | ||
if (node.importKind === 'type') { | ||
if (!sourceImports.typeOnlyNamedImport && | ||
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) { | ||
// definitely import type { TypeX } | ||
sourceImports.typeOnlyNamedImport = node; | ||
} | ||
} | ||
} | ||
else { | ||
if (!sourceImports.valueOnlyNamedImport && | ||
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) { | ||
sourceImports.valueOnlyNamedImport = node; | ||
sourceImports.valueImport = node; | ||
else { | ||
if (!sourceImports.valueOnlyNamedImport && | ||
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier)) { | ||
sourceImports.valueOnlyNamedImport = node; | ||
sourceImports.valueImport = node; | ||
} | ||
else if (!sourceImports.valueImport && | ||
node.specifiers.some(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier)) { | ||
sourceImports.valueImport = node; | ||
} | ||
} | ||
else if (!sourceImports.valueImport && | ||
node.specifiers.some(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier)) { | ||
sourceImports.valueImport = node; | ||
} | ||
} | ||
const typeSpecifiers = []; | ||
const inlineTypeSpecifiers = []; | ||
const valueSpecifiers = []; | ||
const unusedSpecifiers = []; | ||
for (const specifier of node.specifiers) { | ||
if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier && | ||
specifier.importKind === 'type') { | ||
inlineTypeSpecifiers.push(specifier); | ||
continue; | ||
} | ||
const [variable] = context.getDeclaredVariables(specifier); | ||
if (variable.references.length === 0) { | ||
unusedSpecifiers.push(specifier); | ||
} | ||
else { | ||
const onlyHasTypeReferences = variable.references.every(ref => { | ||
var _a, _b; | ||
/** | ||
* keep origin import kind when export | ||
* export { Type } | ||
* export default Type; | ||
*/ | ||
if (((_a = ref.identifier.parent) === null || _a === void 0 ? void 0 : _a.type) === | ||
utils_1.AST_NODE_TYPES.ExportSpecifier || | ||
((_b = ref.identifier.parent) === null || _b === void 0 ? void 0 : _b.type) === | ||
utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
if (ref.isValueReference && ref.isTypeReference) { | ||
return node.importKind === 'type'; | ||
const typeSpecifiers = []; | ||
const inlineTypeSpecifiers = []; | ||
const valueSpecifiers = []; | ||
const unusedSpecifiers = []; | ||
for (const specifier of node.specifiers) { | ||
if (specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier && | ||
specifier.importKind === 'type') { | ||
inlineTypeSpecifiers.push(specifier); | ||
continue; | ||
} | ||
const [variable] = (0, eslint_utils_1.getDeclaredVariables)(context, specifier); | ||
if (variable.references.length === 0) { | ||
unusedSpecifiers.push(specifier); | ||
} | ||
else { | ||
const onlyHasTypeReferences = variable.references.every(ref => { | ||
/** | ||
* keep origin import kind when export | ||
* export { Type } | ||
* export default Type; | ||
*/ | ||
if (ref.identifier.parent.type === | ||
utils_1.AST_NODE_TYPES.ExportSpecifier || | ||
ref.identifier.parent.type === | ||
utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
if (ref.isValueReference && ref.isTypeReference) { | ||
return node.importKind === 'type'; | ||
} | ||
} | ||
} | ||
if (ref.isValueReference) { | ||
let parent = ref.identifier.parent; | ||
let child = ref.identifier; | ||
while (parent) { | ||
switch (parent.type) { | ||
// CASE 1: | ||
// `type T = typeof foo` will create a value reference because "foo" must be a value type | ||
// however this value reference is safe to use with type-only imports | ||
case utils_1.AST_NODE_TYPES.TSTypeQuery: | ||
return true; | ||
case utils_1.AST_NODE_TYPES.TSQualifiedName: | ||
// TSTypeQuery must have a TSESTree.EntityName as its child, so we can filter here and break early | ||
if (parent.left !== child) { | ||
if (ref.isValueReference) { | ||
let parent = ref.identifier.parent; | ||
let child = ref.identifier; | ||
while (parent) { | ||
switch (parent.type) { | ||
// CASE 1: | ||
// `type T = typeof foo` will create a value reference because "foo" must be a value type | ||
// however this value reference is safe to use with type-only imports | ||
case utils_1.AST_NODE_TYPES.TSTypeQuery: | ||
return true; | ||
case utils_1.AST_NODE_TYPES.TSQualifiedName: | ||
// TSTypeQuery must have a TSESTree.EntityName as its child, so we can filter here and break early | ||
if (parent.left !== child) { | ||
return false; | ||
} | ||
child = parent; | ||
parent = parent.parent; | ||
continue; | ||
// END CASE 1 | ||
////////////// | ||
// CASE 2: | ||
// `type T = { [foo]: string }` will create a value reference because "foo" must be a value type | ||
// however this value reference is safe to use with type-only imports. | ||
// Also this is represented as a non-type AST - hence it uses MemberExpression | ||
case utils_1.AST_NODE_TYPES.TSPropertySignature: | ||
return parent.key === child; | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
if (parent.object !== child) { | ||
return false; | ||
} | ||
child = parent; | ||
parent = parent.parent; | ||
continue; | ||
// END CASE 2 | ||
default: | ||
return false; | ||
} | ||
child = parent; | ||
parent = parent.parent; | ||
continue; | ||
// END CASE 1 | ||
////////////// | ||
// CASE 2: | ||
// `type T = { [foo]: string }` will create a value reference because "foo" must be a value type | ||
// however this value reference is safe to use with type-only imports. | ||
// Also this is represented as a non-type AST - hence it uses MemberExpression | ||
case utils_1.AST_NODE_TYPES.TSPropertySignature: | ||
return parent.key === child; | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
if (parent.object !== child) { | ||
return false; | ||
} | ||
child = parent; | ||
parent = parent.parent; | ||
continue; | ||
// END CASE 2 | ||
default: | ||
return false; | ||
} | ||
} | ||
} | ||
return ref.isTypeReference; | ||
}); | ||
if (onlyHasTypeReferences) { | ||
typeSpecifiers.push(specifier); | ||
} | ||
return ref.isTypeReference; | ||
}); | ||
if (onlyHasTypeReferences) { | ||
typeSpecifiers.push(specifier); | ||
else { | ||
valueSpecifiers.push(specifier); | ||
} | ||
} | ||
else { | ||
valueSpecifiers.push(specifier); | ||
} | ||
} | ||
} | ||
if ((node.importKind === 'value' && typeSpecifiers.length) || | ||
(node.importKind === 'type' && valueSpecifiers.length)) { | ||
sourceImports.reportValueImports.push({ | ||
node, | ||
typeSpecifiers, | ||
valueSpecifiers, | ||
unusedSpecifiers, | ||
inlineTypeSpecifiers, | ||
}); | ||
} | ||
}, | ||
'Program:exit'() { | ||
for (const sourceImports of Object.values(sourceImportsMap)) { | ||
if (sourceImports.reportValueImports.length === 0) { | ||
// nothing to fix. value specifiers and type specifiers are correctly written | ||
continue; | ||
if ((node.importKind === 'value' && typeSpecifiers.length) || | ||
(node.importKind === 'type' && valueSpecifiers.length)) { | ||
sourceImports.reportValueImports.push({ | ||
node, | ||
typeSpecifiers, | ||
valueSpecifiers, | ||
unusedSpecifiers, | ||
inlineTypeSpecifiers, | ||
}); | ||
} | ||
for (const report of sourceImports.reportValueImports) { | ||
if (report.valueSpecifiers.length === 0 && | ||
report.unusedSpecifiers.length === 0 && | ||
report.node.importKind !== 'type') { | ||
context.report({ | ||
node: report.node, | ||
messageId: 'typeOverValue', | ||
*fix(fixer) { | ||
yield* fixToTypeImportDeclaration(fixer, report, sourceImports); | ||
}, | ||
}); | ||
}, | ||
'Program:exit'() { | ||
for (const sourceImports of Object.values(sourceImportsMap)) { | ||
if (sourceImports.reportValueImports.length === 0) { | ||
// nothing to fix. value specifiers and type specifiers are correctly written | ||
continue; | ||
} | ||
else { | ||
const isTypeImport = report.node.importKind === 'type'; | ||
// we have a mixed type/value import or just value imports, so we need to split them out into multiple imports if separate-type-imports is configured | ||
const importNames = (isTypeImport | ||
? report.valueSpecifiers // import type { A } from 'roo'; // WHERE A is used in value position | ||
: report.typeSpecifiers) // import { A, B } from 'roo'; // WHERE A is used in type position and B is in value position | ||
.map(specifier => `"${specifier.local.name}"`); | ||
const message = (() => { | ||
const typeImports = util.formatWordList(importNames); | ||
if (importNames.length === 1) { | ||
if (isTypeImport) { | ||
for (const report of sourceImports.reportValueImports) { | ||
if (report.valueSpecifiers.length === 0 && | ||
report.unusedSpecifiers.length === 0 && | ||
report.node.importKind !== 'type') { | ||
/** checks if import has type assertions | ||
* ``` | ||
* import * as type from 'mod' assert { type: 'json' }; | ||
* ``` | ||
* https://github.com/typescript-eslint/typescript-eslint/issues/7527 | ||
*/ | ||
if (report.node.attributes.length === 0) { | ||
context.report({ | ||
node: report.node, | ||
messageId: 'typeOverValue', | ||
*fix(fixer) { | ||
yield* fixToTypeImportDeclaration(fixer, report, sourceImports); | ||
}, | ||
}); | ||
} | ||
} | ||
else { | ||
const isTypeImport = report.node.importKind === 'type'; | ||
// we have a mixed type/value import or just value imports, so we need to split them out into multiple imports if separate-type-imports is configured | ||
const importNames = (isTypeImport | ||
? report.valueSpecifiers // import type { A } from 'roo'; // WHERE A is used in value position | ||
: report.typeSpecifiers) // import { A, B } from 'roo'; // WHERE A is used in type position and B is in value position | ||
.map(specifier => `"${specifier.local.name}"`); | ||
const message = (() => { | ||
const typeImports = (0, util_1.formatWordList)(importNames); | ||
if (importNames.length === 1) { | ||
if (isTypeImport) { | ||
return { | ||
messageId: 'aImportInDecoMeta', | ||
data: { typeImports }, | ||
}; | ||
} | ||
return { | ||
messageId: 'aImportInDecoMeta', | ||
data: { typeImports }, | ||
}; | ||
} | ||
else { | ||
return { | ||
messageId: 'aImportIsOnlyTypes', | ||
@@ -244,4 +230,2 @@ data: { typeImports }, | ||
} | ||
} | ||
else { | ||
if (isTypeImport) { | ||
@@ -253,62 +237,64 @@ return { | ||
} | ||
else { | ||
return { | ||
messageId: 'someImportsAreOnlyTypes', | ||
data: { typeImports }, // typeImports are all the type specifiers in the value position | ||
}; | ||
} | ||
} | ||
})(); | ||
context.report(Object.assign(Object.assign({ node: report.node }, message), { *fix(fixer) { | ||
if (isTypeImport) { | ||
// take all the valueSpecifiers and put them on a new line | ||
yield* fixToValueImportDeclaration(fixer, report, sourceImports); | ||
} | ||
else { | ||
// take all the typeSpecifiers and put them on a new line | ||
yield* fixToTypeImportDeclaration(fixer, report, sourceImports); | ||
} | ||
} })); | ||
return { | ||
messageId: 'someImportsAreOnlyTypes', | ||
data: { typeImports }, // typeImports are all the type specifiers in the value position | ||
}; | ||
})(); | ||
context.report({ | ||
node: report.node, | ||
...message, | ||
*fix(fixer) { | ||
if (isTypeImport) { | ||
// take all the valueSpecifiers and put them on a new line | ||
yield* fixToValueImportDeclaration(fixer, report, sourceImports); | ||
} | ||
else { | ||
// take all the typeSpecifiers and put them on a new line | ||
yield* fixToTypeImportDeclaration(fixer, report, sourceImports); | ||
} | ||
}, | ||
}); | ||
} | ||
} | ||
} | ||
} | ||
}, | ||
} | ||
: { | ||
// prefer no type imports | ||
'ImportDeclaration[importKind = "type"]'(node) { | ||
context.report({ | ||
node, | ||
messageId: 'valueOverType', | ||
fix(fixer) { | ||
return fixRemoveTypeSpecifierFromImportDeclaration(fixer, node); | ||
}, | ||
}); | ||
}, | ||
'ImportSpecifier[importKind = "type"]'(node) { | ||
context.report({ | ||
node, | ||
messageId: 'valueOverType', | ||
fix(fixer) { | ||
return fixRemoveTypeSpecifierFromImportSpecifier(fixer, node); | ||
}, | ||
}); | ||
}, | ||
})), (disallowTypeAnnotations | ||
? { | ||
// disallow `import()` type | ||
TSImportType(node) { | ||
context.report({ | ||
node, | ||
messageId: 'noImportTypeAnnotations', | ||
}); | ||
}, | ||
} | ||
: {})); | ||
}, | ||
} | ||
: { | ||
// prefer no type imports | ||
'ImportDeclaration[importKind = "type"]'(node) { | ||
context.report({ | ||
node, | ||
messageId: 'valueOverType', | ||
fix(fixer) { | ||
return fixRemoveTypeSpecifierFromImportDeclaration(fixer, node); | ||
}, | ||
}); | ||
}, | ||
'ImportSpecifier[importKind = "type"]'(node) { | ||
context.report({ | ||
node, | ||
messageId: 'valueOverType', | ||
fix(fixer) { | ||
return fixRemoveTypeSpecifierFromImportSpecifier(fixer, node); | ||
}, | ||
}); | ||
}, | ||
}), | ||
...(disallowTypeAnnotations | ||
? { | ||
// disallow `import()` type | ||
TSImportType(node) { | ||
context.report({ | ||
node, | ||
messageId: 'noImportTypeAnnotations', | ||
}); | ||
}, | ||
} | ||
: {}), | ||
}; | ||
function classifySpecifier(node) { | ||
var _a; | ||
const defaultSpecifier = node.specifiers[0].type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier | ||
? node.specifiers[0] | ||
: null; | ||
const namespaceSpecifier = (_a = node.specifiers.find((specifier) => specifier.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier)) !== null && _a !== void 0 ? _a : null; | ||
const namespaceSpecifier = node.specifiers.find((specifier) => specifier.type === utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier) ?? null; | ||
const namedSpecifiers = node.specifiers.filter((specifier) => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier); | ||
@@ -336,5 +322,5 @@ return { | ||
// import DefType, {Type1, Type2} from 'foo' | ||
const openingBraceToken = util.nullThrows(sourceCode.getTokenBefore(subsetNamedSpecifiers[0], util.isOpeningBraceToken), util.NullThrowsReasons.MissingToken('{', node.type)); | ||
const commaToken = util.nullThrows(sourceCode.getTokenBefore(openingBraceToken, util.isCommaToken), util.NullThrowsReasons.MissingToken(',', node.type)); | ||
const closingBraceToken = util.nullThrows(sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util.isClosingBraceToken), util.NullThrowsReasons.MissingToken('}', node.type)); | ||
const openingBraceToken = (0, util_1.nullThrows)(sourceCode.getTokenBefore(subsetNamedSpecifiers[0], util_1.isOpeningBraceToken), util_1.NullThrowsReasons.MissingToken('{', node.type)); | ||
const commaToken = (0, util_1.nullThrows)(sourceCode.getTokenBefore(openingBraceToken, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type)); | ||
const closingBraceToken = (0, util_1.nullThrows)(sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', node.type)); | ||
// import DefType, {...} from 'foo' | ||
@@ -381,3 +367,3 @@ // ^^^^^^^ remove | ||
textRange[0] = before.range[1]; | ||
if (util.isCommaToken(before)) { | ||
if ((0, util_1.isCommaToken)(before)) { | ||
removeRange[0] = before.range[0]; | ||
@@ -393,3 +379,3 @@ } | ||
if (isFirst || isLast) { | ||
if (util.isCommaToken(after)) { | ||
if ((0, util_1.isCommaToken)(after)) { | ||
removeRange[1] = after.range[1]; | ||
@@ -410,5 +396,5 @@ } | ||
function fixInsertNamedSpecifiersInNamedSpecifierList(fixer, target, insertText) { | ||
const closingBraceToken = util.nullThrows(sourceCode.getFirstTokenBetween(sourceCode.getFirstToken(target), target.source, util.isClosingBraceToken), util.NullThrowsReasons.MissingToken('}', target.type)); | ||
const closingBraceToken = (0, util_1.nullThrows)(sourceCode.getFirstTokenBetween(sourceCode.getFirstToken(target), target.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', target.type)); | ||
const before = sourceCode.getTokenBefore(closingBraceToken); | ||
if (!util.isCommaToken(before) && !util.isOpeningBraceToken(before)) { | ||
if (!(0, util_1.isCommaToken)(before) && !(0, util_1.isOpeningBraceToken)(before)) { | ||
insertText = `,${insertText}`; | ||
@@ -451,3 +437,6 @@ } | ||
// import * as types from 'foo' | ||
yield* fixInsertTypeSpecifierForImportDeclaration(fixer, node, false); | ||
// checks for presence of import assertions | ||
if (node.attributes.length === 0) { | ||
yield* fixInsertTypeSpecifierForImportDeclaration(fixer, node, false); | ||
} | ||
return; | ||
@@ -520,3 +509,3 @@ } | ||
// import DefType, * as Type from 'foo' | ||
const commaToken = util.nullThrows(sourceCode.getTokenBefore(namespaceSpecifier, util.isCommaToken), util.NullThrowsReasons.MissingToken(',', node.type)); | ||
const commaToken = (0, util_1.nullThrows)(sourceCode.getTokenBefore(namespaceSpecifier, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type)); | ||
// import Def, * as Ns from 'foo' | ||
@@ -532,3 +521,3 @@ // ^^^^^^^^^ remove | ||
if (report.typeSpecifiers.length === node.specifiers.length) { | ||
const importToken = util.nullThrows(sourceCode.getFirstToken(node, util.isImportKeyword), util.NullThrowsReasons.MissingToken('import', node.type)); | ||
const importToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type)); | ||
// import type Type from 'foo' | ||
@@ -539,3 +528,3 @@ // ^^^^ insert | ||
else { | ||
const commaToken = util.nullThrows(sourceCode.getTokenAfter(defaultSpecifier, util.isCommaToken), util.NullThrowsReasons.MissingToken(',', defaultSpecifier.type)); | ||
const commaToken = (0, util_1.nullThrows)(sourceCode.getTokenAfter(defaultSpecifier, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', defaultSpecifier.type)); | ||
// import Type , {...} from 'foo' | ||
@@ -547,3 +536,3 @@ // ^^^^^ pick | ||
yield fixer.insertTextBefore(node, `import type ${defaultText} from ${sourceCode.getText(node.source)};\n`); | ||
const afterToken = util.nullThrows(sourceCode.getTokenAfter(commaToken, { includeComments: true }), util.NullThrowsReasons.MissingToken('any token', node.type)); | ||
const afterToken = (0, util_1.nullThrows)(sourceCode.getTokenAfter(commaToken, { includeComments: true }), util_1.NullThrowsReasons.MissingToken('any token', node.type)); | ||
// import Type , {...} from 'foo' | ||
@@ -564,11 +553,11 @@ // ^^^^^^^ remove | ||
// ^^^^^ insert | ||
const importToken = util.nullThrows(sourceCode.getFirstToken(node, util.isImportKeyword), util.NullThrowsReasons.MissingToken('import', node.type)); | ||
const importToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type)); | ||
yield fixer.insertTextAfter(importToken, ' type'); | ||
if (isDefaultImport) { | ||
// Has default import | ||
const openingBraceToken = sourceCode.getFirstTokenBetween(importToken, node.source, util.isOpeningBraceToken); | ||
const openingBraceToken = sourceCode.getFirstTokenBetween(importToken, node.source, util_1.isOpeningBraceToken); | ||
if (openingBraceToken) { | ||
// Only braces. e.g. import Foo, {} from 'foo' | ||
const commaToken = util.nullThrows(sourceCode.getTokenBefore(openingBraceToken, util.isCommaToken), util.NullThrowsReasons.MissingToken(',', node.type)); | ||
const closingBraceToken = util.nullThrows(sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util.isClosingBraceToken), util.NullThrowsReasons.MissingToken('}', node.type)); | ||
const commaToken = (0, util_1.nullThrows)(sourceCode.getTokenBefore(openingBraceToken, util_1.isCommaToken), util_1.NullThrowsReasons.MissingToken(',', node.type)); | ||
const closingBraceToken = (0, util_1.nullThrows)(sourceCode.getFirstTokenBetween(openingBraceToken, node.source, util_1.isClosingBraceToken), util_1.NullThrowsReasons.MissingToken('}', node.type)); | ||
// import type Foo, {} from 'foo' | ||
@@ -643,8 +632,7 @@ // ^^ remove | ||
function* fixRemoveTypeSpecifierFromImportDeclaration(fixer, node) { | ||
var _a, _b; | ||
// import type Foo from 'foo' | ||
// ^^^^ remove | ||
const importToken = util.nullThrows(sourceCode.getFirstToken(node, util.isImportKeyword), util.NullThrowsReasons.MissingToken('import', node.type)); | ||
const typeToken = util.nullThrows(sourceCode.getFirstTokenBetween(importToken, (_b = (_a = node.specifiers[0]) === null || _a === void 0 ? void 0 : _a.local) !== null && _b !== void 0 ? _b : node.source, util.isTypeKeyword), util.NullThrowsReasons.MissingToken('type', node.type)); | ||
const afterToken = util.nullThrows(sourceCode.getTokenAfter(typeToken, { includeComments: true }), util.NullThrowsReasons.MissingToken('any token', node.type)); | ||
const importToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import', node.type)); | ||
const typeToken = (0, util_1.nullThrows)(sourceCode.getFirstTokenBetween(importToken, node.specifiers[0]?.local ?? node.source, util_1.isTypeKeyword), util_1.NullThrowsReasons.MissingToken('type', node.type)); | ||
const afterToken = (0, util_1.nullThrows)(sourceCode.getTokenAfter(typeToken, { includeComments: true }), util_1.NullThrowsReasons.MissingToken('any token', node.type)); | ||
yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]); | ||
@@ -655,4 +643,4 @@ } | ||
// ^^^^ remove | ||
const typeToken = util.nullThrows(sourceCode.getFirstToken(node, util.isTypeKeyword), util.NullThrowsReasons.MissingToken('type', node.type)); | ||
const afterToken = util.nullThrows(sourceCode.getTokenAfter(typeToken, { includeComments: true }), util.NullThrowsReasons.MissingToken('any token', node.type)); | ||
const typeToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isTypeKeyword), util_1.NullThrowsReasons.MissingToken('type', node.type)); | ||
const afterToken = (0, util_1.nullThrows)(sourceCode.getTokenAfter(typeToken, { includeComments: true }), util_1.NullThrowsReasons.MissingToken('any token', node.type)); | ||
yield fixer.removeRange([typeToken.range[0], afterToken.range[0]]); | ||
@@ -659,0 +647,0 @@ } |
@@ -11,3 +11,2 @@ "use strict"; | ||
description: 'Enforce default parameters to be last', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -28,3 +27,3 @@ }, | ||
function isOptionalParam(node) { | ||
return 'optional' in node && node.optional === true; | ||
return 'optional' in node && node.optional; | ||
} | ||
@@ -31,0 +30,0 @@ /** |
@@ -26,3 +26,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
@@ -38,3 +38,3 @@ const util_1 = require("../util"); | ||
description: 'Enforce dot notation whenever possible', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
extendsBaseRule: true, | ||
@@ -85,15 +85,10 @@ requiresTypeChecking: true, | ||
create(context, [options]) { | ||
var _a; | ||
const rules = baseRule.create(context); | ||
const { program, esTreeNodeToTSNodeMap } = (0, util_1.getParserServices)(context); | ||
const typeChecker = program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const allowPrivateClassPropertyAccess = options.allowPrivateClassPropertyAccess; | ||
const allowProtectedClassPropertyAccess = options.allowProtectedClassPropertyAccess; | ||
const allowIndexSignaturePropertyAccess = ((_a = options.allowIndexSignaturePropertyAccess) !== null && _a !== void 0 ? _a : false) || | ||
tsutils.isCompilerOptionEnabled(program.getCompilerOptions(), | ||
// @ts-expect-error - TS is refining the type to never for some reason | ||
'noPropertyAccessFromIndexSignature'); | ||
const allowIndexSignaturePropertyAccess = (options.allowIndexSignaturePropertyAccess ?? false) || | ||
tsutils.isCompilerOptionEnabled(services.program.getCompilerOptions(), 'noPropertyAccessFromIndexSignature'); | ||
return { | ||
MemberExpression(node) { | ||
var _a, _b; | ||
if ((allowPrivateClassPropertyAccess || | ||
@@ -104,4 +99,4 @@ allowProtectedClassPropertyAccess || | ||
// for perf reasons - only fetch symbols if we have to | ||
const propertySymbol = typeChecker.getSymbolAtLocation(esTreeNodeToTSNodeMap.get(node.property)); | ||
const modifierKind = (_b = (0, util_1.getModifiers)((_a = propertySymbol === null || propertySymbol === void 0 ? void 0 : propertySymbol.getDeclarations()) === null || _a === void 0 ? void 0 : _a[0])) === null || _b === void 0 ? void 0 : _b[0].kind; | ||
const propertySymbol = services.getSymbolAtLocation(node.property); | ||
const modifierKind = (0, util_1.getModifiers)(propertySymbol?.getDeclarations()?.[0])?.[0].kind; | ||
if ((allowPrivateClassPropertyAccess && | ||
@@ -115,3 +110,3 @@ modifierKind === ts.SyntaxKind.PrivateKeyword) || | ||
allowIndexSignaturePropertyAccess) { | ||
const objectType = typeChecker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.object)); | ||
const objectType = services.getTypeAtLocation(node.object); | ||
const indexType = objectType | ||
@@ -118,0 +113,0 @@ .getNonNullableType() |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const explicitReturnTypeUtils_1 = require("../util/explicitReturnTypeUtils"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'explicit-function-return-type', | ||
@@ -35,3 +13,2 @@ meta: { | ||
description: 'Require explicit return types on functions and class methods', | ||
recommended: false, | ||
}, | ||
@@ -98,5 +75,4 @@ messages: { | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function isAllowedFunction(node) { | ||
var _a, _b; | ||
if (options.allowFunctionsWithoutTypeParameters && !node.typeParameters) { | ||
@@ -108,3 +84,3 @@ return true; | ||
} | ||
if (!((_a = options.allowedNames) === null || _a === void 0 ? void 0 : _a.length)) { | ||
if (!options.allowedNames?.length) { | ||
return false; | ||
@@ -116,6 +92,6 @@ } | ||
let funcName; | ||
if ((_b = node.id) === null || _b === void 0 ? void 0 : _b.name) { | ||
if (node.id?.name) { | ||
funcName = node.id.name; | ||
} | ||
else if (parent) { | ||
else { | ||
switch (parent.type) { | ||
@@ -132,3 +108,3 @@ case utils_1.AST_NODE_TYPES.VariableDeclarator: { | ||
if (parent.key.type === utils_1.AST_NODE_TYPES.Identifier && | ||
parent.computed === false) { | ||
!parent.computed) { | ||
funcName = parent.key.name; | ||
@@ -146,3 +122,2 @@ } | ||
node.id && | ||
node.id.type === utils_1.AST_NODE_TYPES.Identifier && | ||
!!options.allowedNames.includes(node.id.name)) { | ||
@@ -149,0 +124,0 @@ return true; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const accessibilityLevel = { | ||
oneOf: [ | ||
{ | ||
const: 'explicit', | ||
description: 'Always require an accessor.', | ||
}, | ||
{ | ||
const: 'no-public', | ||
description: 'Require an accessor except when public.', | ||
}, | ||
{ | ||
const: 'off', | ||
description: 'Never check whether there is an accessor.', | ||
}, | ||
], | ||
}; | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'explicit-member-accessibility', | ||
@@ -52,3 +14,2 @@ meta: { | ||
// too opinionated to be recommended | ||
recommended: false, | ||
}, | ||
@@ -61,49 +22,63 @@ fixable: 'code', | ||
}, | ||
schema: { | ||
$defs: { | ||
accessibilityLevel, | ||
}, | ||
prefixItems: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
accessibility: { $ref: '#/$defs/accessibilityLevel' }, | ||
overrides: { | ||
type: 'object', | ||
properties: { | ||
accessors: { $ref: '#/$defs/accessibilityLevel' }, | ||
constructors: { $ref: '#/$defs/accessibilityLevel' }, | ||
methods: { $ref: '#/$defs/accessibilityLevel' }, | ||
properties: { $ref: '#/$defs/accessibilityLevel' }, | ||
parameterProperties: { | ||
$ref: '#/$defs/accessibilityLevel', | ||
}, | ||
schema: [ | ||
{ | ||
$defs: { | ||
accessibilityLevel: { | ||
oneOf: [ | ||
{ | ||
type: 'string', | ||
enum: ['explicit'], | ||
description: 'Always require an accessor.', | ||
}, | ||
additionalProperties: false, | ||
}, | ||
ignoredMethodNames: { | ||
type: 'array', | ||
items: { | ||
{ | ||
type: 'string', | ||
enum: ['no-public'], | ||
description: 'Require an accessor except when public.', | ||
}, | ||
{ | ||
type: 'string', | ||
enum: ['off'], | ||
description: 'Never check whether there is an accessor.', | ||
}, | ||
], | ||
}, | ||
}, | ||
type: 'object', | ||
properties: { | ||
accessibility: { $ref: '#/items/0/$defs/accessibilityLevel' }, | ||
overrides: { | ||
type: 'object', | ||
properties: { | ||
accessors: { $ref: '#/items/0/$defs/accessibilityLevel' }, | ||
constructors: { $ref: '#/items/0/$defs/accessibilityLevel' }, | ||
methods: { $ref: '#/items/0/$defs/accessibilityLevel' }, | ||
properties: { $ref: '#/items/0/$defs/accessibilityLevel' }, | ||
parameterProperties: { | ||
$ref: '#/items/0/$defs/accessibilityLevel', | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
additionalProperties: false, | ||
ignoredMethodNames: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
}, | ||
}, | ||
}, | ||
], | ||
type: 'array', | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
defaultOptions: [{ accessibility: 'explicit' }], | ||
create(context, [option]) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
const sourceCode = context.getSourceCode(); | ||
const baseCheck = (_a = option.accessibility) !== null && _a !== void 0 ? _a : 'explicit'; | ||
const overrides = (_b = option.overrides) !== null && _b !== void 0 ? _b : {}; | ||
const ctorCheck = (_c = overrides.constructors) !== null && _c !== void 0 ? _c : baseCheck; | ||
const accessorCheck = (_d = overrides.accessors) !== null && _d !== void 0 ? _d : baseCheck; | ||
const methodCheck = (_e = overrides.methods) !== null && _e !== void 0 ? _e : baseCheck; | ||
const propCheck = (_f = overrides.properties) !== null && _f !== void 0 ? _f : baseCheck; | ||
const paramPropCheck = (_g = overrides.parameterProperties) !== null && _g !== void 0 ? _g : baseCheck; | ||
const ignoredMethodNames = new Set((_h = option.ignoredMethodNames) !== null && _h !== void 0 ? _h : []); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const baseCheck = option.accessibility ?? 'explicit'; | ||
const overrides = option.overrides ?? {}; | ||
const ctorCheck = overrides.constructors ?? baseCheck; | ||
const accessorCheck = overrides.accessors ?? baseCheck; | ||
const methodCheck = overrides.methods ?? baseCheck; | ||
const propCheck = overrides.properties ?? baseCheck; | ||
const paramPropCheck = overrides.parameterProperties ?? baseCheck; | ||
const ignoredMethodNames = new Set(option.ignoredMethodNames ?? []); | ||
/** | ||
@@ -132,3 +107,3 @@ * Checks if a method declaration has an accessibility modifier. | ||
} | ||
const { name: methodName } = util.getNameFromMember(methodDefinition, sourceCode); | ||
const { name: methodName } = (0, util_1.getNameFromMember)(methodDefinition, sourceCode); | ||
if (check === 'off' || ignoredMethodNames.has(methodName)) { | ||
@@ -198,4 +173,3 @@ return; | ||
function fix(accessibility, fixer) { | ||
var _a; | ||
if ((_a = node === null || node === void 0 ? void 0 : node.decorators) === null || _a === void 0 ? void 0 : _a.length) { | ||
if (node.decorators.length) { | ||
const lastDecorator = node.decorators[node.decorators.length - 1]; | ||
@@ -234,3 +208,3 @@ const nextToken = sourceCode.getTokenAfter(lastDecorator); | ||
const nodeType = 'class property'; | ||
const { name: propertyName } = util.getNameFromMember(propertyDefinition, sourceCode); | ||
const { name: propertyName } = (0, util_1.getNameFromMember)(propertyDefinition, sourceCode); | ||
if (propCheck === 'no-public' && | ||
@@ -237,0 +211,0 @@ propertyDefinition.accessibility === 'public') { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const explicitReturnTypeUtils_1 = require("../util/explicitReturnTypeUtils"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'explicit-module-boundary-types', | ||
@@ -36,3 +14,2 @@ meta: { | ||
description: "Require explicit return and argument types on exported functions' and classes' public class methods", | ||
recommended: false, | ||
}, | ||
@@ -79,6 +56,2 @@ messages: { | ||
}, | ||
// DEPRECATED - To be removed in next major | ||
shouldTrackReferences: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
@@ -99,3 +72,3 @@ additionalProperties: false, | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
// tracks all of the functions we've already checked | ||
@@ -215,4 +188,3 @@ const checkedFunctions = new Set(); | ||
function isAllowedName(node) { | ||
var _a; | ||
if (!node || !options.allowedNames || !options.allowedNames.length) { | ||
if (!node || !options.allowedNames || options.allowedNames.length === 0) { | ||
return false; | ||
@@ -222,3 +194,3 @@ } | ||
node.type === utils_1.AST_NODE_TYPES.FunctionDeclaration) { | ||
return (((_a = node.id) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Identifier && | ||
return (node.id?.type === utils_1.AST_NODE_TYPES.Identifier && | ||
options.allowedNames.includes(node.id.name)); | ||
@@ -245,3 +217,2 @@ } | ||
function isExportedHigherOrderFunction(node) { | ||
var _a; | ||
let current = node.parent; | ||
@@ -251,6 +222,6 @@ while (current) { | ||
// the parent of a return will always be a block statement, so we can skip over it | ||
current = (_a = current.parent) === null || _a === void 0 ? void 0 : _a.parent; | ||
current = current.parent.parent; | ||
continue; | ||
} | ||
if (!util.isFunction(current) || | ||
if (!(0, util_1.isFunction)(current) || | ||
!(0, explicitReturnTypeUtils_1.doesImmediatelyReturnFunctionExpression)(current)) { | ||
@@ -267,3 +238,3 @@ return false; | ||
function followReference(node) { | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
const variable = scope.set.get(node.name); | ||
@@ -352,7 +323,6 @@ /* istanbul ignore if */ if (!variable) { | ||
function checkEmptyBodyFunctionExpression(node) { | ||
var _a, _b, _c; | ||
const isConstructor = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
const isConstructor = node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
node.parent.kind === 'constructor'; | ||
const isSetAccessor = (((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition || | ||
((_c = node.parent) === null || _c === void 0 ? void 0 : _c.type) === utils_1.AST_NODE_TYPES.MethodDefinition) && | ||
const isSetAccessor = (node.parent.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition || | ||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) && | ||
node.parent.kind === 'set'; | ||
@@ -359,0 +329,0 @@ if (!isConstructor && !isSetAccessor && !node.returnType) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'func-call-spacing', | ||
@@ -33,3 +11,2 @@ meta: { | ||
description: 'Require or disallow spacing between function identifiers and their invocations', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -44,2 +21,3 @@ }, | ||
{ | ||
type: 'string', | ||
enum: ['never'], | ||
@@ -55,2 +33,3 @@ }, | ||
{ | ||
type: 'string', | ||
enum: ['always'], | ||
@@ -81,3 +60,3 @@ }, | ||
create(context, [option, config]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const text = sourceCode.getText(); | ||
@@ -91,7 +70,6 @@ /** | ||
function checkSpacing(node) { | ||
var _a; | ||
const isOptionalCall = util.isOptionalCallExpression(node); | ||
const isOptionalCall = (0, util_1.isOptionalCallExpression)(node); | ||
const closingParenToken = sourceCode.getLastToken(node); | ||
const lastCalleeTokenWithoutPossibleParens = sourceCode.getLastToken((_a = node.typeParameters) !== null && _a !== void 0 ? _a : node.callee); | ||
const openingParenToken = sourceCode.getFirstTokenBetween(lastCalleeTokenWithoutPossibleParens, closingParenToken, util.isOpeningParenToken); | ||
const lastCalleeTokenWithoutPossibleParens = sourceCode.getLastToken(node.typeArguments ?? node.callee); | ||
const openingParenToken = sourceCode.getFirstTokenBetween(lastCalleeTokenWithoutPossibleParens, closingParenToken, util_1.isOpeningParenToken); | ||
if (!openingParenToken || openingParenToken.range[1] >= node.range[1]) { | ||
@@ -101,3 +79,3 @@ // new expression with no parens... | ||
} | ||
const lastCalleeToken = sourceCode.getTokenBefore(openingParenToken, util.isNotOptionalChainPunctuator); | ||
const lastCalleeToken = sourceCode.getTokenBefore(openingParenToken, util_1.isNotOptionalChainPunctuator); | ||
const textBetweenTokens = text | ||
@@ -107,3 +85,3 @@ .slice(lastCalleeToken.range[1], openingParenToken.range[0]) | ||
const hasWhitespace = /\s/u.test(textBetweenTokens); | ||
const hasNewline = hasWhitespace && util.LINEBREAK_MATCHER.test(textBetweenTokens); | ||
const hasNewline = hasWhitespace && util_1.LINEBREAK_MATCHER.test(textBetweenTokens); | ||
if (option === 'never') { | ||
@@ -110,0 +88,0 @@ if (hasWhitespace) { |
@@ -8,28 +8,6 @@ "use strict"; | ||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -102,3 +80,3 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('indent'); | ||
]); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'indent', | ||
@@ -110,3 +88,2 @@ meta: { | ||
// too opinionated to be recommended | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -164,7 +141,20 @@ }, | ||
if (type === utils_1.AST_NODE_TYPES.Property) { | ||
return Object.assign({ type }, base); | ||
return { | ||
type, | ||
...base, | ||
}; | ||
} | ||
else { | ||
return Object.assign({ type, static: false, readonly: false, declare: false }, base); | ||
} | ||
return { | ||
type, | ||
accessibility: undefined, | ||
declare: false, | ||
decorators: [], | ||
definite: false, | ||
optional: false, | ||
override: false, | ||
readonly: false, | ||
static: false, | ||
typeAnnotation: undefined, | ||
...base, | ||
}; | ||
} | ||
@@ -205,2 +195,3 @@ return Object.assign({}, rules, { | ||
test: { | ||
parent: node, | ||
type: utils_1.AST_NODE_TYPES.BinaryExpression, | ||
@@ -278,2 +269,3 @@ operator: 'extends', | ||
], | ||
declare: false, | ||
// location data | ||
@@ -318,2 +310,9 @@ parent: node.parent, | ||
superClass: node.extends[0].expression, | ||
abstract: false, | ||
declare: false, | ||
decorators: [], | ||
implements: [], | ||
superTypeArguments: undefined, | ||
superTypeParameters: undefined, | ||
typeParameters: undefined, | ||
// location data | ||
@@ -326,3 +325,3 @@ parent: node.parent, | ||
TSMappedType(node) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const squareBracketStart = sourceCode.getTokenBefore(node.typeParameter); | ||
@@ -334,2 +333,3 @@ // transform it to an ObjectExpression | ||
{ | ||
parent: node, | ||
type: utils_1.AST_NODE_TYPES.Property, | ||
@@ -354,2 +354,3 @@ key: node.typeParameter, | ||
method: false, | ||
optional: false, | ||
shorthand: false, | ||
@@ -411,2 +412,4 @@ }, | ||
attributes: attributes, | ||
typeArguments: undefined, | ||
typeParameters: undefined, | ||
// location data | ||
@@ -413,0 +416,0 @@ parent: node.parent, |
@@ -15,2 +15,3 @@ "use strict"; | ||
const class_literal_property_style_1 = __importDefault(require("./class-literal-property-style")); | ||
const class_methods_use_this_1 = __importDefault(require("./class-methods-use-this")); | ||
const comma_dangle_1 = __importDefault(require("./comma-dangle")); | ||
@@ -36,2 +37,3 @@ const comma_spacing_1 = __importDefault(require("./comma-spacing")); | ||
const lines_between_class_members_1 = __importDefault(require("./lines-between-class-members")); | ||
const max_params_1 = __importDefault(require("./max-params")); | ||
const member_delimiter_style_1 = __importDefault(require("./member-delimiter-style")); | ||
@@ -47,3 +49,2 @@ const member_ordering_1 = __importDefault(require("./member-ordering")); | ||
const no_duplicate_enum_values_1 = __importDefault(require("./no-duplicate-enum-values")); | ||
const no_duplicate_imports_1 = __importDefault(require("./no-duplicate-imports")); | ||
const no_duplicate_type_constituents_1 = __importDefault(require("./no-duplicate-type-constituents")); | ||
@@ -60,3 +61,2 @@ const no_dynamic_delete_1 = __importDefault(require("./no-dynamic-delete")); | ||
const no_for_in_array_1 = __importDefault(require("./no-for-in-array")); | ||
const no_implicit_any_catch_1 = __importDefault(require("./no-implicit-any-catch")); | ||
const no_implied_eval_1 = __importDefault(require("./no-implied-eval")); | ||
@@ -78,3 +78,2 @@ const no_import_type_side_effects_1 = __importDefault(require("./no-import-type-side-effects")); | ||
const no_non_null_assertion_1 = __importDefault(require("./no-non-null-assertion")); | ||
const no_parameter_properties_1 = __importDefault(require("./no-parameter-properties")); | ||
const no_redeclare_1 = __importDefault(require("./no-redeclare")); | ||
@@ -98,4 +97,6 @@ const no_redundant_type_constituents_1 = __importDefault(require("./no-redundant-type-constituents")); | ||
const no_unsafe_declaration_merging_1 = __importDefault(require("./no-unsafe-declaration-merging")); | ||
const no_unsafe_enum_comparison_1 = __importDefault(require("./no-unsafe-enum-comparison")); | ||
const no_unsafe_member_access_1 = __importDefault(require("./no-unsafe-member-access")); | ||
const no_unsafe_return_1 = __importDefault(require("./no-unsafe-return")); | ||
const no_unsafe_unary_minus_1 = __importDefault(require("./no-unsafe-unary-minus")); | ||
const no_unused_expressions_1 = __importDefault(require("./no-unused-expressions")); | ||
@@ -106,2 +107,3 @@ const no_unused_vars_1 = __importDefault(require("./no-unused-vars")); | ||
const no_useless_empty_export_1 = __importDefault(require("./no-useless-empty-export")); | ||
const no_useless_template_literals_1 = __importDefault(require("./no-useless-template-literals")); | ||
const no_var_requires_1 = __importDefault(require("./no-var-requires")); | ||
@@ -113,2 +115,3 @@ const non_nullable_type_assertion_style_1 = __importDefault(require("./non-nullable-type-assertion-style")); | ||
const prefer_as_const_1 = __importDefault(require("./prefer-as-const")); | ||
const prefer_destructuring_1 = __importDefault(require("./prefer-destructuring")); | ||
const prefer_enum_initializers_1 = __importDefault(require("./prefer-enum-initializers")); | ||
@@ -138,3 +141,2 @@ const prefer_for_of_1 = __importDefault(require("./prefer-for-of")); | ||
const sort_type_constituents_1 = __importDefault(require("./sort-type-constituents")); | ||
const sort_type_union_intersection_members_1 = __importDefault(require("./sort-type-union-intersection-members")); | ||
const space_before_blocks_1 = __importDefault(require("./space-before-blocks")); | ||
@@ -160,2 +162,3 @@ const space_before_function_paren_1 = __importDefault(require("./space-before-function-paren")); | ||
'class-literal-property-style': class_literal_property_style_1.default, | ||
'class-methods-use-this': class_methods_use_this_1.default, | ||
'comma-dangle': comma_dangle_1.default, | ||
@@ -181,2 +184,3 @@ 'comma-spacing': comma_spacing_1.default, | ||
'lines-between-class-members': lines_between_class_members_1.default, | ||
'max-params': max_params_1.default, | ||
'member-delimiter-style': member_delimiter_style_1.default, | ||
@@ -192,3 +196,2 @@ 'member-ordering': member_ordering_1.default, | ||
'no-duplicate-enum-values': no_duplicate_enum_values_1.default, | ||
'no-duplicate-imports': no_duplicate_imports_1.default, | ||
'no-duplicate-type-constituents': no_duplicate_type_constituents_1.default, | ||
@@ -205,3 +208,2 @@ 'no-dynamic-delete': no_dynamic_delete_1.default, | ||
'no-for-in-array': no_for_in_array_1.default, | ||
'no-implicit-any-catch': no_implicit_any_catch_1.default, | ||
'no-implied-eval': no_implied_eval_1.default, | ||
@@ -223,3 +225,2 @@ 'no-import-type-side-effects': no_import_type_side_effects_1.default, | ||
'no-non-null-assertion': no_non_null_assertion_1.default, | ||
'no-parameter-properties': no_parameter_properties_1.default, | ||
'no-redeclare': no_redeclare_1.default, | ||
@@ -243,4 +244,6 @@ 'no-redundant-type-constituents': no_redundant_type_constituents_1.default, | ||
'no-unsafe-declaration-merging': no_unsafe_declaration_merging_1.default, | ||
'no-unsafe-enum-comparison': no_unsafe_enum_comparison_1.default, | ||
'no-unsafe-member-access': no_unsafe_member_access_1.default, | ||
'no-unsafe-return': no_unsafe_return_1.default, | ||
'no-unsafe-unary-minus': no_unsafe_unary_minus_1.default, | ||
'no-unused-expressions': no_unused_expressions_1.default, | ||
@@ -251,2 +254,3 @@ 'no-unused-vars': no_unused_vars_1.default, | ||
'no-useless-empty-export': no_useless_empty_export_1.default, | ||
'no-useless-template-literals': no_useless_template_literals_1.default, | ||
'no-var-requires': no_var_requires_1.default, | ||
@@ -258,2 +262,3 @@ 'non-nullable-type-assertion-style': non_nullable_type_assertion_style_1.default, | ||
'prefer-as-const': prefer_as_const_1.default, | ||
'prefer-destructuring': prefer_destructuring_1.default, | ||
'prefer-enum-initializers': prefer_enum_initializers_1.default, | ||
@@ -283,3 +288,2 @@ 'prefer-for-of': prefer_for_of_1.default, | ||
'sort-type-constituents': sort_type_constituents_1.default, | ||
'sort-type-union-intersection-members': sort_type_union_intersection_members_1.default, | ||
'space-before-blocks': space_before_blocks_1.default, | ||
@@ -286,0 +290,0 @@ 'space-before-function-paren': space_before_function_paren_1.default, |
@@ -13,3 +13,2 @@ "use strict"; | ||
description: 'Require or disallow initialization in variable declarations', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -16,0 +15,0 @@ }, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -34,12 +12,3 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('key-spacing'); | ||
: baseRule.meta.schema; | ||
/** | ||
* TODO: replace with native .at() once Node 14 stops being supported | ||
*/ | ||
function at(arr, position) { | ||
if (position < 0) { | ||
return arr[arr.length + position]; | ||
} | ||
return arr[position]; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'key-spacing', | ||
@@ -50,3 +19,2 @@ meta: { | ||
description: 'Enforce consistent spacing between property names and type annotations in types and interfaces', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -61,3 +29,3 @@ }, | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const baseRules = baseRule.create(context); | ||
@@ -69,3 +37,3 @@ /** | ||
const line = position.line - 1; // position.line is 1-indexed | ||
return util.getStringLength(at(sourceCode.lines, line).slice(0, position.column)); | ||
return (0, util_1.getStringLength)(sourceCode.lines.at(line).slice(0, position.column)); | ||
} | ||
@@ -77,3 +45,3 @@ /** | ||
function getLastTokenBeforeColon(node) { | ||
const colonToken = sourceCode.getTokenAfter(node, util.isColonToken); | ||
const colonToken = sourceCode.getTokenAfter(node, util_1.isColonToken); | ||
return sourceCode.getTokenBefore(colonToken); | ||
@@ -99,3 +67,3 @@ } | ||
const code = sourceCode.getText(node); | ||
return code.slice(0, sourceCode.getTokenAfter(at(node.parameters, -1), util.isClosingBracketToken).range[1] - node.range[0]); | ||
return code.slice(0, sourceCode.getTokenAfter(node.parameters.at(-1), util_1.isClosingBracketToken).range[1] - node.range[0]); | ||
} | ||
@@ -108,3 +76,3 @@ /** | ||
? node.key | ||
: at(node.parameters, -1)).loc.end; | ||
: node.parameters.at(-1)).loc.end; | ||
} | ||
@@ -127,5 +95,3 @@ function checkBeforeColon(node, expectedWhitespaceBeforeColon, mode) { | ||
} | ||
else { | ||
return fixer.insertTextBefore(typeAnnotation, ' '.repeat(-difference)); | ||
} | ||
return fixer.insertTextBefore(typeAnnotation, ' '.repeat(-difference)); | ||
}, | ||
@@ -141,5 +107,10 @@ data: { | ||
const { typeAnnotation } = node; | ||
const colon = typeAnnotation.loc.start.column; | ||
const typeStart = typeAnnotation.typeAnnotation.loc.start.column; | ||
const difference = typeStart - colon - 1 - expectedWhitespaceAfterColon; | ||
const colonToken = sourceCode.getFirstToken(typeAnnotation); | ||
const typeStart = sourceCode.getTokenAfter(colonToken, { | ||
includeComments: true, | ||
}).loc.start.column; | ||
const difference = typeStart - | ||
colonToken.loc.start.column - | ||
1 - | ||
expectedWhitespaceAfterColon; | ||
if (mode === 'strict' ? difference : difference < 0) { | ||
@@ -152,9 +123,7 @@ context.report({ | ||
return fixer.removeRange([ | ||
typeAnnotation.typeAnnotation.range[0] - difference, | ||
typeAnnotation.typeAnnotation.range[0], | ||
colonToken.range[1], | ||
colonToken.range[1] + difference, | ||
]); | ||
} | ||
else { | ||
return fixer.insertTextBefore(typeAnnotation.typeAnnotation, ' '.repeat(-difference)); | ||
} | ||
return fixer.insertTextAfter(colonToken, ' '.repeat(-difference)); | ||
}, | ||
@@ -186,3 +155,3 @@ data: { | ||
leadingComments[0].loc.start.line - groupEndLine <= 1 && | ||
candidateValueStartLine - at(leadingComments, -1).loc.end.line <= 1) { | ||
candidateValueStartLine - leadingComments.at(-1).loc.end.line <= 1) { | ||
for (let i = 1; i < leadingComments.length; i++) { | ||
@@ -200,10 +169,9 @@ if (leadingComments[i].loc.start.line - | ||
function checkAlignGroup(group) { | ||
var _a, _b, _c, _d, _e, _f, _g, _h; | ||
let alignColumn = 0; | ||
const align = (_d = (typeof options.align === 'object' | ||
const align = (typeof options.align === 'object' | ||
? options.align.on | ||
: typeof ((_a = options.multiLine) === null || _a === void 0 ? void 0 : _a.align) === 'object' | ||
: typeof options.multiLine?.align === 'object' | ||
? options.multiLine.align.on | ||
: (_c = (_b = options.multiLine) === null || _b === void 0 ? void 0 : _b.align) !== null && _c !== void 0 ? _c : options.align)) !== null && _d !== void 0 ? _d : 'colon'; | ||
const beforeColon = (_e = (typeof options.align === 'object' | ||
: options.multiLine?.align ?? options.align) ?? 'colon'; | ||
const beforeColon = (typeof options.align === 'object' | ||
? options.align.beforeColon | ||
@@ -214,5 +182,5 @@ : options.multiLine | ||
: options.multiLine.beforeColon | ||
: options.beforeColon)) !== null && _e !== void 0 ? _e : false; | ||
: options.beforeColon) ?? false; | ||
const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0; | ||
const afterColon = (_f = (typeof options.align === 'object' | ||
const afterColon = (typeof options.align === 'object' | ||
? options.align.afterColon | ||
@@ -223,5 +191,5 @@ : options.multiLine | ||
: options.multiLine.afterColon | ||
: options.afterColon)) !== null && _f !== void 0 ? _f : true; | ||
: options.afterColon) ?? true; | ||
const expectedWhitespaceAfterColon = afterColon ? 1 : 0; | ||
const mode = (_h = (typeof options.align === 'object' | ||
const mode = (typeof options.align === 'object' | ||
? options.align.mode | ||
@@ -231,5 +199,5 @@ : options.multiLine | ||
? // same behavior as in original rule | ||
(_g = options.multiLine.align.mode) !== null && _g !== void 0 ? _g : options.multiLine.mode | ||
options.multiLine.align.mode ?? options.multiLine.mode | ||
: options.multiLine.mode | ||
: options.mode)) !== null && _h !== void 0 ? _h : 'strict'; | ||
: options.mode) ?? 'strict'; | ||
for (const node of group) { | ||
@@ -270,5 +238,3 @@ if (isKeyTypeNode(node)) { | ||
} | ||
else { | ||
return fixer.insertTextBefore(toCheck, ' '.repeat(-difference)); | ||
} | ||
return fixer.insertTextBefore(toCheck, ' '.repeat(-difference)); | ||
}, | ||
@@ -290,4 +256,3 @@ data: { | ||
function checkIndividualNode(node, { singleLine }) { | ||
var _a, _b, _c; | ||
const beforeColon = (_a = (singleLine | ||
const beforeColon = (singleLine | ||
? options.singleLine | ||
@@ -298,5 +263,5 @@ ? options.singleLine.beforeColon | ||
? options.multiLine.beforeColon | ||
: options.beforeColon)) !== null && _a !== void 0 ? _a : false; | ||
: options.beforeColon) ?? false; | ||
const expectedWhitespaceBeforeColon = beforeColon ? 1 : 0; | ||
const afterColon = (_b = (singleLine | ||
const afterColon = (singleLine | ||
? options.singleLine | ||
@@ -307,5 +272,5 @@ ? options.singleLine.afterColon | ||
? options.multiLine.afterColon | ||
: options.afterColon)) !== null && _b !== void 0 ? _b : true; | ||
: options.afterColon) ?? true; | ||
const expectedWhitespaceAfterColon = afterColon ? 1 : 0; | ||
const mode = (_c = (singleLine | ||
const mode = (singleLine | ||
? options.singleLine | ||
@@ -316,3 +281,3 @@ ? options.singleLine.mode | ||
? options.multiLine.mode | ||
: options.mode)) !== null && _c !== void 0 ? _c : 'strict'; | ||
: options.mode) ?? 'strict'; | ||
if (isApplicable(node)) { | ||
@@ -324,3 +289,2 @@ checkBeforeColon(node, expectedWhitespaceBeforeColon, mode); | ||
function validateBody(body) { | ||
var _a; | ||
const isSingleLine = body.loc.start.line === body.loc.end.line; | ||
@@ -330,3 +294,3 @@ const members = body.type === utils_1.AST_NODE_TYPES.TSTypeLiteral ? body.members : body.body; | ||
let unalignedElements = []; | ||
if (options.align || ((_a = options.multiLine) === null || _a === void 0 ? void 0 : _a.align)) { | ||
if (options.align || options.multiLine?.align) { | ||
let currentAlignGroup = []; | ||
@@ -336,3 +300,3 @@ alignGroups.push(currentAlignGroup); | ||
for (const node of members) { | ||
let prevAlignedNode = at(currentAlignGroup, -1); | ||
let prevAlignedNode = currentAlignGroup.at(-1); | ||
if (prevAlignedNode !== prevNode) { | ||
@@ -344,3 +308,3 @@ prevAlignedNode = undefined; | ||
} | ||
else if ((prevNode === null || prevNode === void 0 ? void 0 : prevNode.loc.start.line) === node.loc.start.line) { | ||
else if (prevNode?.loc.start.line === node.loc.start.line) { | ||
if (prevAlignedNode) { | ||
@@ -372,5 +336,10 @@ // Here, prevNode === prevAlignedNode === currentAlignGroup.at(-1) | ||
} | ||
return Object.assign(Object.assign({}, baseRules), { TSTypeLiteral: validateBody, TSInterfaceBody: validateBody, ClassBody: validateBody }); | ||
return { | ||
...baseRules, | ||
TSTypeLiteral: validateBody, | ||
TSInterfaceBody: validateBody, | ||
ClassBody: validateBody, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=key-spacing.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -34,3 +12,3 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('keyword-spacing'); | ||
: baseRule.meta.schema; | ||
const schema = util.deepMerge( | ||
const schema = (0, util_1.deepMerge)( | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 | ||
@@ -47,3 +25,3 @@ baseSchema, { | ||
}); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'keyword-spacing', | ||
@@ -54,3 +32,2 @@ meta: { | ||
description: 'Enforce consistent spacing before and after keywords', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -65,6 +42,8 @@ }, | ||
create(context, [{ after, overrides }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const baseRules = baseRule.create(context); | ||
return Object.assign(Object.assign({}, baseRules), { TSAsExpression(node) { | ||
const asToken = util.nullThrows(sourceCode.getTokenAfter(node.expression, token => token.value === 'as'), util.NullThrowsReasons.MissingToken('as', node.type)); | ||
return { | ||
...baseRules, | ||
TSAsExpression(node) { | ||
const asToken = (0, util_1.nullThrows)(sourceCode.getTokenAfter(node.expression, token => token.value === 'as'), util_1.NullThrowsReasons.MissingToken('as', node.type)); | ||
const oldTokenType = asToken.type; | ||
@@ -82,11 +61,10 @@ // as is a contextual keyword, so it's always reported as an Identifier | ||
'ImportDeclaration[importKind=type]'(node) { | ||
var _a, _b, _c, _d; | ||
const { type: typeOptionOverride = {} } = overrides !== null && overrides !== void 0 ? overrides : {}; | ||
const { type: typeOptionOverride = {} } = overrides ?? {}; | ||
const typeToken = sourceCode.getFirstToken(node, { skip: 1 }); | ||
const punctuatorToken = sourceCode.getTokenAfter(typeToken); | ||
if (((_b = (_a = node.specifiers) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier) { | ||
if (node.specifiers[0]?.type === utils_1.AST_NODE_TYPES.ImportDefaultSpecifier) { | ||
return; | ||
} | ||
const spacesBetweenTypeAndPunctuator = punctuatorToken.range[0] - typeToken.range[1]; | ||
if (((_c = typeOptionOverride.after) !== null && _c !== void 0 ? _c : after) === true && | ||
if ((typeOptionOverride.after ?? after) === true && | ||
spacesBetweenTypeAndPunctuator === 0) { | ||
@@ -102,3 +80,3 @@ context.report({ | ||
} | ||
if (((_d = typeOptionOverride.after) !== null && _d !== void 0 ? _d : after) === false && | ||
if ((typeOptionOverride.after ?? after) === false && | ||
spacesBetweenTypeAndPunctuator > 0) { | ||
@@ -117,5 +95,6 @@ context.report({ | ||
} | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=keyword-spacing.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -56,3 +34,3 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('lines-around-comment'); | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'lines-around-comment', | ||
@@ -63,88 +41,84 @@ meta: { | ||
description: 'Require empty lines around comments', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
}, | ||
schema: { | ||
type: 'array', | ||
items: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
beforeBlockComment: { | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
afterBlockComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
beforeLineComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
afterLineComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowBlockStart: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowBlockEnd: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowClassStart: { | ||
type: 'boolean', | ||
}, | ||
allowClassEnd: { | ||
type: 'boolean', | ||
}, | ||
allowObjectStart: { | ||
type: 'boolean', | ||
}, | ||
allowObjectEnd: { | ||
type: 'boolean', | ||
}, | ||
allowArrayStart: { | ||
type: 'boolean', | ||
}, | ||
allowArrayEnd: { | ||
type: 'boolean', | ||
}, | ||
allowInterfaceStart: { | ||
type: 'boolean', | ||
}, | ||
allowInterfaceEnd: { | ||
type: 'boolean', | ||
}, | ||
allowTypeStart: { | ||
type: 'boolean', | ||
}, | ||
allowTypeEnd: { | ||
type: 'boolean', | ||
}, | ||
allowEnumStart: { | ||
type: 'boolean', | ||
}, | ||
allowEnumEnd: { | ||
type: 'boolean', | ||
}, | ||
allowModuleStart: { | ||
type: 'boolean', | ||
}, | ||
allowModuleEnd: { | ||
type: 'boolean', | ||
}, | ||
ignorePattern: { | ||
type: 'string', | ||
}, | ||
applyDefaultIgnorePatterns: { | ||
type: 'boolean', | ||
}, | ||
schema: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
beforeBlockComment: { | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
additionalProperties: false, | ||
afterBlockComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
beforeLineComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
afterLineComment: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowBlockStart: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowBlockEnd: { | ||
type: 'boolean', | ||
default: false, | ||
}, | ||
allowClassStart: { | ||
type: 'boolean', | ||
}, | ||
allowClassEnd: { | ||
type: 'boolean', | ||
}, | ||
allowObjectStart: { | ||
type: 'boolean', | ||
}, | ||
allowObjectEnd: { | ||
type: 'boolean', | ||
}, | ||
allowArrayStart: { | ||
type: 'boolean', | ||
}, | ||
allowArrayEnd: { | ||
type: 'boolean', | ||
}, | ||
allowInterfaceStart: { | ||
type: 'boolean', | ||
}, | ||
allowInterfaceEnd: { | ||
type: 'boolean', | ||
}, | ||
allowTypeStart: { | ||
type: 'boolean', | ||
}, | ||
allowTypeEnd: { | ||
type: 'boolean', | ||
}, | ||
allowEnumStart: { | ||
type: 'boolean', | ||
}, | ||
allowEnumEnd: { | ||
type: 'boolean', | ||
}, | ||
allowModuleStart: { | ||
type: 'boolean', | ||
}, | ||
allowModuleEnd: { | ||
type: 'boolean', | ||
}, | ||
ignorePattern: { | ||
type: 'string', | ||
}, | ||
applyDefaultIgnorePatterns: { | ||
type: 'boolean', | ||
}, | ||
}, | ||
], | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
fixable: baseRule.meta.fixable, | ||
@@ -160,7 +134,6 @@ hasSuggestions: baseRule.meta.hasSuggestions, | ||
create(context, [_options]) { | ||
var _a; | ||
const options = _options; | ||
const defaultIgnoreRegExp = COMMENTS_IGNORE_PATTERN; | ||
const customIgnoreRegExp = new RegExp((_a = options.ignorePattern) !== null && _a !== void 0 ? _a : '', 'u'); | ||
const sourceCode = context.getSourceCode(); | ||
const customIgnoreRegExp = new RegExp(options.ignorePattern ?? '', 'u'); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const comments = sourceCode.getAllComments(); | ||
@@ -180,4 +153,4 @@ const lines = sourceCode.lines; | ||
}); | ||
} while (currentToken && util.isCommentToken(currentToken)); | ||
if (currentToken && util.isTokenOnSameLine(currentToken, token)) { | ||
} while (currentToken && (0, util_1.isCommentToken)(currentToken)); | ||
if (currentToken && (0, util_1.isTokenOnSameLine)(currentToken, token)) { | ||
return true; | ||
@@ -190,4 +163,4 @@ } | ||
}); | ||
} while (currentToken && util.isCommentToken(currentToken)); | ||
if (currentToken && util.isTokenOnSameLine(token, currentToken)) { | ||
} while (currentToken && (0, util_1.isCommentToken)(currentToken)); | ||
if (currentToken && (0, util_1.isTokenOnSameLine)(token, currentToken)) { | ||
return true; | ||
@@ -309,4 +282,4 @@ } | ||
!commentAndEmptyLines.has(prevLineNum) && | ||
!(util.isCommentToken(previousTokenOrComment) && | ||
util.isTokenOnSameLine(previousTokenOrComment, token))) { | ||
!((0, util_1.isCommentToken)(previousTokenOrComment) && | ||
(0, util_1.isTokenOnSameLine)(previousTokenOrComment, token))) { | ||
const lineStart = token.range[0] - token.loc.start.column; | ||
@@ -326,4 +299,4 @@ const range = [lineStart, lineStart]; | ||
!commentAndEmptyLines.has(nextLineNum) && | ||
!(util.isCommentToken(nextTokenOrComment) && | ||
util.isTokenOnSameLine(token, nextTokenOrComment))) { | ||
!((0, util_1.isCommentToken)(nextTokenOrComment) && | ||
(0, util_1.isTokenOnSameLine)(token, nextTokenOrComment))) { | ||
context.report({ | ||
@@ -378,9 +351,7 @@ node: token, | ||
} | ||
else if (token.type === utils_1.AST_TOKEN_TYPES.Block) { | ||
if (options.beforeBlockComment || options.afterBlockComment) { | ||
checkForEmptyLine(token, { | ||
after: options.afterBlockComment, | ||
before: options.beforeBlockComment, | ||
}); | ||
} | ||
else if (options.beforeBlockComment || options.afterBlockComment) { | ||
checkForEmptyLine(token, { | ||
after: options.afterBlockComment, | ||
before: options.beforeBlockComment, | ||
}); | ||
} | ||
@@ -387,0 +358,0 @@ }); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('lines-between-class-members'); | ||
const schema = util.deepMerge(Object.assign({}, baseRule.meta.schema), { | ||
const schema = Object.values((0, util_1.deepMerge)({ ...baseRule.meta.schema }, { | ||
1: { | ||
exceptAfterOverload: { | ||
type: 'boolean', | ||
default: true, | ||
properties: { | ||
exceptAfterOverload: { | ||
type: 'boolean', | ||
default: true, | ||
}, | ||
}, | ||
}, | ||
}); | ||
exports.default = util.createRule({ | ||
})); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'lines-between-class-members', | ||
@@ -44,3 +23,2 @@ meta: { | ||
description: 'Require or disallow an empty line between class members', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -62,3 +40,3 @@ }, | ||
const rules = baseRule.create(context); | ||
const exceptAfterOverload = (secondOption === null || secondOption === void 0 ? void 0 : secondOption.exceptAfterOverload) && firstOption === 'always'; | ||
const exceptAfterOverload = secondOption?.exceptAfterOverload && firstOption === 'always'; | ||
function isOverload(node) { | ||
@@ -74,3 +52,3 @@ return ((node.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition || | ||
: node.body; | ||
rules.ClassBody(Object.assign(Object.assign({}, node), { body })); | ||
rules.ClassBody({ ...node, body }); | ||
}, | ||
@@ -77,0 +55,0 @@ }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const definition = { | ||
type: 'object', | ||
properties: { | ||
multiline: { | ||
type: 'object', | ||
properties: { | ||
delimiter: { enum: ['none', 'semi', 'comma'] }, | ||
requireLast: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
singleline: { | ||
type: 'object', | ||
properties: { | ||
// note can't have "none" for single line delimiter as it's invalid syntax | ||
delimiter: { enum: ['semi', 'comma'] }, | ||
requireLast: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}; | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const isLastTokenEndOfLine = (token, line) => { | ||
@@ -87,3 +42,25 @@ const positionInLine = token.loc.start.column; | ||
}; | ||
exports.default = util.createRule({ | ||
const BASE_SCHEMA = { | ||
type: 'object', | ||
properties: { | ||
multiline: { | ||
type: 'object', | ||
properties: { | ||
delimiter: { $ref: '#/items/0/$defs/multiLineOption' }, | ||
requireLast: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
singleline: { | ||
type: 'object', | ||
properties: { | ||
delimiter: { $ref: '#/items/0/$defs/singleLineOption' }, | ||
requireLast: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
}, | ||
additionalProperties: false, | ||
}; | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'member-delimiter-style', | ||
@@ -94,3 +71,2 @@ meta: { | ||
description: 'Require a specific member delimiter style for interfaces and type literals', | ||
recommended: false, | ||
}, | ||
@@ -106,9 +82,27 @@ fixable: 'whitespace', | ||
{ | ||
$defs: { | ||
multiLineOption: { | ||
type: 'string', | ||
enum: ['none', 'semi', 'comma'], | ||
}, | ||
// note can't have "none" for single line delimiter as it's invalid syntax | ||
singleLineOption: { | ||
type: 'string', | ||
enum: ['semi', 'comma'], | ||
}, | ||
// note - need to define this last as it references the enums | ||
delimiterConfig: BASE_SCHEMA, | ||
}, | ||
type: 'object', | ||
properties: Object.assign({}, definition.properties, { | ||
properties: { | ||
...BASE_SCHEMA.properties, | ||
overrides: { | ||
type: 'object', | ||
properties: { | ||
interface: definition, | ||
typeLiteral: definition, | ||
interface: { | ||
$ref: '#/items/0/$defs/delimiterConfig', | ||
}, | ||
typeLiteral: { | ||
$ref: '#/items/0/$defs/delimiterConfig', | ||
}, | ||
}, | ||
@@ -118,5 +112,6 @@ additionalProperties: false, | ||
multilineDetection: { | ||
type: 'string', | ||
enum: ['brackets', 'last-member'], | ||
}, | ||
}), | ||
}, | ||
additionalProperties: false, | ||
@@ -140,9 +135,8 @@ }, | ||
create(context, [options]) { | ||
var _a; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
// use the base options as the defaults for the cases | ||
const baseOptions = options; | ||
const overrides = (_a = baseOptions.overrides) !== null && _a !== void 0 ? _a : {}; | ||
const interfaceOptions = util.deepMerge(baseOptions, overrides.interface); | ||
const typeLiteralOptions = util.deepMerge(baseOptions, overrides.typeLiteral); | ||
const overrides = baseOptions.overrides ?? {}; | ||
const interfaceOptions = (0, util_1.deepMerge)(baseOptions, overrides.interface); | ||
const typeLiteralOptions = (0, util_1.deepMerge)(baseOptions, overrides.typeLiteral); | ||
/** | ||
@@ -178,3 +172,3 @@ * Check the last token in the given member. | ||
const sourceCodeLines = sourceCode.getLines(); | ||
const lastTokenLine = sourceCodeLines[(lastToken === null || lastToken === void 0 ? void 0 : lastToken.loc.start.line) - 1]; | ||
const lastTokenLine = sourceCodeLines[lastToken.loc.start.line - 1]; | ||
const optsSemi = getOption('semi'); | ||
@@ -256,5 +250,6 @@ const optsComma = getOption('comma'); | ||
const opts = isSingleLine | ||
? Object.assign(Object.assign({}, typeOpts.singleline), { type: 'single-line' }) : Object.assign(Object.assign({}, typeOpts.multiline), { type: 'multi-line' }); | ||
? { ...typeOpts.singleline, type: 'single-line' } | ||
: { ...typeOpts.multiline, type: 'multi-line' }; | ||
members.forEach((member, index) => { | ||
checkLastToken(member, opts !== null && opts !== void 0 ? opts : {}, index === members.length - 1); | ||
checkLastToken(member, opts, index === members.length - 1); | ||
}); | ||
@@ -261,0 +256,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var __importDefault = (this && this.__importDefault) || function (mod) { | ||
@@ -31,4 +8,5 @@ return (mod && mod.__esModule) ? mod : { "default": mod }; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const natural_compare_lite_1 = __importDefault(require("natural-compare-lite")); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const natural_compare_1 = __importDefault(require("natural-compare")); | ||
const util_1 = require("../util"); | ||
const neverConfig = { | ||
@@ -43,3 +21,3 @@ type: 'string', | ||
{ | ||
enum: memberTypes, | ||
$ref: memberTypes, | ||
}, | ||
@@ -49,3 +27,3 @@ { | ||
items: { | ||
enum: memberTypes, | ||
$ref: memberTypes, | ||
}, | ||
@@ -63,14 +41,6 @@ }, | ||
order: { | ||
type: 'string', | ||
enum: [ | ||
'alphabetically', | ||
'alphabetically-case-insensitive', | ||
'as-written', | ||
'natural', | ||
'natural-case-insensitive', | ||
], | ||
$ref: '#/items/0/$defs/orderOptions', | ||
}, | ||
optionalityOrder: { | ||
type: 'string', | ||
enum: ['optional-first', 'required-first'], | ||
$ref: '#/items/0/$defs/optionalityOrderOptions', | ||
}, | ||
@@ -114,2 +84,25 @@ }, | ||
'constructor', | ||
// Accessors | ||
'public-static-accessor', | ||
'protected-static-accessor', | ||
'private-static-accessor', | ||
'#private-static-accessor', | ||
'public-decorated-accessor', | ||
'protected-decorated-accessor', | ||
'private-decorated-accessor', | ||
'public-instance-accessor', | ||
'protected-instance-accessor', | ||
'private-instance-accessor', | ||
'#private-instance-accessor', | ||
'public-abstract-accessor', | ||
'protected-abstract-accessor', | ||
'public-accessor', | ||
'protected-accessor', | ||
'private-accessor', | ||
'#private-accessor', | ||
'static-accessor', | ||
'instance-accessor', | ||
'abstract-accessor', | ||
'decorated-accessor', | ||
'accessor', | ||
// Getters | ||
@@ -193,2 +186,3 @@ 'public-static-get', | ||
'constructor', | ||
'accessor', | ||
'get', | ||
@@ -207,3 +201,3 @@ 'set', | ||
} | ||
// Only class instance fields, methods, get and set can have decorators attached to them | ||
// Only class instance fields, methods, accessors, get and set can have decorators attached to them | ||
if (accessibility !== '#private' && | ||
@@ -213,2 +207,3 @@ (type === 'readonly-field' || | ||
type === 'method' || | ||
type === 'accessor' || | ||
type === 'get' || | ||
@@ -262,2 +257,4 @@ type === 'set')) { | ||
return node.readonly ? 'readonly-field' : 'field'; | ||
case utils_1.AST_NODE_TYPES.AccessorProperty: | ||
return 'accessor'; | ||
case utils_1.AST_NODE_TYPES.PropertyDefinition: | ||
@@ -283,7 +280,7 @@ return node.value && functionExpressions.includes(node.value.type) | ||
function getMemberRawName(member, sourceCode) { | ||
const { name, type } = util.getNameFromMember(member, sourceCode); | ||
if (type === util.MemberNameType.Quoted) { | ||
const { name, type } = (0, util_1.getNameFromMember)(member, sourceCode); | ||
if (type === util_1.MemberNameType.Quoted) { | ||
return name.slice(1, -1); | ||
} | ||
if (type === util.MemberNameType.Private) { | ||
if (type === util_1.MemberNameType.Private) { | ||
return name.slice(1); | ||
@@ -316,3 +313,3 @@ } | ||
case utils_1.AST_NODE_TYPES.TSIndexSignature: | ||
return util.getNameFromIndexSignature(node); | ||
return (0, util_1.getNameFromIndexSignature)(node); | ||
case utils_1.AST_NODE_TYPES.StaticBlock: | ||
@@ -367,7 +364,6 @@ return 'static block'; | ||
function getAccessibility(node) { | ||
var _a; | ||
if ('accessibility' in node && node.accessibility) { | ||
return node.accessibility; | ||
} | ||
if ('key' in node && ((_a = node.key) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.PrivateIdentifier) { | ||
if ('key' in node && node.key.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) { | ||
return '#private'; | ||
@@ -474,3 +470,3 @@ } | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'member-ordering', | ||
@@ -481,3 +477,2 @@ meta: { | ||
description: 'Require a consistent member declaration order', | ||
recommended: false, | ||
}, | ||
@@ -491,66 +486,63 @@ messages: { | ||
{ | ||
type: 'object', | ||
properties: { | ||
default: { | ||
oneOf: [ | ||
neverConfig, | ||
arrayConfig(allMemberTypes), | ||
objectConfig(allMemberTypes), | ||
$defs: { | ||
orderOptions: { | ||
type: 'string', | ||
enum: [ | ||
'alphabetically', | ||
'alphabetically-case-insensitive', | ||
'as-written', | ||
'natural', | ||
'natural-case-insensitive', | ||
], | ||
}, | ||
classes: { | ||
oneOf: [ | ||
neverConfig, | ||
arrayConfig(allMemberTypes), | ||
objectConfig(allMemberTypes), | ||
optionalityOrderOptions: { | ||
type: 'string', | ||
enum: ['optional-first', 'required-first'], | ||
}, | ||
allItems: { | ||
type: 'string', | ||
enum: allMemberTypes, | ||
}, | ||
typeItems: { | ||
type: 'string', | ||
enum: [ | ||
'readonly-signature', | ||
'signature', | ||
'readonly-field', | ||
'field', | ||
'method', | ||
'constructor', | ||
], | ||
}, | ||
classExpressions: { | ||
baseConfig: { | ||
oneOf: [ | ||
neverConfig, | ||
arrayConfig(allMemberTypes), | ||
objectConfig(allMemberTypes), | ||
arrayConfig('#/items/0/$defs/allItems'), | ||
objectConfig('#/items/0/$defs/allItems'), | ||
], | ||
}, | ||
interfaces: { | ||
typesConfig: { | ||
oneOf: [ | ||
neverConfig, | ||
arrayConfig([ | ||
'readonly-signature', | ||
'signature', | ||
'readonly-field', | ||
'field', | ||
'method', | ||
'constructor', | ||
]), | ||
objectConfig([ | ||
'readonly-signature', | ||
'signature', | ||
'readonly-field', | ||
'field', | ||
'method', | ||
'constructor', | ||
]), | ||
arrayConfig('#/items/0/$defs/typeItems'), | ||
objectConfig('#/items/0/$defs/typeItems'), | ||
], | ||
}, | ||
}, | ||
type: 'object', | ||
properties: { | ||
default: { | ||
$ref: '#/items/0/$defs/baseConfig', | ||
}, | ||
classes: { | ||
$ref: '#/items/0/$defs/baseConfig', | ||
}, | ||
classExpressions: { | ||
$ref: '#/items/0/$defs/baseConfig', | ||
}, | ||
interfaces: { | ||
$ref: '#/items/0/$defs/typesConfig', | ||
}, | ||
typeLiterals: { | ||
oneOf: [ | ||
neverConfig, | ||
arrayConfig([ | ||
'readonly-signature', | ||
'signature', | ||
'readonly-field', | ||
'field', | ||
'method', | ||
'constructor', | ||
]), | ||
objectConfig([ | ||
'readonly-signature', | ||
'signature', | ||
'readonly-field', | ||
'field', | ||
'method', | ||
'constructor', | ||
]), | ||
], | ||
$ref: '#/items/0/$defs/typesConfig', | ||
}, | ||
@@ -582,8 +574,8 @@ }, | ||
// Find first member which isn't correctly sorted | ||
members.forEach(member => { | ||
for (const member of members) { | ||
const rank = getRank(member, groupOrder, supportsModifiers); | ||
const name = getMemberName(member, context.getSourceCode()); | ||
const name = getMemberName(member, (0, eslint_utils_1.getSourceCode)(context)); | ||
const rankLastMember = previousRanks[previousRanks.length - 1]; | ||
if (rank === -1) { | ||
return; | ||
continue; | ||
} | ||
@@ -611,3 +603,3 @@ // Works for 1st item because x < undefined === false for any x (typeof string) | ||
} | ||
}); | ||
} | ||
return isCorrectlySorted ? memberGroups : null; | ||
@@ -628,3 +620,3 @@ } | ||
members.forEach(member => { | ||
const name = getMemberName(member, context.getSourceCode()); | ||
const name = getMemberName(member, (0, eslint_utils_1.getSourceCode)(context)); | ||
// Note: Not all members have names | ||
@@ -649,2 +641,5 @@ if (name) { | ||
function naturalOutOfOrder(name, previousName, order) { | ||
if (name === previousName) { | ||
return false; | ||
} | ||
switch (order) { | ||
@@ -656,5 +651,5 @@ case 'alphabetically': | ||
case 'natural': | ||
return (0, natural_compare_lite_1.default)(name, previousName) !== 1; | ||
return (0, natural_compare_1.default)(name, previousName) !== 1; | ||
case 'natural-case-insensitive': | ||
return ((0, natural_compare_lite_1.default)(name.toLowerCase(), previousName.toLowerCase()) !== 1); | ||
return ((0, natural_compare_1.default)(name.toLowerCase(), previousName.toLowerCase()) !== 1); | ||
} | ||
@@ -677,3 +672,3 @@ } | ||
data: { | ||
member: getMemberName(member, context.getSourceCode()), | ||
member: getMemberName(member, (0, eslint_utils_1.getSourceCode)(context)), | ||
optionalOrRequired: optionalityOrder === 'required-first' ? 'required' : 'optional', | ||
@@ -758,16 +753,12 @@ }, | ||
ClassDeclaration(node) { | ||
var _a; | ||
validateMembersOrder(node.body.body, (_a = options.classes) !== null && _a !== void 0 ? _a : options.default, true); | ||
validateMembersOrder(node.body.body, options.classes ?? options.default, true); | ||
}, | ||
ClassExpression(node) { | ||
var _a; | ||
validateMembersOrder(node.body.body, (_a = options.classExpressions) !== null && _a !== void 0 ? _a : options.default, true); | ||
validateMembersOrder(node.body.body, options.classExpressions ?? options.default, true); | ||
}, | ||
TSInterfaceDeclaration(node) { | ||
var _a; | ||
validateMembersOrder(node.body.body, (_a = options.interfaces) !== null && _a !== void 0 ? _a : options.default, false); | ||
validateMembersOrder(node.body.body, options.interfaces ?? options.default, false); | ||
}, | ||
TSTypeLiteral(node) { | ||
var _a; | ||
validateMembersOrder(node.members, (_a = options.typeLiterals) !== null && _a !== void 0 ? _a : options.default, false); | ||
validateMembersOrder(node.members, options.typeLiterals ?? options.default, false); | ||
}, | ||
@@ -774,0 +765,0 @@ }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'method-signature-style', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Enforce using a particular method signature syntax', | ||
recommended: false, | ||
}, | ||
@@ -44,2 +21,3 @@ fixable: 'code', | ||
{ | ||
type: 'string', | ||
enum: ['property', 'method'], | ||
@@ -51,3 +29,3 @@ }, | ||
create(context, [mode]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function getMethodKey(node) { | ||
@@ -69,4 +47,4 @@ let key = sourceCode.getText(node.key); | ||
if (node.params.length > 0) { | ||
const openingParen = util.nullThrows(sourceCode.getTokenBefore(node.params[0], util.isOpeningParenToken), 'Missing opening paren before first parameter'); | ||
const closingParen = util.nullThrows(sourceCode.getTokenAfter(node.params[node.params.length - 1], util.isClosingParenToken), 'Missing closing paren after last parameter'); | ||
const openingParen = (0, util_1.nullThrows)(sourceCode.getTokenBefore(node.params[0], util_1.isOpeningParenToken), 'Missing opening paren before first parameter'); | ||
const closingParen = (0, util_1.nullThrows)(sourceCode.getTokenAfter(node.params[node.params.length - 1], util_1.isClosingParenToken), 'Missing closing paren after last parameter'); | ||
params = sourceCode.text.substring(openingParen.range[0], closingParen.range[1]); | ||
@@ -90,3 +68,3 @@ } | ||
if (lastToken && | ||
(util.isSemicolonToken(lastToken) || util.isCommaToken(lastToken))) { | ||
((0, util_1.isSemicolonToken)(lastToken) || (0, util_1.isCommaToken)(lastToken))) { | ||
return lastToken.value; | ||
@@ -108,18 +86,59 @@ } | ||
} | ||
return Object.assign(Object.assign({}, (mode === 'property' && { | ||
TSMethodSignature(methodNode) { | ||
if (methodNode.kind !== 'method') { | ||
return; | ||
} | ||
const parent = methodNode.parent; | ||
const members = (parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.TSInterfaceBody | ||
? parent.body | ||
: (parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.TSTypeLiteral | ||
? parent.members | ||
: []; | ||
const duplicatedKeyMethodNodes = members.filter((element) => element.type === utils_1.AST_NODE_TYPES.TSMethodSignature && | ||
element !== methodNode && | ||
getMethodKey(element) === getMethodKey(methodNode)); | ||
const isParentModule = isNodeParentModuleDeclaration(methodNode); | ||
if (duplicatedKeyMethodNodes.length > 0) { | ||
return { | ||
...(mode === 'property' && { | ||
TSMethodSignature(methodNode) { | ||
if (methodNode.kind !== 'method') { | ||
return; | ||
} | ||
const parent = methodNode.parent; | ||
const members = parent.type === utils_1.AST_NODE_TYPES.TSInterfaceBody | ||
? parent.body | ||
: parent.type === utils_1.AST_NODE_TYPES.TSTypeLiteral | ||
? parent.members | ||
: []; | ||
const duplicatedKeyMethodNodes = members.filter((element) => element.type === utils_1.AST_NODE_TYPES.TSMethodSignature && | ||
element !== methodNode && | ||
getMethodKey(element) === getMethodKey(methodNode)); | ||
const isParentModule = isNodeParentModuleDeclaration(methodNode); | ||
if (duplicatedKeyMethodNodes.length > 0) { | ||
if (isParentModule) { | ||
context.report({ | ||
node: methodNode, | ||
messageId: 'errorMethod', | ||
}); | ||
} | ||
else { | ||
context.report({ | ||
node: methodNode, | ||
messageId: 'errorMethod', | ||
*fix(fixer) { | ||
const methodNodes = [ | ||
methodNode, | ||
...duplicatedKeyMethodNodes, | ||
].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1)); | ||
const typeString = methodNodes | ||
.map(node => { | ||
const params = getMethodParams(node); | ||
const returnType = getMethodReturnType(node); | ||
return `(${params} => ${returnType})`; | ||
}) | ||
.join(' & '); | ||
const key = getMethodKey(methodNode); | ||
const delimiter = getDelimiter(methodNode); | ||
yield fixer.replaceText(methodNode, `${key}: ${typeString}${delimiter}`); | ||
for (const node of duplicatedKeyMethodNodes) { | ||
const lastToken = sourceCode.getLastToken(node); | ||
if (lastToken) { | ||
const nextToken = sourceCode.getTokenAfter(lastToken); | ||
if (nextToken) { | ||
yield fixer.remove(node); | ||
yield fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], ''); | ||
} | ||
} | ||
} | ||
}, | ||
}); | ||
} | ||
return; | ||
} | ||
if (isParentModule) { | ||
@@ -135,74 +154,35 @@ context.report({ | ||
messageId: 'errorMethod', | ||
*fix(fixer) { | ||
const methodNodes = [ | ||
methodNode, | ||
...duplicatedKeyMethodNodes, | ||
].sort((a, b) => (a.range[0] < b.range[0] ? -1 : 1)); | ||
const typeString = methodNodes | ||
.map(node => { | ||
const params = getMethodParams(node); | ||
const returnType = getMethodReturnType(node); | ||
return `(${params} => ${returnType})`; | ||
}) | ||
.join(' & '); | ||
fix: fixer => { | ||
const key = getMethodKey(methodNode); | ||
const params = getMethodParams(methodNode); | ||
const returnType = getMethodReturnType(methodNode); | ||
const delimiter = getDelimiter(methodNode); | ||
yield fixer.replaceText(methodNode, `${key}: ${typeString}${delimiter}`); | ||
for (const node of duplicatedKeyMethodNodes) { | ||
const lastToken = sourceCode.getLastToken(node); | ||
if (lastToken) { | ||
const nextToken = sourceCode.getTokenAfter(lastToken); | ||
if (nextToken) { | ||
yield fixer.remove(node); | ||
yield fixer.replaceTextRange([lastToken.range[1], nextToken.range[0]], ''); | ||
} | ||
} | ||
} | ||
return fixer.replaceText(methodNode, `${key}: ${params} => ${returnType}${delimiter}`); | ||
}, | ||
}); | ||
} | ||
return; | ||
} | ||
if (isParentModule) { | ||
}, | ||
}), | ||
...(mode === 'method' && { | ||
TSPropertySignature(propertyNode) { | ||
const typeNode = propertyNode.typeAnnotation?.typeAnnotation; | ||
if (typeNode?.type !== utils_1.AST_NODE_TYPES.TSFunctionType) { | ||
return; | ||
} | ||
context.report({ | ||
node: methodNode, | ||
messageId: 'errorMethod', | ||
}); | ||
} | ||
else { | ||
context.report({ | ||
node: methodNode, | ||
messageId: 'errorMethod', | ||
node: propertyNode, | ||
messageId: 'errorProperty', | ||
fix: fixer => { | ||
const key = getMethodKey(methodNode); | ||
const params = getMethodParams(methodNode); | ||
const returnType = getMethodReturnType(methodNode); | ||
const delimiter = getDelimiter(methodNode); | ||
return fixer.replaceText(methodNode, `${key}: ${params} => ${returnType}${delimiter}`); | ||
const key = getMethodKey(propertyNode); | ||
const params = getMethodParams(typeNode); | ||
const returnType = getMethodReturnType(typeNode); | ||
const delimiter = getDelimiter(propertyNode); | ||
return fixer.replaceText(propertyNode, `${key}${params}: ${returnType}${delimiter}`); | ||
}, | ||
}); | ||
} | ||
}, | ||
})), (mode === 'method' && { | ||
TSPropertySignature(propertyNode) { | ||
var _a; | ||
const typeNode = (_a = propertyNode.typeAnnotation) === null || _a === void 0 ? void 0 : _a.typeAnnotation; | ||
if ((typeNode === null || typeNode === void 0 ? void 0 : typeNode.type) !== utils_1.AST_NODE_TYPES.TSFunctionType) { | ||
return; | ||
} | ||
context.report({ | ||
node: propertyNode, | ||
messageId: 'errorProperty', | ||
fix: fixer => { | ||
const key = getMethodKey(propertyNode); | ||
const params = getMethodParams(typeNode); | ||
const returnType = getMethodReturnType(typeNode); | ||
const delimiter = getDelimiter(propertyNode); | ||
return fixer.replaceText(propertyNode, `${key}${params}: ${returnType}${delimiter}`); | ||
}, | ||
}); | ||
}, | ||
})); | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=method-signature-style.js.map |
@@ -12,4 +12,3 @@ "use strict"; | ||
PredefinedFormats[PredefinedFormats["UPPER_CASE"] = 6] = "UPPER_CASE"; | ||
})(PredefinedFormats || (PredefinedFormats = {})); | ||
exports.PredefinedFormats = PredefinedFormats; | ||
})(PredefinedFormats || (exports.PredefinedFormats = PredefinedFormats = {})); | ||
var UnderscoreOptions; | ||
@@ -24,4 +23,3 @@ (function (UnderscoreOptions) { | ||
UnderscoreOptions[UnderscoreOptions["allowSingleOrDouble"] = 6] = "allowSingleOrDouble"; | ||
})(UnderscoreOptions || (UnderscoreOptions = {})); | ||
exports.UnderscoreOptions = UnderscoreOptions; | ||
})(UnderscoreOptions || (exports.UnderscoreOptions = UnderscoreOptions = {})); | ||
var Selectors; | ||
@@ -49,6 +47,8 @@ (function (Selectors) { | ||
Selectors[Selectors["typeParameter"] = 131072] = "typeParameter"; | ||
})(Selectors || (Selectors = {})); | ||
exports.Selectors = Selectors; | ||
// other | ||
Selectors[Selectors["import"] = 262144] = "import"; | ||
})(Selectors || (exports.Selectors = Selectors = {})); | ||
var MetaSelectors; | ||
(function (MetaSelectors) { | ||
/* eslint-disable @typescript-eslint/prefer-literal-enum-member */ | ||
MetaSelectors[MetaSelectors["default"] = -1] = "default"; | ||
@@ -60,4 +60,4 @@ MetaSelectors[MetaSelectors["variableLike"] = 7] = "variableLike"; | ||
MetaSelectors[MetaSelectors["property"] = 3584] = "property"; | ||
})(MetaSelectors || (MetaSelectors = {})); | ||
exports.MetaSelectors = MetaSelectors; | ||
/* eslint-enable @typescript-eslint/prefer-literal-enum-member */ | ||
})(MetaSelectors || (exports.MetaSelectors = MetaSelectors = {})); | ||
var Modifiers; | ||
@@ -91,14 +91,16 @@ (function (Modifiers) { | ||
Modifiers[Modifiers["async"] = 16384] = "async"; | ||
// default imports | ||
Modifiers[Modifiers["default"] = 32768] = "default"; | ||
// namespace imports | ||
Modifiers[Modifiers["namespace"] = 65536] = "namespace"; | ||
// make sure TypeModifiers starts at Modifiers + 1 or else sorting won't work | ||
})(Modifiers || (Modifiers = {})); | ||
exports.Modifiers = Modifiers; | ||
})(Modifiers || (exports.Modifiers = Modifiers = {})); | ||
var TypeModifiers; | ||
(function (TypeModifiers) { | ||
TypeModifiers[TypeModifiers["boolean"] = 32768] = "boolean"; | ||
TypeModifiers[TypeModifiers["string"] = 65536] = "string"; | ||
TypeModifiers[TypeModifiers["number"] = 131072] = "number"; | ||
TypeModifiers[TypeModifiers["function"] = 262144] = "function"; | ||
TypeModifiers[TypeModifiers["array"] = 524288] = "array"; | ||
})(TypeModifiers || (TypeModifiers = {})); | ||
exports.TypeModifiers = TypeModifiers; | ||
TypeModifiers[TypeModifiers["boolean"] = 131072] = "boolean"; | ||
TypeModifiers[TypeModifiers["string"] = 262144] = "string"; | ||
TypeModifiers[TypeModifiers["number"] = 524288] = "number"; | ||
TypeModifiers[TypeModifiers["function"] = 1048576] = "function"; | ||
TypeModifiers[TypeModifiers["array"] = 2097152] = "array"; | ||
})(TypeModifiers || (exports.TypeModifiers = TypeModifiers = {})); | ||
//# sourceMappingURL=enums.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.parseOptions = void 0; | ||
const util = __importStar(require("../../util")); | ||
const util_1 = require("../../util"); | ||
const enums_1 = require("./enums"); | ||
@@ -32,8 +9,7 @@ const shared_1 = require("./shared"); | ||
function normalizeOption(option) { | ||
var _a, _b, _c, _d, _e, _f; | ||
let weight = 0; | ||
(_a = option.modifiers) === null || _a === void 0 ? void 0 : _a.forEach(mod => { | ||
option.modifiers?.forEach(mod => { | ||
weight |= enums_1.Modifiers[mod]; | ||
}); | ||
(_b = option.types) === null || _b === void 0 ? void 0 : _b.forEach(mod => { | ||
option.types?.forEach(mod => { | ||
weight |= enums_1.TypeModifiers[mod]; | ||
@@ -62,4 +38,4 @@ }); | ||
suffix: option.suffix && option.suffix.length > 0 ? option.suffix : null, | ||
modifiers: (_d = (_c = option.modifiers) === null || _c === void 0 ? void 0 : _c.map(m => enums_1.Modifiers[m])) !== null && _d !== void 0 ? _d : null, | ||
types: (_f = (_e = option.types) === null || _e === void 0 ? void 0 : _e.map(m => enums_1.TypeModifiers[m])) !== null && _f !== void 0 ? _f : null, | ||
modifiers: option.modifiers?.map(m => enums_1.Modifiers[m]) ?? null, | ||
types: option.types?.map(m => enums_1.TypeModifiers[m]) ?? null, | ||
filter: option.filter !== undefined | ||
@@ -82,5 +58,8 @@ ? typeof option.filter === 'string' | ||
: [option.selector]; | ||
return selectors.map(selector => (Object.assign({ selector: (0, shared_1.isMetaSelector)(selector) | ||
return selectors.map(selector => ({ | ||
selector: (0, shared_1.isMetaSelector)(selector) | ||
? enums_1.MetaSelectors[selector] | ||
: enums_1.Selectors[selector] }, normalizedOption))); | ||
: enums_1.Selectors[selector], | ||
...normalizedOption, | ||
})); | ||
} | ||
@@ -91,8 +70,10 @@ function parseOptions(context) { | ||
.reduce((acc, val) => acc.concat(val), []); | ||
return util.getEnumNames(enums_1.Selectors).reduce((acc, k) => { | ||
const result = (0, util_1.getEnumNames)(enums_1.Selectors).reduce((acc, k) => { | ||
acc[k] = (0, validator_1.createValidator)(k, context, normalizedOptions); | ||
return acc; | ||
// eslint-disable-next-line @typescript-eslint/prefer-reduce-type-parameter | ||
}, {}); | ||
return result; | ||
} | ||
exports.parseOptions = parseOptions; | ||
//# sourceMappingURL=parse-options.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.SCHEMA = void 0; | ||
const util = __importStar(require("../../util")); | ||
const util_1 = require("../../util"); | ||
const enums_1 = require("./enums"); | ||
const UNDERSCORE_SCHEMA = { | ||
type: 'string', | ||
enum: util.getEnumNames(enums_1.UnderscoreOptions), | ||
}; | ||
const PREFIX_SUFFIX_SCHEMA = { | ||
type: 'array', | ||
items: { | ||
const $DEFS = { | ||
// enums | ||
underscoreOptions: { | ||
type: 'string', | ||
minLength: 1, | ||
enum: (0, util_1.getEnumNames)(enums_1.UnderscoreOptions), | ||
}, | ||
additionalItems: false, | ||
}; | ||
const MATCH_REGEX_SCHEMA = { | ||
type: 'object', | ||
properties: { | ||
match: { type: 'boolean' }, | ||
regex: { type: 'string' }, | ||
predefinedFormats: { | ||
type: 'string', | ||
enum: (0, util_1.getEnumNames)(enums_1.PredefinedFormats), | ||
}, | ||
required: ['match', 'regex'], | ||
}; | ||
const FORMAT_OPTIONS_PROPERTIES = { | ||
format: { | ||
typeModifiers: { | ||
type: 'string', | ||
enum: (0, util_1.getEnumNames)(enums_1.TypeModifiers), | ||
}, | ||
// repeated types | ||
prefixSuffixConfig: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
minLength: 1, | ||
}, | ||
additionalItems: false, | ||
}, | ||
matchRegexConfig: { | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
match: { type: 'boolean' }, | ||
regex: { type: 'string' }, | ||
}, | ||
required: ['match', 'regex'], | ||
}, | ||
formatOptionsConfig: { | ||
oneOf: [ | ||
@@ -55,4 +43,3 @@ { | ||
items: { | ||
type: 'string', | ||
enum: util.getEnumNames(enums_1.PredefinedFormats), | ||
$ref: '#/$defs/predefinedFormats', | ||
}, | ||
@@ -66,2 +53,16 @@ additionalItems: false, | ||
}, | ||
}; | ||
const UNDERSCORE_SCHEMA = { | ||
$ref: '#/$defs/underscoreOptions', | ||
}; | ||
const PREFIX_SUFFIX_SCHEMA = { | ||
$ref: '#/$defs/prefixSuffixConfig', | ||
}; | ||
const MATCH_REGEX_SCHEMA = { | ||
$ref: '#/$defs/matchRegexConfig', | ||
}; | ||
const FORMAT_OPTIONS_PROPERTIES = { | ||
format: { | ||
$ref: '#/$defs/formatOptionsConfig', | ||
}, | ||
custom: MATCH_REGEX_SCHEMA, | ||
@@ -106,4 +107,3 @@ leadingUnderscore: UNDERSCORE_SCHEMA, | ||
items: { | ||
type: 'string', | ||
enum: util.getEnumNames(enums_1.TypeModifiers), | ||
$ref: '#/$defs/typeModifiers', | ||
}, | ||
@@ -116,3 +116,7 @@ additionalItems: false, | ||
type: 'object', | ||
properties: Object.assign(Object.assign({}, FORMAT_OPTIONS_PROPERTIES), selector), | ||
description: `Selector '${selectorString}'`, | ||
properties: { | ||
...FORMAT_OPTIONS_PROPERTIES, | ||
...selector, | ||
}, | ||
required: ['selector', 'format'], | ||
@@ -126,40 +130,40 @@ additionalProperties: false, | ||
type: 'object', | ||
properties: Object.assign(Object.assign({}, FORMAT_OPTIONS_PROPERTIES), { | ||
filter: { | ||
oneOf: [ | ||
{ | ||
description: 'Multiple selectors in one config', | ||
properties: { | ||
...FORMAT_OPTIONS_PROPERTIES, | ||
...{ | ||
filter: { | ||
oneOf: [ | ||
{ | ||
type: 'string', | ||
minLength: 1, | ||
}, | ||
MATCH_REGEX_SCHEMA, | ||
], | ||
}, | ||
selector: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
minLength: 1, | ||
enum: [...(0, util_1.getEnumNames)(enums_1.MetaSelectors), ...(0, util_1.getEnumNames)(enums_1.Selectors)], | ||
}, | ||
MATCH_REGEX_SCHEMA, | ||
], | ||
}, | ||
selector: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
enum: [ | ||
...util.getEnumNames(enums_1.MetaSelectors), | ||
...util.getEnumNames(enums_1.Selectors), | ||
], | ||
additionalItems: false, | ||
}, | ||
additionalItems: false, | ||
}, | ||
modifiers: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
enum: util.getEnumNames(enums_1.Modifiers), | ||
modifiers: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
enum: (0, util_1.getEnumNames)(enums_1.Modifiers), | ||
}, | ||
additionalItems: false, | ||
}, | ||
additionalItems: false, | ||
}, | ||
types: { | ||
type: 'array', | ||
items: { | ||
type: 'string', | ||
enum: util.getEnumNames(enums_1.TypeModifiers), | ||
types: { | ||
type: 'array', | ||
items: { | ||
$ref: '#/$defs/typeModifiers', | ||
}, | ||
additionalItems: false, | ||
}, | ||
additionalItems: false, | ||
}, | ||
}), | ||
}, | ||
required: ['selector', 'format'], | ||
@@ -170,2 +174,3 @@ additionalProperties: false, | ||
const SCHEMA = { | ||
$defs: $DEFS, | ||
type: 'array', | ||
@@ -175,3 +180,3 @@ items: { | ||
selectorsSchema(), | ||
...selectorSchema('default', false, util.getEnumNames(enums_1.Modifiers)), | ||
...selectorSchema('default', false, (0, util_1.getEnumNames)(enums_1.Modifiers)), | ||
...selectorSchema('variableLike', false, ['unused', 'async']), | ||
@@ -287,2 +292,3 @@ ...selectorSchema('variable', true, [ | ||
...selectorSchema('typeParameter', false, ['unused']), | ||
...selectorSchema('import', false, ['default', 'namespace']), | ||
], | ||
@@ -289,0 +295,0 @@ }, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.createValidator = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../../util")); | ||
const util_1 = require("../../util"); | ||
const enums_1 = require("./enums"); | ||
@@ -68,3 +45,2 @@ const format_1 = require("./format"); | ||
return (node, modifiers = new Set()) => { | ||
var _a, _b, _c; | ||
const originalName = node.type === utils_1.AST_NODE_TYPES.Identifier || | ||
@@ -77,7 +53,7 @@ node.type === utils_1.AST_NODE_TYPES.PrivateIdentifier | ||
for (const config of configs) { | ||
if (((_a = config.filter) === null || _a === void 0 ? void 0 : _a.regex.test(originalName)) !== ((_b = config.filter) === null || _b === void 0 ? void 0 : _b.match)) { | ||
if (config.filter?.regex.test(originalName) !== config.filter?.match) { | ||
// name does not match the filter | ||
continue; | ||
} | ||
if ((_c = config.modifiers) === null || _c === void 0 ? void 0 : _c.some(modifier => !modifiers.has(modifier))) { | ||
if (config.modifiers?.some(modifier => !modifiers.has(modifier))) { | ||
// does not have the required modifiers | ||
@@ -125,3 +101,2 @@ continue; | ||
function formatReportData({ affixes, formats, originalName, processedName, position, custom, count, }) { | ||
var _a; | ||
return { | ||
@@ -133,8 +108,8 @@ type: (0, shared_1.selectorTypeToMessageString)(type), | ||
count, | ||
affixes: affixes === null || affixes === void 0 ? void 0 : affixes.join(', '), | ||
formats: formats === null || formats === void 0 ? void 0 : formats.map(f => enums_1.PredefinedFormats[f]).join(', '), | ||
regex: (_a = custom === null || custom === void 0 ? void 0 : custom.regex) === null || _a === void 0 ? void 0 : _a.toString(), | ||
regexMatch: (custom === null || custom === void 0 ? void 0 : custom.match) === true | ||
affixes: affixes?.join(', '), | ||
formats: formats?.map(f => enums_1.PredefinedFormats[f]).join(', '), | ||
regex: custom?.regex.toString(), | ||
regexMatch: custom?.match === true | ||
? 'match' | ||
: (custom === null || custom === void 0 ? void 0 : custom.match) === false | ||
: custom?.match === false | ||
? 'not match' | ||
@@ -297,3 +272,3 @@ : null, | ||
const formats = config.format; | ||
if (!(formats === null || formats === void 0 ? void 0 : formats.length)) { | ||
if (!formats?.length) { | ||
return true; | ||
@@ -338,7 +313,6 @@ } | ||
} | ||
const { esTreeNodeToTSNodeMap, program } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const tsNode = esTreeNodeToTSNodeMap.get(node); | ||
const type = checker | ||
.getTypeAtLocation(tsNode) | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const type = services | ||
.getTypeAtLocation(node) | ||
// remove null and undefined from the type, as we don't care about it here | ||
@@ -345,0 +319,0 @@ .getNonNullableType(); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const naming_convention_utils_1 = require("./naming-convention-utils"); | ||
@@ -40,2 +18,6 @@ // This essentially mirrors ESLint's `camelcase` rule | ||
{ | ||
selector: 'import', | ||
format: ['camelCase', 'PascalCase'], | ||
}, | ||
{ | ||
selector: 'variable', | ||
@@ -51,3 +33,3 @@ format: ['camelCase', 'UPPER_CASE'], | ||
]; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'naming-convention', | ||
@@ -57,3 +39,2 @@ meta: { | ||
description: 'Enforce naming conventions for everything across a codebase', | ||
recommended: false, | ||
// technically only requires type checking if the user uses "type" modifiers | ||
@@ -75,4 +56,3 @@ requiresTypeChecking: true, | ||
create(contextWithoutDefaults) { | ||
const context = contextWithoutDefaults.options && | ||
contextWithoutDefaults.options.length > 0 | ||
const context = contextWithoutDefaults.options.length > 0 | ||
? contextWithoutDefaults | ||
@@ -84,10 +64,4 @@ : // only apply the defaults when the user provides no config | ||
const validators = (0, naming_convention_utils_1.parseOptions)(context); | ||
// getParserServices(context, false) -- dirty hack to work around the docs checker test... | ||
const compilerOptions = util | ||
.getParserServices(context, true) | ||
.program.getCompilerOptions(); | ||
const compilerOptions = (0, util_1.getParserServices)(context, true).program?.getCompilerOptions() ?? {}; | ||
function handleMember(validator, node, modifiers) { | ||
if (!validator) { | ||
return; | ||
} | ||
const key = node.key; | ||
@@ -125,9 +99,8 @@ if (requiresQuoting(key, compilerOptions.target)) { | ||
} | ||
const unusedVariables = util.collectUnusedVariables(context); | ||
function isUnused(name, initialScope = context.getScope()) { | ||
var _a; | ||
const unusedVariables = (0, util_1.collectUnusedVariables)(context); | ||
function isUnused(name, initialScope = (0, eslint_utils_1.getScope)(context)) { | ||
let variable = null; | ||
let scope = initialScope; | ||
while (scope) { | ||
variable = (_a = scope.set.get(name)) !== null && _a !== void 0 ? _a : null; | ||
variable = scope.set.get(name) ?? null; | ||
if (variable) { | ||
@@ -144,11 +117,10 @@ break; | ||
function isDestructured(id) { | ||
var _a, _b, _c; | ||
return ( | ||
// `const { x }` | ||
// does not match `const { x: y }` | ||
(((_a = id.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Property && id.parent.shorthand) || | ||
(id.parent.type === utils_1.AST_NODE_TYPES.Property && id.parent.shorthand) || | ||
// `const { x = 2 }` | ||
// does not match const `{ x: y = 2 }` | ||
(((_b = id.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.AssignmentPattern && | ||
((_c = id.parent.parent) === null || _c === void 0 ? void 0 : _c.type) === utils_1.AST_NODE_TYPES.Property && | ||
(id.parent.type === utils_1.AST_NODE_TYPES.AssignmentPattern && | ||
id.parent.parent.type === utils_1.AST_NODE_TYPES.Property && | ||
id.parent.parent.shorthand)); | ||
@@ -163,10 +135,33 @@ } | ||
function isAsyncVariableIdentifier(id) { | ||
return Boolean(id.parent && | ||
(('async' in id.parent && id.parent.async) || | ||
('init' in id.parent && | ||
id.parent.init && | ||
'async' in id.parent.init && | ||
id.parent.init.async))); | ||
return Boolean(('async' in id.parent && id.parent.async) || | ||
('init' in id.parent && | ||
id.parent.init && | ||
'async' in id.parent.init && | ||
id.parent.init.async)); | ||
} | ||
const selectors = { | ||
// #region import | ||
'ImportDefaultSpecifier, ImportNamespaceSpecifier, ImportSpecifier': { | ||
validator: validators.import, | ||
handler: (node, validator) => { | ||
const modifiers = new Set(); | ||
switch (node.type) { | ||
case utils_1.AST_NODE_TYPES.ImportDefaultSpecifier: | ||
modifiers.add(naming_convention_utils_1.Modifiers.default); | ||
break; | ||
case utils_1.AST_NODE_TYPES.ImportNamespaceSpecifier: | ||
modifiers.add(naming_convention_utils_1.Modifiers.namespace); | ||
break; | ||
case utils_1.AST_NODE_TYPES.ImportSpecifier: | ||
// Handle `import { default as Foo }` | ||
if (node.imported.name !== 'default') { | ||
return; | ||
} | ||
modifiers.add(naming_convention_utils_1.Modifiers.default); | ||
break; | ||
} | ||
validator(node.local, modifiers); | ||
}, | ||
}, | ||
// #endregion | ||
// #region variable | ||
@@ -179,7 +174,7 @@ VariableDeclarator: { | ||
const parent = node.parent; | ||
if ((parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.VariableDeclaration) { | ||
if (parent.type === utils_1.AST_NODE_TYPES.VariableDeclaration) { | ||
if (parent.kind === 'const') { | ||
baseModifiers.add(naming_convention_utils_1.Modifiers.const); | ||
} | ||
if (isGlobal(context.getScope())) { | ||
if (isGlobal((0, eslint_utils_1.getScope)(context))) { | ||
baseModifiers.add(naming_convention_utils_1.Modifiers.global); | ||
@@ -193,3 +188,3 @@ } | ||
} | ||
if (isExported(parent, id.name, context.getScope())) { | ||
if (isExported(parent, id.name, (0, eslint_utils_1.getScope)(context))) { | ||
modifiers.add(naming_convention_utils_1.Modifiers.exported); | ||
@@ -217,3 +212,3 @@ } | ||
// functions create their own nested scope | ||
const scope = context.getScope().upper; | ||
const scope = (0, eslint_utils_1.getScope)(context).upper; | ||
if (isGlobal(scope)) { | ||
@@ -377,3 +372,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.global); | ||
// classes create their own nested scope | ||
const scope = context.getScope().upper; | ||
const scope = (0, eslint_utils_1.getScope)(context).upper; | ||
if (node.abstract) { | ||
@@ -397,3 +392,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.abstract); | ||
const modifiers = new Set(); | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
if (isExported(node, node.id.name, scope)) { | ||
@@ -414,3 +409,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.exported); | ||
const modifiers = new Set(); | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
if (isExported(node, node.id.name, scope)) { | ||
@@ -432,3 +427,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.exported); | ||
// enums create their own nested scope | ||
const scope = context.getScope().upper; | ||
const scope = (0, eslint_utils_1.getScope)(context).upper; | ||
if (isExported(node, node.id.name, scope)) { | ||
@@ -449,3 +444,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.exported); | ||
const modifiers = new Set(); | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
if (isUnused(node.name.name, scope)) { | ||
@@ -459,4 +454,3 @@ modifiers.add(naming_convention_utils_1.Modifiers.unused); | ||
}; | ||
return Object.fromEntries(Object.entries(selectors) | ||
.map(([selector, { validator, handler }]) => { | ||
return Object.fromEntries(Object.entries(selectors).map(([selector, { validator, handler }]) => { | ||
return [ | ||
@@ -468,4 +462,3 @@ selector, | ||
]; | ||
}) | ||
.filter((s) => s != null)); | ||
})); | ||
}, | ||
@@ -480,5 +473,4 @@ }); | ||
function isExported(node, name, scope) { | ||
var _a, _b; | ||
if (((_a = node === null || node === void 0 ? void 0 : node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration || | ||
((_b = node === null || node === void 0 ? void 0 : node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) { | ||
if (node?.parent?.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration || | ||
node?.parent?.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) { | ||
return true; | ||
@@ -493,4 +485,4 @@ } | ||
const refParent = ref.identifier.parent; | ||
if ((refParent === null || refParent === void 0 ? void 0 : refParent.type) === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration || | ||
(refParent === null || refParent === void 0 ? void 0 : refParent.type) === utils_1.AST_NODE_TYPES.ExportSpecifier) { | ||
if (refParent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration || | ||
refParent.type === utils_1.AST_NODE_TYPES.ExportSpecifier) { | ||
return true; | ||
@@ -514,4 +506,4 @@ } | ||
: `${node.value}`; | ||
return util.requiresQuoting(name, target); | ||
return (0, util_1.requiresQuoting)(name, target); | ||
} | ||
//# sourceMappingURL=naming-convention.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-array-constructor', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow generic `Array` constructors', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
extendsBaseRule: true, | ||
@@ -54,4 +32,4 @@ }, | ||
node.callee.name === 'Array' && | ||
!node.typeParameters && | ||
!util.isOptionalCallExpression(node)) { | ||
!node.typeArguments && | ||
!(0, util_1.isOptionalCallExpression)(node)) { | ||
context.report({ | ||
@@ -64,3 +42,3 @@ node, | ||
} | ||
const fullText = context.getSourceCode().getText(node); | ||
const fullText = (0, eslint_utils_1.getSourceCode)(context).getText(node); | ||
const preambleLength = node.callee.range[1] - node.range[0]; | ||
@@ -67,0 +45,0 @@ return fixer.replaceText(node, `[${fullText.slice(preambleLength + 1, -1)}]`); |
@@ -27,11 +27,12 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
var Usefulness; | ||
(function (Usefulness) { | ||
Usefulness[Usefulness["Always"] = 0] = "Always"; | ||
Usefulness["Always"] = "always"; | ||
Usefulness["Never"] = "will"; | ||
Usefulness["Sometimes"] = "may"; | ||
})(Usefulness || (Usefulness = {})); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-base-to-string', | ||
@@ -41,3 +42,3 @@ meta: { | ||
description: 'Require `.toString()` to only be called on objects which provide useful information when stringified', | ||
recommended: 'strict', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -70,6 +71,5 @@ }, | ||
create(context, [option]) { | ||
var _a; | ||
const parserServices = util.getParserServices(context); | ||
const typeChecker = parserServices.program.getTypeChecker(); | ||
const ignoredTypeNames = (_a = option.ignoredTypeNames) !== null && _a !== void 0 ? _a : []; | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const ignoredTypeNames = option.ignoredTypeNames ?? []; | ||
function checkExpression(node, type) { | ||
@@ -79,3 +79,3 @@ if (node.type === utils_1.AST_NODE_TYPES.Literal) { | ||
} | ||
const certainty = collectToStringCertainty(type !== null && type !== void 0 ? type : typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node))); | ||
const certainty = collectToStringCertainty(type ?? services.getTypeAtLocation(node)); | ||
if (certainty === Usefulness.Always) { | ||
@@ -87,3 +87,3 @@ return; | ||
certainty, | ||
name: context.getSourceCode().getText(node), | ||
name: (0, eslint_utils_1.getSourceCode)(context).getText(node), | ||
}, | ||
@@ -95,4 +95,4 @@ messageId: 'baseToString', | ||
function collectToStringCertainty(type) { | ||
const toString = typeChecker.getPropertyOfType(type, 'toString'); | ||
const declarations = toString === null || toString === void 0 ? void 0 : toString.getDeclarations(); | ||
const toString = checker.getPropertyOfType(type, 'toString'); | ||
const declarations = toString?.getDeclarations(); | ||
if (!toString || !declarations || declarations.length === 0) { | ||
@@ -106,3 +106,3 @@ return Usefulness.Always; | ||
} | ||
if (ignoredTypeNames.includes(util.getTypeName(typeChecker, type))) { | ||
if (ignoredTypeNames.includes((0, util_1.getTypeName)(checker, type))) { | ||
return Usefulness.Always; | ||
@@ -146,8 +146,8 @@ } | ||
'AssignmentExpression[operator = "+="], BinaryExpression[operator = "+"]'(node) { | ||
const leftType = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node.left)); | ||
const rightType = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node.right)); | ||
if (util.getTypeName(typeChecker, leftType) === 'string') { | ||
const leftType = services.getTypeAtLocation(node.left); | ||
const rightType = services.getTypeAtLocation(node.right); | ||
if ((0, util_1.getTypeName)(checker, leftType) === 'string') { | ||
checkExpression(node.right, rightType); | ||
} | ||
else if (util.getTypeName(typeChecker, rightType) === 'string' && | ||
else if ((0, util_1.getTypeName)(checker, rightType) === 'string' && | ||
node.left.type !== utils_1.AST_NODE_TYPES.PrivateIdentifier) { | ||
@@ -162,4 +162,3 @@ checkExpression(node.left, leftType); | ||
TemplateLiteral(node) { | ||
if (node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression) { | ||
return; | ||
@@ -166,0 +165,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-confusing-non-null-assertion', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow non-null assertion in locations that may be confusing', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -50,3 +28,3 @@ fixable: 'code', | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
@@ -63,5 +41,5 @@ 'BinaryExpression, AssignmentExpression'(node) { | ||
const tokenAfterLeft = sourceCode.getTokenAfter(node.left); | ||
if ((leftHandFinalToken === null || leftHandFinalToken === void 0 ? void 0 : leftHandFinalToken.type) === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
(leftHandFinalToken === null || leftHandFinalToken === void 0 ? void 0 : leftHandFinalToken.value) === '!' && | ||
(tokenAfterLeft === null || tokenAfterLeft === void 0 ? void 0 : tokenAfterLeft.value) !== ')') { | ||
if (leftHandFinalToken?.type === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
leftHandFinalToken.value === '!' && | ||
tokenAfterLeft?.value !== ')') { | ||
if (isLeftHandPrimaryExpression(node.left)) { | ||
@@ -68,0 +46,0 @@ context.report({ |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-confusing-void-expression', | ||
@@ -36,3 +37,3 @@ meta: { | ||
description: 'Require expressions of type void to appear in statement position', | ||
recommended: false, | ||
recommended: 'strict', | ||
requiresTypeChecking: true, | ||
@@ -76,6 +77,4 @@ }, | ||
'AwaitExpression, CallExpression, TaggedTemplateExpression'(node) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(checker, tsNode); | ||
const services = (0, util_1.getParserServices)(context); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
if (!tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike)) { | ||
@@ -90,3 +89,3 @@ // not a void expression | ||
} | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const wrapVoidFix = (fixer) => { | ||
@@ -113,8 +112,11 @@ const nodeText = sourceCode.getText(node); | ||
fix(fixer) { | ||
if (!canFix(arrowFunction)) { | ||
return null; | ||
} | ||
const arrowBody = arrowFunction.body; | ||
const arrowBodyText = sourceCode.getText(arrowBody); | ||
const newArrowBodyText = `{ ${arrowBodyText}; }`; | ||
if (util.isParenthesized(arrowBody, sourceCode)) { | ||
const bodyOpeningParen = sourceCode.getTokenBefore(arrowBody, util.isOpeningParenToken); | ||
const bodyClosingParen = sourceCode.getTokenAfter(arrowBody, util.isClosingParenToken); | ||
if ((0, util_1.isParenthesized)(arrowBody, sourceCode)) { | ||
const bodyOpeningParen = sourceCode.getTokenBefore(arrowBody, util_1.isOpeningParenToken); | ||
const bodyClosingParen = sourceCode.getTokenAfter(arrowBody, util_1.isClosingParenToken); | ||
return fixer.replaceTextRange([bodyOpeningParen.range[0], bodyClosingParen.range[1]], newArrowBodyText); | ||
@@ -143,2 +145,5 @@ } | ||
fix(fixer) { | ||
if (!canFix(returnStmt)) { | ||
return null; | ||
} | ||
const returnValue = returnStmt.argument; | ||
@@ -160,3 +165,2 @@ const returnValueText = sourceCode.getText(returnValue); | ||
fix(fixer) { | ||
var _a; | ||
const returnValue = returnStmt.argument; | ||
@@ -169,3 +173,3 @@ const returnValueText = sourceCode.getText(returnValue); | ||
} | ||
if (((_a = returnStmt.parent) === null || _a === void 0 ? void 0 : _a.type) !== utils_1.AST_NODE_TYPES.BlockStatement) { | ||
if (returnStmt.parent.type !== utils_1.AST_NODE_TYPES.BlockStatement) { | ||
// e.g. `if (cond) return console.error();` | ||
@@ -203,3 +207,3 @@ // add braces if not inside a block | ||
function findInvalidAncestor(node) { | ||
const parent = util.nullThrows(node.parent, util.NullThrowsReasons.MissingParent); | ||
const parent = (0, util_1.nullThrows)(node.parent, util_1.NullThrowsReasons.MissingParent); | ||
if (parent.type === utils_1.AST_NODE_TYPES.SequenceExpression) { | ||
@@ -255,3 +259,3 @@ if (node !== parent.expressions[parent.expressions.length - 1]) { | ||
// the parent must be a block | ||
const block = util.nullThrows(node.parent, util.NullThrowsReasons.MissingParent); | ||
const block = (0, util_1.nullThrows)(node.parent, util_1.NullThrowsReasons.MissingParent); | ||
if (block.type !== utils_1.AST_NODE_TYPES.BlockStatement) { | ||
@@ -262,3 +266,3 @@ // e.g. `if (cond) return;` (not in a block) | ||
// the block's parent must be a function | ||
const blockParent = util.nullThrows(block.parent, util.NullThrowsReasons.MissingParent); | ||
const blockParent = (0, util_1.nullThrows)(block.parent, util_1.NullThrowsReasons.MissingParent); | ||
if (![ | ||
@@ -287,7 +291,15 @@ utils_1.AST_NODE_TYPES.FunctionDeclaration, | ||
function isPreventingASI(node, sourceCode) { | ||
const startToken = util.nullThrows(sourceCode.getFirstToken(node), util.NullThrowsReasons.MissingToken('first token', node.type)); | ||
const startToken = (0, util_1.nullThrows)(sourceCode.getFirstToken(node), util_1.NullThrowsReasons.MissingToken('first token', node.type)); | ||
return ['(', '[', '`'].includes(startToken.value); | ||
} | ||
function canFix(node) { | ||
const services = (0, util_1.getParserServices)(context); | ||
const targetNode = node.type === utils_1.AST_NODE_TYPES.ReturnStatement | ||
? node.argument | ||
: node.body; | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, targetNode); | ||
return tsutils.isTypeFlagSet(type, ts.TypeFlags.VoidLike); | ||
} | ||
}, | ||
}); | ||
//# sourceMappingURL=no-confusing-void-expression.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-dupe-class-members'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-dupe-class-members', | ||
@@ -36,3 +13,2 @@ meta: { | ||
description: 'Disallow duplicate class members', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -59,13 +35,19 @@ }, | ||
} | ||
return Object.assign(Object.assign(Object.assign({}, rules), (rules.MethodDefinition | ||
? { | ||
MethodDefinition: wrapMemberDefinitionListener(rules.MethodDefinition), | ||
} | ||
: {})), (rules['MethodDefinition, PropertyDefinition'] | ||
? { | ||
'MethodDefinition, PropertyDefinition': wrapMemberDefinitionListener(rules['MethodDefinition, PropertyDefinition']), | ||
} | ||
: {})); | ||
return { | ||
...rules, | ||
// for ESLint <= v7 | ||
...(rules.MethodDefinition | ||
? { | ||
MethodDefinition: wrapMemberDefinitionListener(rules.MethodDefinition), | ||
} | ||
: {}), | ||
// for ESLint v8 | ||
...(rules['MethodDefinition, PropertyDefinition'] | ||
? { | ||
'MethodDefinition, PropertyDefinition': wrapMemberDefinitionListener(rules['MethodDefinition, PropertyDefinition']), | ||
} | ||
: {}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=no-dupe-class-members.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-duplicate-enum-values', | ||
@@ -34,3 +11,3 @@ meta: { | ||
description: 'Disallow duplicate enum member values', | ||
recommended: 'strict', | ||
recommended: 'recommended', | ||
}, | ||
@@ -37,0 +14,0 @@ hasSuggestions: false, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const astIgnoreKeys = new Set(['range', 'loc', 'parent']); | ||
@@ -58,3 +36,3 @@ const isSameAstNode = (actualNode, expectedNode) => { | ||
}; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-duplicate-type-constituents', | ||
@@ -65,3 +43,3 @@ meta: { | ||
description: 'Disallow duplicate constituents of union or intersection types', | ||
recommended: false, | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -95,3 +73,3 @@ }, | ||
create(context, [{ ignoreIntersections, ignoreUnions }]) { | ||
const parserServices = util.getParserServices(context); | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
@@ -123,3 +101,3 @@ function checkDuplicate(node) { | ||
function reportDuplicate(duplicateConstituent, parentNode) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const beforeTokens = sourceCode.getTokensBefore(duplicateConstituent.duplicated, { filter: token => token.value === '|' || token.value === '&' }); | ||
@@ -155,9 +133,12 @@ const beforeUnionOrIntersectionToken = beforeTokens[beforeTokens.length - 1]; | ||
} | ||
return Object.assign(Object.assign({}, (!ignoreIntersections && { | ||
TSIntersectionType: checkDuplicate, | ||
})), (!ignoreUnions && { | ||
TSUnionType: checkDuplicate, | ||
})); | ||
return { | ||
...(!ignoreIntersections && { | ||
TSIntersectionType: checkDuplicate, | ||
}), | ||
...(!ignoreUnions && { | ||
TSUnionType: checkDuplicate, | ||
}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=no-duplicate-type-constituents.js.map |
@@ -27,5 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-dynamic-delete', | ||
@@ -71,3 +72,3 @@ meta: { | ||
function getTokenRange(property) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return [ | ||
@@ -74,0 +75,0 @@ sourceCode.getTokenBefore(property).range[0], |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-empty-function'); | ||
const schema = util.deepMerge( | ||
const schema = (0, util_1.deepMerge)( | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 | ||
@@ -38,2 +15,3 @@ Array.isArray(baseRule.meta.schema) | ||
items: { | ||
type: 'string', | ||
enum: [ | ||
@@ -59,3 +37,3 @@ 'functions', | ||
}); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-empty-function', | ||
@@ -66,3 +44,3 @@ meta: { | ||
description: 'Disallow empty functions', | ||
recommended: 'error', | ||
recommended: 'stylistic', | ||
extendsBaseRule: true, | ||
@@ -92,3 +70,3 @@ }, | ||
function isBodyEmpty(node) { | ||
return !node.body || node.body.body.length === 0; | ||
return node.body.body.length === 0; | ||
} | ||
@@ -102,4 +80,3 @@ /** | ||
function hasParameterProperties(node) { | ||
var _a; | ||
return (_a = node.params) === null || _a === void 0 ? void 0 : _a.some(param => param.type === utils_1.AST_NODE_TYPES.TSParameterProperty); | ||
return node.params.some(param => param.type === utils_1.AST_NODE_TYPES.TSParameterProperty); | ||
} | ||
@@ -114,3 +91,3 @@ /** | ||
if (isBodyEmpty(node) && | ||
(parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
parent.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
parent.kind === 'constructor') { | ||
@@ -134,5 +111,4 @@ const { accessibility } = parent; | ||
function isAllowedEmptyDecoratedFunctions(node) { | ||
var _a; | ||
if (isAllowedDecoratedFunctions && isBodyEmpty(node)) { | ||
const decorators = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.MethodDefinition | ||
const decorators = node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition | ||
? node.parent.decorators | ||
@@ -145,9 +121,10 @@ : undefined; | ||
function isAllowedEmptyOverrideMethod(node) { | ||
var _a; | ||
return (isAllowedOverrideMethods && | ||
isBodyEmpty(node) && | ||
((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
node.parent.override === true); | ||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
node.parent.override); | ||
} | ||
return Object.assign(Object.assign({}, rules), { FunctionExpression(node) { | ||
return { | ||
...rules, | ||
FunctionExpression(node) { | ||
if (isAllowedEmptyConstructor(node) || | ||
@@ -160,10 +137,5 @@ isAllowedEmptyDecoratedFunctions(node) || | ||
}, | ||
FunctionDeclaration(node) { | ||
if (isAllowedEmptyDecoratedFunctions(node)) { | ||
return; | ||
} | ||
rules.FunctionDeclaration(node); | ||
} }); | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=no-empty-function.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-empty-interface', | ||
@@ -34,3 +13,3 @@ meta: { | ||
description: 'Disallow the declaration of empty interfaces', | ||
recommended: 'error', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -63,5 +42,4 @@ fixable: 'code', | ||
TSInterfaceDeclaration(node) { | ||
var _a, _b; | ||
const sourceCode = context.getSourceCode(); | ||
const filename = context.getFilename(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const filename = (0, eslint_utils_1.getFilename)(context); | ||
if (node.body.body.length !== 0) { | ||
@@ -72,3 +50,3 @@ // interface contains members --> Nothing to report | ||
const extend = node.extends; | ||
if (!extend || extend.length === 0) { | ||
if (extend.length === 0) { | ||
context.report({ | ||
@@ -89,21 +67,26 @@ node: node.id, | ||
}; | ||
const scope = context.getScope(); | ||
const mergedWithClassDeclaration = (_b = (_a = scope.set | ||
.get(node.id.name)) === null || _a === void 0 ? void 0 : _a.defs) === null || _b === void 0 ? void 0 : _b.some(def => def.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration); | ||
const isInAmbientDeclaration = !!(util.isDefinitionFile(filename) && | ||
scope.type === 'tsModule' && | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
const mergedWithClassDeclaration = scope.set | ||
.get(node.id.name) | ||
?.defs.some(def => def.node.type === utils_1.AST_NODE_TYPES.ClassDeclaration); | ||
const isInAmbientDeclaration = !!((0, util_1.isDefinitionFile)(filename) && | ||
scope.type === scope_manager_1.ScopeType.tsModule && | ||
scope.block.declare); | ||
const useAutoFix = !(isInAmbientDeclaration || mergedWithClassDeclaration); | ||
context.report(Object.assign({ node: node.id, messageId: 'noEmptyWithSuper' }, (useAutoFix | ||
? { fix } | ||
: !mergedWithClassDeclaration | ||
? { | ||
suggest: [ | ||
{ | ||
messageId: 'noEmptyWithSuper', | ||
fix, | ||
}, | ||
], | ||
} | ||
: null))); | ||
context.report({ | ||
node: node.id, | ||
messageId: 'noEmptyWithSuper', | ||
...(useAutoFix | ||
? { fix } | ||
: !mergedWithClassDeclaration | ||
? { | ||
suggest: [ | ||
{ | ||
messageId: 'noEmptyWithSuper', | ||
fix, | ||
}, | ||
], | ||
} | ||
: null), | ||
}); | ||
} | ||
@@ -110,0 +93,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-explicit-any', | ||
@@ -34,3 +11,3 @@ meta: { | ||
description: 'Disallow the `any` type', | ||
recommended: 'warn', | ||
recommended: 'recommended', | ||
}, | ||
@@ -76,11 +53,11 @@ fixable: 'code', | ||
return [ | ||
utils_1.AST_NODE_TYPES.ArrowFunctionExpression, | ||
utils_1.AST_NODE_TYPES.FunctionDeclaration, | ||
utils_1.AST_NODE_TYPES.FunctionExpression, | ||
utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression, | ||
utils_1.AST_NODE_TYPES.TSFunctionType, | ||
utils_1.AST_NODE_TYPES.TSConstructorType, | ||
utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration, | ||
utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration, | ||
utils_1.AST_NODE_TYPES.TSMethodSignature, | ||
utils_1.AST_NODE_TYPES.ArrowFunctionExpression, // const x = (...args: any[]) => {}; | ||
utils_1.AST_NODE_TYPES.FunctionDeclaration, // function f(...args: any[]) {} | ||
utils_1.AST_NODE_TYPES.FunctionExpression, // const x = function(...args: any[]) {}; | ||
utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression, // declare class A { f(...args: any[]): unknown; } | ||
utils_1.AST_NODE_TYPES.TSFunctionType, // type T = (...args: any[]) => unknown; | ||
utils_1.AST_NODE_TYPES.TSConstructorType, // type T = new (...args: any[]) => unknown | ||
utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration, // type T = {(...args: any[]): unknown}; | ||
utils_1.AST_NODE_TYPES.TSConstructSignatureDeclaration, // type T = {new (...args: any[]): unknown}; | ||
utils_1.AST_NODE_TYPES.TSMethodSignature, // type T = {f(...args: any[]): unknown}; | ||
utils_1.AST_NODE_TYPES.TSDeclareFunction, // declare function _8(...args: any[]): unknown; | ||
@@ -97,3 +74,2 @@ ].includes(node.type); | ||
return (node.type === utils_1.AST_NODE_TYPES.RestElement && | ||
node.parent !== undefined && | ||
isNodeValidFunction(node.parent)); | ||
@@ -119,3 +95,2 @@ } | ||
return (node.type === utils_1.AST_NODE_TYPES.TSTypeReference && | ||
node.typeName !== undefined && | ||
node.typeName.type === utils_1.AST_NODE_TYPES.Identifier && | ||
@@ -141,4 +116,3 @@ ['Array', 'ReadonlyArray'].includes(node.typeName.name)); | ||
function isGreatGrandparentRestElement(node) { | ||
var _a, _b; | ||
return (((_b = (_a = node === null || node === void 0 ? void 0 : node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent) != null && | ||
return (node.parent?.parent?.parent != null && | ||
isNodeRestElementInFunction(node.parent.parent.parent)); | ||
@@ -153,4 +127,3 @@ } | ||
function isGreatGreatGrandparentRestElement(node) { | ||
var _a, _b, _c; | ||
return (((_c = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent) === null || _c === void 0 ? void 0 : _c.parent) != null && | ||
return (node.parent?.parent?.parent?.parent != null && | ||
isNodeValidTSType(node.parent.parent) && | ||
@@ -194,3 +167,7 @@ isNodeRestElementInFunction(node.parent.parent.parent.parent)); | ||
} | ||
context.report(Object.assign({ node, messageId: 'unexpectedAny' }, fixOrSuggest)); | ||
context.report({ | ||
node, | ||
messageId: 'unexpectedAny', | ||
...fixOrSuggest, | ||
}); | ||
}, | ||
@@ -197,0 +174,0 @@ }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-extra-non-null-assertion', | ||
@@ -33,3 +10,3 @@ meta: { | ||
description: 'Disallow extra non-null assertions', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -36,0 +13,0 @@ fixable: 'code', |
"use strict"; | ||
// any is required to work around manipulating the AST in weird ways | ||
/* eslint-disable @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment */ | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-extra-parens'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-extra-parens', | ||
@@ -38,3 +16,2 @@ meta: { | ||
description: 'Disallow unnecessary parentheses', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -49,2 +26,3 @@ }, | ||
create(context) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const rules = baseRule.create(context); | ||
@@ -54,4 +32,4 @@ function binaryExp(node) { | ||
// makes the rule think it should skip the left or right | ||
const isLeftTypeAssertion = util.isTypeAssertion(node.left); | ||
const isRightTypeAssertion = util.isTypeAssertion(node.right); | ||
const isLeftTypeAssertion = (0, util_1.isTypeAssertion)(node.left); | ||
const isRightTypeAssertion = (0, util_1.isTypeAssertion)(node.right); | ||
if (isLeftTypeAssertion && isRightTypeAssertion) { | ||
@@ -61,6 +39,18 @@ return; // ignore | ||
if (isLeftTypeAssertion) { | ||
return rule(Object.assign(Object.assign({}, node), { left: Object.assign(Object.assign({}, node.left), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rule({ | ||
...node, | ||
left: { | ||
...node.left, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
if (isRightTypeAssertion) { | ||
return rule(Object.assign(Object.assign({}, node), { right: Object.assign(Object.assign({}, node.right), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rule({ | ||
...node, | ||
right: { | ||
...node.right, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -70,14 +60,26 @@ return rule(node); | ||
function callExp(node) { | ||
var _a; | ||
const rule = rules.CallExpression; | ||
if (util.isTypeAssertion(node.callee)) { | ||
if ((0, util_1.isTypeAssertion)(node.callee)) { | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
return rule(Object.assign(Object.assign({}, node), { callee: Object.assign(Object.assign({}, node.callee), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rule({ | ||
...node, | ||
callee: { | ||
...node.callee, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
if (node.arguments.length === 1 && | ||
((_a = node.typeParameters) === null || _a === void 0 ? void 0 : _a.params.some(param => param.type === utils_1.AST_NODE_TYPES.TSImportType || | ||
param.type === utils_1.AST_NODE_TYPES.TSArrayType))) { | ||
return rule(Object.assign(Object.assign({}, node), { arguments: [ | ||
Object.assign(Object.assign({}, node.arguments[0]), { type: utils_1.AST_NODE_TYPES.SequenceExpression }), | ||
] })); | ||
// is there any opening parenthesis in type arguments | ||
sourceCode.getTokenAfter(node.callee, util_1.isOpeningParenToken) !== | ||
sourceCode.getTokenBefore(node.arguments[0], util_1.isOpeningParenToken)) { | ||
return rule({ | ||
...node, | ||
arguments: [ | ||
{ | ||
...node.arguments[0], | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
], | ||
}); | ||
} | ||
@@ -88,5 +90,11 @@ return rule(node); | ||
const rule = rules.UnaryExpression; | ||
if (util.isTypeAssertion(node.argument)) { | ||
if ((0, util_1.isTypeAssertion)(node.argument)) { | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
return rule(Object.assign(Object.assign({}, node), { argument: Object.assign(Object.assign({}, node.argument), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rule({ | ||
...node, | ||
argument: { | ||
...node.argument, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -98,3 +106,3 @@ return rule(node); | ||
ArrowFunctionExpression(node) { | ||
if (!util.isTypeAssertion(node.body)) { | ||
if (!(0, util_1.isTypeAssertion)(node.body)) { | ||
return rules.ArrowFunctionExpression(node); | ||
@@ -105,5 +113,11 @@ } | ||
AwaitExpression(node) { | ||
if (util.isTypeAssertion(node.argument)) { | ||
if ((0, util_1.isTypeAssertion)(node.argument)) { | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
return rules.AwaitExpression(Object.assign(Object.assign({}, node), { argument: Object.assign(Object.assign({}, node.argument), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rules.AwaitExpression({ | ||
...node, | ||
argument: { | ||
...node.argument, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -115,5 +129,10 @@ return rules.AwaitExpression(node); | ||
ClassDeclaration(node) { | ||
var _a; | ||
if (((_a = node.superClass) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSAsExpression) { | ||
return rules.ClassDeclaration(Object.assign(Object.assign({}, node), { superClass: Object.assign(Object.assign({}, node.superClass), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
if (node.superClass?.type === utils_1.AST_NODE_TYPES.TSAsExpression) { | ||
return rules.ClassDeclaration({ | ||
...node, | ||
superClass: { | ||
...node.superClass, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -123,5 +142,10 @@ return rules.ClassDeclaration(node); | ||
ClassExpression(node) { | ||
var _a; | ||
if (((_a = node.superClass) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSAsExpression) { | ||
return rules.ClassExpression(Object.assign(Object.assign({}, node), { superClass: Object.assign(Object.assign({}, node.superClass), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
if (node.superClass?.type === utils_1.AST_NODE_TYPES.TSAsExpression) { | ||
return rules.ClassExpression({ | ||
...node, | ||
superClass: { | ||
...node.superClass, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -132,11 +156,29 @@ return rules.ClassExpression(node); | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
if (util.isTypeAssertion(node.test)) { | ||
return rules.ConditionalExpression(Object.assign(Object.assign({}, node), { test: Object.assign(Object.assign({}, node.test), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
if ((0, util_1.isTypeAssertion)(node.test)) { | ||
return rules.ConditionalExpression({ | ||
...node, | ||
test: { | ||
...node.test, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
if (util.isTypeAssertion(node.consequent)) { | ||
return rules.ConditionalExpression(Object.assign(Object.assign({}, node), { consequent: Object.assign(Object.assign({}, node.consequent), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
if ((0, util_1.isTypeAssertion)(node.consequent)) { | ||
return rules.ConditionalExpression({ | ||
...node, | ||
consequent: { | ||
...node.consequent, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
if (util.isTypeAssertion(node.alternate)) { | ||
if ((0, util_1.isTypeAssertion)(node.alternate)) { | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
return rules.ConditionalExpression(Object.assign(Object.assign({}, node), { alternate: Object.assign(Object.assign({}, node.alternate), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rules.ConditionalExpression({ | ||
...node, | ||
alternate: { | ||
...node.alternate, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -149,10 +191,19 @@ return rules.ConditionalExpression(node); | ||
// make the rule skip the piece by removing it entirely | ||
if (node.init && util.isTypeAssertion(node.init)) { | ||
return rules.ForStatement(Object.assign(Object.assign({}, node), { init: null })); | ||
if (node.init && (0, util_1.isTypeAssertion)(node.init)) { | ||
return rules.ForStatement({ | ||
...node, | ||
init: null, | ||
}); | ||
} | ||
if (node.test && util.isTypeAssertion(node.test)) { | ||
return rules.ForStatement(Object.assign(Object.assign({}, node), { test: null })); | ||
if (node.test && (0, util_1.isTypeAssertion)(node.test)) { | ||
return rules.ForStatement({ | ||
...node, | ||
test: null, | ||
}); | ||
} | ||
if (node.update && util.isTypeAssertion(node.update)) { | ||
return rules.ForStatement(Object.assign(Object.assign({}, node), { update: null })); | ||
if (node.update && (0, util_1.isTypeAssertion)(node.update)) { | ||
return rules.ForStatement({ | ||
...node, | ||
update: null, | ||
}); | ||
} | ||
@@ -162,3 +213,3 @@ return rules.ForStatement(node); | ||
'ForStatement > *.init:exit'(node) { | ||
if (!util.isTypeAssertion(node)) { | ||
if (!(0, util_1.isTypeAssertion)(node)) { | ||
return rules['ForStatement > *.init:exit'](node); | ||
@@ -170,5 +221,11 @@ } | ||
MemberExpression(node) { | ||
if (util.isTypeAssertion(node.object)) { | ||
if ((0, util_1.isTypeAssertion)(node.object)) { | ||
// reduces the precedence of the node so the rule thinks it needs to be wrapped | ||
return rules.MemberExpression(Object.assign(Object.assign({}, node), { object: Object.assign(Object.assign({}, node.object), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rules.MemberExpression({ | ||
...node, | ||
object: { | ||
...node.object, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -182,3 +239,3 @@ return rules.MemberExpression(node); | ||
SpreadElement(node) { | ||
if (!util.isTypeAssertion(node.argument)) { | ||
if (!(0, util_1.isTypeAssertion)(node.argument)) { | ||
return rules.SpreadElement(node); | ||
@@ -188,3 +245,3 @@ } | ||
SwitchCase(node) { | ||
if (node.test && !util.isTypeAssertion(node.test)) { | ||
if (node.test && !(0, util_1.isTypeAssertion)(node.test)) { | ||
return rules.SwitchCase(node); | ||
@@ -195,3 +252,3 @@ } | ||
ThrowStatement(node) { | ||
if (node.argument && !util.isTypeAssertion(node.argument)) { | ||
if (node.argument && !(0, util_1.isTypeAssertion)(node.argument)) { | ||
return rules.ThrowStatement(node); | ||
@@ -206,3 +263,3 @@ } | ||
YieldExpression(node) { | ||
if (node.argument && !util.isTypeAssertion(node.argument)) { | ||
if (node.argument && !(0, util_1.isTypeAssertion)(node.argument)) { | ||
return rules.YieldExpression(node); | ||
@@ -212,5 +269,6 @@ } | ||
}; | ||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition | ||
if (rules.ForInStatement && rules.ForOfStatement) { | ||
overrides.ForInStatement = function (node) { | ||
if (util.isTypeAssertion(node.right)) { | ||
if ((0, util_1.isTypeAssertion)(node.right)) { | ||
// as of 7.20.0 there's no way to skip checking the right of the ForIn | ||
@@ -223,5 +281,12 @@ // so just don't validate it at all | ||
overrides.ForOfStatement = function (node) { | ||
if (util.isTypeAssertion(node.right)) { | ||
if ((0, util_1.isTypeAssertion)(node.right)) { | ||
// makes the rule skip checking of the right | ||
return rules.ForOfStatement(Object.assign(Object.assign({}, node), { type: utils_1.AST_NODE_TYPES.ForOfStatement, right: Object.assign(Object.assign({}, node.right), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rules.ForOfStatement({ | ||
...node, | ||
type: utils_1.AST_NODE_TYPES.ForOfStatement, | ||
right: { | ||
...node.right, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -233,5 +298,12 @@ return rules.ForOfStatement(node); | ||
overrides['ForInStatement, ForOfStatement'] = function (node) { | ||
if (util.isTypeAssertion(node.right)) { | ||
if ((0, util_1.isTypeAssertion)(node.right)) { | ||
// makes the rule skip checking of the right | ||
return rules['ForInStatement, ForOfStatement'](Object.assign(Object.assign({}, node), { type: utils_1.AST_NODE_TYPES.ForOfStatement, right: Object.assign(Object.assign({}, node.right), { type: utils_1.AST_NODE_TYPES.SequenceExpression }) })); | ||
return rules['ForInStatement, ForOfStatement']({ | ||
...node, | ||
type: utils_1.AST_NODE_TYPES.ForOfStatement, | ||
right: { | ||
...node.right, | ||
type: utils_1.AST_NODE_TYPES.SequenceExpression, | ||
}, | ||
}); | ||
} | ||
@@ -238,0 +310,0 @@ return rules['ForInStatement, ForOfStatement'](node); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-extra-semi'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-extra-semi', | ||
@@ -35,3 +12,2 @@ meta: { | ||
description: 'Disallow unnecessary semicolons', | ||
recommended: 'error', | ||
extendsBaseRule: true, | ||
@@ -47,4 +23,5 @@ }, | ||
const rules = baseRule.create(context); | ||
return Object.assign(Object.assign({}, rules), { 'TSAbstractMethodDefinition, TSAbstractPropertyDefinition'(node) { | ||
var _a; | ||
return { | ||
...rules, | ||
'TSAbstractMethodDefinition, TSAbstractPropertyDefinition'(node) { | ||
if (rules.MethodDefinition) { | ||
@@ -60,7 +37,8 @@ // for ESLint <= v7 | ||
// for ESLint >= v8.3.0 | ||
(_a = rules['MethodDefinition, PropertyDefinition, StaticBlock']) === null || _a === void 0 ? void 0 : _a.call(rules, node); | ||
rules['MethodDefinition, PropertyDefinition, StaticBlock']?.(node); | ||
} | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=no-extra-semi.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-extraneous-class', | ||
@@ -77,5 +54,4 @@ meta: { | ||
return !!(allowWithDecorator && | ||
node && | ||
node.decorators && | ||
node.decorators.length); | ||
node?.decorators && | ||
node.decorators.length !== 0); | ||
}; | ||
@@ -85,3 +61,3 @@ return { | ||
const parent = node.parent; | ||
if (!parent || parent.superClass || isAllowWithDecorator(parent)) { | ||
if (parent.superClass || isAllowWithDecorator(parent)) { | ||
return; | ||
@@ -88,0 +64,0 @@ } |
@@ -27,7 +27,10 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
const messageBase = 'Promises must be awaited, end with a call to .catch, or end with a call to .then with a rejection handler.'; | ||
const messageBaseVoid = 'Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler' + | ||
' or be explicitly marked as ignored with the `void` operator.'; | ||
const messageRejectionHandler = 'A rejection handler that is not a function will be ignored.'; | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-floating-promises', | ||
@@ -37,3 +40,3 @@ meta: { | ||
description: 'Require Promise-like statements to be handled appropriately', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -43,7 +46,8 @@ }, | ||
messages: { | ||
floating: 'Promises must be awaited, end with a call to .catch, or end with a call to .then with a rejection handler.', | ||
floating: messageBase, | ||
floatingFixAwait: 'Add await operator.', | ||
floatingVoid: 'Promises must be awaited, end with a call to .catch, end with a call to .then with a rejection handler' + | ||
' or be explicitly marked as ignored with the `void` operator.', | ||
floatingVoid: messageBaseVoid, | ||
floatingFixVoid: 'Add void operator to ignore.', | ||
floatingUselessRejectionHandler: messageBase + ' ' + messageRejectionHandler, | ||
floatingUselessRejectionHandlerVoid: messageBaseVoid + ' ' + messageRejectionHandler, | ||
}, | ||
@@ -59,3 +63,3 @@ schema: [ | ||
ignoreIIFE: { | ||
description: 'Whether to ignore async IIFEs (Immediately Invocated Function Expressions).', | ||
description: 'Whether to ignore async IIFEs (Immediately Invoked Function Expressions).', | ||
type: 'boolean', | ||
@@ -76,4 +80,4 @@ }, | ||
create(context, [options]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
return { | ||
@@ -88,7 +92,10 @@ ExpressionStatement(node) { | ||
} | ||
if (isUnhandledPromise(checker, expression)) { | ||
const { isUnhandled, nonFunctionHandler } = isUnhandledPromise(checker, expression); | ||
if (isUnhandled) { | ||
if (options.ignoreVoid) { | ||
context.report({ | ||
node, | ||
messageId: 'floatingVoid', | ||
messageId: nonFunctionHandler | ||
? 'floatingUselessRejectionHandlerVoid' | ||
: 'floatingVoid', | ||
suggest: [ | ||
@@ -98,12 +105,10 @@ { | ||
fix(fixer) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.expression); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node.expression); | ||
if (isHigherPrecedenceThanUnary(tsNode)) { | ||
return fixer.insertTextBefore(node, 'void '); | ||
} | ||
else { | ||
return [ | ||
fixer.insertTextBefore(node, 'void ('), | ||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'), | ||
]; | ||
} | ||
return [ | ||
fixer.insertTextBefore(node, 'void ('), | ||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'), | ||
]; | ||
}, | ||
@@ -117,3 +122,5 @@ }, | ||
node, | ||
messageId: 'floating', | ||
messageId: nonFunctionHandler | ||
? 'floatingUselessRejectionHandler' | ||
: 'floating', | ||
suggest: [ | ||
@@ -127,12 +134,10 @@ { | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.expression); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node.expression); | ||
if (isHigherPrecedenceThanUnary(tsNode)) { | ||
return fixer.insertTextBefore(node, 'await '); | ||
} | ||
else { | ||
return [ | ||
fixer.insertTextBefore(node, 'await ('), | ||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'), | ||
]; | ||
} | ||
return [ | ||
fixer.insertTextBefore(node, 'await ('), | ||
fixer.insertTextAfterRange([expression.range[1], expression.range[1]], ')'), | ||
]; | ||
}, | ||
@@ -147,6 +152,6 @@ }, | ||
function isHigherPrecedenceThanUnary(node) { | ||
const operator = tsutils.isBinaryExpression(node) | ||
const operator = ts.isBinaryExpression(node) | ||
? node.operatorToken.kind | ||
: ts.SyntaxKind.Unknown; | ||
const nodePrecedence = util.getOperatorPrecedence(node.kind, operator); | ||
const nodePrecedence = (0, util_1.getOperatorPrecedence)(node.kind, operator); | ||
return nodePrecedence > util_1.OperatorPrecedence.Unary; | ||
@@ -158,7 +163,12 @@ } | ||
} | ||
return (node.expression.type === utils_1.AST_NODE_TYPES.CallExpression && | ||
(node.expression.callee.type === | ||
utils_1.AST_NODE_TYPES.ArrowFunctionExpression || | ||
node.expression.callee.type === utils_1.AST_NODE_TYPES.FunctionExpression)); | ||
return (node.expression.callee.type === | ||
utils_1.AST_NODE_TYPES.ArrowFunctionExpression || | ||
node.expression.callee.type === utils_1.AST_NODE_TYPES.FunctionExpression); | ||
} | ||
function isValidRejectionHandler(rejectionHandler) { | ||
return (services.program | ||
.getTypeChecker() | ||
.getTypeAtLocation(services.esTreeNodeToTSNodeMap.get(rejectionHandler)) | ||
.getCallSignatures().length > 0); | ||
} | ||
function isUnhandledPromise(checker, node) { | ||
@@ -170,3 +180,5 @@ // First, check expressions whose resulting types may not be promise-like | ||
// value is promise-like. | ||
return node.expressions.some(item => isUnhandledPromise(checker, item)); | ||
return (node.expressions | ||
.map(item => isUnhandledPromise(checker, item)) | ||
.find(result => result.isUnhandled) ?? { isUnhandled: false }); | ||
} | ||
@@ -181,11 +193,30 @@ if (!options.ignoreVoid && | ||
// Check the type. At this point it can't be unhandled if it isn't a promise | ||
if (!isPromiseLike(checker, parserServices.esTreeNodeToTSNodeMap.get(node))) { | ||
return false; | ||
if (!isPromiseLike(checker, services.esTreeNodeToTSNodeMap.get(node))) { | ||
return { isUnhandled: false }; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { | ||
// If the outer expression is a call, it must be either a `.then()` or | ||
// `.catch()` that handles the promise. | ||
return (!isPromiseCatchCallWithHandler(node) && | ||
!isPromiseThenCallWithRejectionHandler(node) && | ||
!isPromiseFinallyCallWithHandler(node)); | ||
// If the outer expression is a call, a `.catch()` or `.then()` with | ||
// rejection handler handles the promise. | ||
const catchRejectionHandler = getRejectionHandlerFromCatchCall(node); | ||
if (catchRejectionHandler) { | ||
if (isValidRejectionHandler(catchRejectionHandler)) { | ||
return { isUnhandled: false }; | ||
} | ||
return { isUnhandled: true, nonFunctionHandler: true }; | ||
} | ||
const thenRejectionHandler = getRejectionHandlerFromThenCall(node); | ||
if (thenRejectionHandler) { | ||
if (isValidRejectionHandler(thenRejectionHandler)) { | ||
return { isUnhandled: false }; | ||
} | ||
return { isUnhandled: true, nonFunctionHandler: true }; | ||
} | ||
// `x.finally()` is transparent to resolution of the promise, so check `x`. | ||
// ("object" in this context is the `x` in `x.finally()`) | ||
const promiseFinallyObject = getObjectFromFinallyCall(node); | ||
if (promiseFinallyObject) { | ||
return isUnhandledPromise(checker, promiseFinallyObject); | ||
} | ||
// All other cases are unhandled. | ||
return { isUnhandled: true }; | ||
} | ||
@@ -195,4 +226,7 @@ else if (node.type === utils_1.AST_NODE_TYPES.ConditionalExpression) { | ||
// ternary. Check them directly. | ||
return (isUnhandledPromise(checker, node.alternate) || | ||
isUnhandledPromise(checker, node.consequent)); | ||
const alternateResult = isUnhandledPromise(checker, node.alternate); | ||
if (alternateResult.isUnhandled) { | ||
return alternateResult; | ||
} | ||
return isUnhandledPromise(checker, node.consequent); | ||
} | ||
@@ -205,7 +239,10 @@ else if (node.type === utils_1.AST_NODE_TYPES.MemberExpression || | ||
// necessary then/catch call at the end of the chain. | ||
return true; | ||
return { isUnhandled: true }; | ||
} | ||
else if (node.type === utils_1.AST_NODE_TYPES.LogicalExpression) { | ||
return (isUnhandledPromise(checker, node.left) || | ||
isUnhandledPromise(checker, node.right)); | ||
const leftResult = isUnhandledPromise(checker, node.left); | ||
if (leftResult.isUnhandled) { | ||
return leftResult; | ||
} | ||
return isUnhandledPromise(checker, node.right); | ||
} | ||
@@ -215,3 +252,3 @@ // We conservatively return false for all other types of expressions because | ||
// we just can't tell. | ||
return false; | ||
return { isUnhandled: false }; | ||
} | ||
@@ -257,20 +294,27 @@ }, | ||
} | ||
function isPromiseCatchCallWithHandler(expression) { | ||
return (expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
function getRejectionHandlerFromCatchCall(expression) { | ||
if (expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
expression.callee.property.type === utils_1.AST_NODE_TYPES.Identifier && | ||
expression.callee.property.name === 'catch' && | ||
expression.arguments.length >= 1); | ||
expression.arguments.length >= 1) { | ||
return expression.arguments[0]; | ||
} | ||
return undefined; | ||
} | ||
function isPromiseThenCallWithRejectionHandler(expression) { | ||
return (expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
function getRejectionHandlerFromThenCall(expression) { | ||
if (expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
expression.callee.property.type === utils_1.AST_NODE_TYPES.Identifier && | ||
expression.callee.property.name === 'then' && | ||
expression.arguments.length >= 2); | ||
expression.arguments.length >= 2) { | ||
return expression.arguments[1]; | ||
} | ||
return undefined; | ||
} | ||
function isPromiseFinallyCallWithHandler(expression) { | ||
return (expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
function getObjectFromFinallyCall(expression) { | ||
return expression.callee.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
expression.callee.property.type === utils_1.AST_NODE_TYPES.Identifier && | ||
expression.callee.property.name === 'finally' && | ||
expression.arguments.length >= 1); | ||
expression.callee.property.name === 'finally' | ||
? expression.callee.object | ||
: undefined; | ||
} | ||
//# sourceMappingURL=no-floating-promises.js.map |
@@ -27,4 +27,4 @@ "use strict"; | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-for-in-array', | ||
@@ -34,3 +34,3 @@ meta: { | ||
description: 'Disallow iterating over an array with a for-in loop', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -48,7 +48,6 @@ }, | ||
ForInStatement(node) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(checker, originalNode.expression); | ||
if (util.isTypeArrayTypeOrUnionOfArrayTypes(type, checker) || | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node.right); | ||
if ((0, util_1.isTypeArrayTypeOrUnionOfArrayTypes)(type, checker) || | ||
(type.flags & ts.TypeFlags.StringLike) !== 0) { | ||
@@ -55,0 +54,0 @@ context.report({ |
@@ -27,5 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const FUNCTION_CONSTRUCTOR = 'Function'; | ||
@@ -39,3 +40,3 @@ const GLOBAL_CANDIDATES = new Set(['global', 'window', 'globalThis']); | ||
]); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-implied-eval', | ||
@@ -45,3 +46,3 @@ meta: { | ||
description: 'Disallow the use of `eval()`-like methods', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
extendsBaseRule: true, | ||
@@ -59,5 +60,4 @@ requiresTypeChecking: true, | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const program = parserServices.program; | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
function getCalleeName(node) { | ||
@@ -81,5 +81,3 @@ if (node.type === utils_1.AST_NODE_TYPES.Identifier) { | ||
function isFunctionType(node) { | ||
var _a; | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const type = services.getTypeAtLocation(node); | ||
const symbol = type.getSymbol(); | ||
@@ -90,7 +88,8 @@ if (symbol && | ||
} | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison | ||
if (symbol && symbol.escapedName === FUNCTION_CONSTRUCTOR) { | ||
const declarations = (_a = symbol.getDeclarations()) !== null && _a !== void 0 ? _a : []; | ||
const declarations = symbol.getDeclarations() ?? []; | ||
for (const declaration of declarations) { | ||
const sourceFile = declaration.getSourceFile(); | ||
if (program.isSourceFileDefaultLibrary(sourceFile)) { | ||
if (services.program.isSourceFileDefaultLibrary(sourceFile)) { | ||
return true; | ||
@@ -124,10 +123,7 @@ } | ||
function isReferenceToGlobalFunction(calleeName) { | ||
const ref = context | ||
.getScope() | ||
.references.find(ref => ref.identifier.name === calleeName); | ||
const ref = (0, eslint_utils_1.getScope)(context).references.find(ref => ref.identifier.name === calleeName); | ||
// ensure it's the "global" version | ||
return !(ref === null || ref === void 0 ? void 0 : ref.resolved) || ref.resolved.defs.length === 0; | ||
return !ref?.resolved || ref.resolved.defs.length === 0; | ||
} | ||
function checkImpliedEval(node) { | ||
var _a; | ||
const calleeName = getCalleeName(node.callee); | ||
@@ -138,10 +134,9 @@ if (calleeName == null) { | ||
if (calleeName === FUNCTION_CONSTRUCTOR) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node.callee); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const type = services.getTypeAtLocation(node.callee); | ||
const symbol = type.getSymbol(); | ||
if (symbol) { | ||
const declarations = (_a = symbol.getDeclarations()) !== null && _a !== void 0 ? _a : []; | ||
const declarations = symbol.getDeclarations() ?? []; | ||
for (const declaration of declarations) { | ||
const sourceFile = declaration.getSourceFile(); | ||
if (program.isSourceFileDefaultLibrary(sourceFile)) { | ||
if (services.program.isSourceFileDefaultLibrary(sourceFile)) { | ||
context.report({ node, messageId: 'noFunctionConstructor' }); | ||
@@ -148,0 +143,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-import-type-side-effects', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Enforce the use of top-level import type qualifier when an import only has specifiers with inline type qualifiers', | ||
recommended: false, | ||
}, | ||
@@ -45,3 +22,3 @@ fixable: 'code', | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
@@ -66,3 +43,3 @@ 'ImportDeclaration[importKind!="type"]'(node) { | ||
for (const specifier of specifiers) { | ||
const qualifier = util.nullThrows(sourceCode.getFirstToken(specifier, util.isTypeKeyword), util.NullThrowsReasons.MissingToken('type keyword', 'import specifier')); | ||
const qualifier = (0, util_1.nullThrows)(sourceCode.getFirstToken(specifier, util_1.isTypeKeyword), util_1.NullThrowsReasons.MissingToken('type keyword', 'import specifier')); | ||
fixes.push(fixer.removeRange([ | ||
@@ -73,3 +50,3 @@ qualifier.range[0], | ||
} | ||
const importKeyword = util.nullThrows(sourceCode.getFirstToken(node, util.isImportKeyword), util.NullThrowsReasons.MissingToken('import keyword', 'import')); | ||
const importKeyword = (0, util_1.nullThrows)(sourceCode.getFirstToken(node, util_1.isImportKeyword), util_1.NullThrowsReasons.MissingToken('import keyword', 'import')); | ||
fixes.push(fixer.insertTextAfter(importKeyword, ' type')); | ||
@@ -76,0 +53,0 @@ return fixes; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-inferrable-types', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow explicit type declarations for variables or parameters initialized to a number, string, or boolean', | ||
recommended: 'error', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -63,3 +41,3 @@ fixable: 'code', | ||
create(context, [{ ignoreParameters, ignoreProperties }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function isFunctionCall(init, callName) { | ||
@@ -148,3 +126,3 @@ if (init.type === utils_1.AST_NODE_TYPES.ChainExpression) { | ||
function reportInferrableType(node, typeNode, initNode) { | ||
if (!typeNode || !initNode || !typeNode.typeAnnotation) { | ||
if (!typeNode || !initNode) { | ||
return; | ||
@@ -176,15 +154,15 @@ } | ||
function inferrableVariableVisitor(node) { | ||
if (!node.id) { | ||
return; | ||
} | ||
reportInferrableType(node, node.id.typeAnnotation, node.init); | ||
} | ||
function inferrableParameterVisitor(node) { | ||
if (ignoreParameters || !node.params) { | ||
if (ignoreParameters) { | ||
return; | ||
} | ||
node.params.filter(param => param.type === utils_1.AST_NODE_TYPES.AssignmentPattern && | ||
param.left && | ||
param.right).forEach(param => { | ||
reportInferrableType(param, param.left.typeAnnotation, param.right); | ||
node.params.forEach(param => { | ||
if (param.type === utils_1.AST_NODE_TYPES.TSParameterProperty) { | ||
param = param.parameter; | ||
} | ||
if (param.type === utils_1.AST_NODE_TYPES.AssignmentPattern) { | ||
reportInferrableType(param, param.left.typeAnnotation, param.right); | ||
} | ||
}); | ||
@@ -191,0 +169,0 @@ } |
"use strict"; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -14,9 +13,5 @@ const utils_1 = require("@typescript-eslint/utils"); | ||
description: 'Disallow `this` keywords outside of classes or class-like objects', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
}, | ||
// TODO: this rule has only had messages since v7.0 - remove this when we remove support for v6 | ||
messages: (_a = baseRule.meta.messages) !== null && _a !== void 0 ? _a : { | ||
unexpectedThis: "Unexpected 'this'.", | ||
}, | ||
messages: baseRule.meta.messages, | ||
hasSuggestions: baseRule.meta.hasSuggestions, | ||
@@ -43,3 +38,5 @@ schema: baseRule.meta.schema, | ||
const thisIsValidStack = []; | ||
return Object.assign(Object.assign({}, rules), { PropertyDefinition() { | ||
return { | ||
...rules, | ||
PropertyDefinition() { | ||
thisIsValidStack.push(true); | ||
@@ -51,24 +48,20 @@ }, | ||
FunctionDeclaration(node) { | ||
var _a; | ||
thisIsValidStack.push(node.params.some(param => param.type === utils_1.AST_NODE_TYPES.Identifier && param.name === 'this')); | ||
// baseRule's work | ||
(_a = rules.FunctionDeclaration) === null || _a === void 0 ? void 0 : _a.call(rules, node); | ||
rules.FunctionDeclaration?.(node); | ||
}, | ||
'FunctionDeclaration:exit'(node) { | ||
var _a; | ||
thisIsValidStack.pop(); | ||
// baseRule's work | ||
(_a = rules['FunctionDeclaration:exit']) === null || _a === void 0 ? void 0 : _a.call(rules, node); | ||
rules['FunctionDeclaration:exit']?.(node); | ||
}, | ||
FunctionExpression(node) { | ||
var _a; | ||
thisIsValidStack.push(node.params.some(param => param.type === utils_1.AST_NODE_TYPES.Identifier && param.name === 'this')); | ||
// baseRule's work | ||
(_a = rules.FunctionExpression) === null || _a === void 0 ? void 0 : _a.call(rules, node); | ||
rules.FunctionExpression?.(node); | ||
}, | ||
'FunctionExpression:exit'(node) { | ||
var _a; | ||
thisIsValidStack.pop(); | ||
// baseRule's work | ||
(_a = rules['FunctionExpression:exit']) === null || _a === void 0 ? void 0 : _a.call(rules, node); | ||
rules['FunctionExpression:exit']?.(node); | ||
}, | ||
@@ -82,5 +75,6 @@ ThisExpression(node) { | ||
rules.ThisExpression(node); | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=no-invalid-this.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-invalid-void-type', | ||
@@ -54,3 +32,3 @@ meta: { | ||
items: { type: 'string' }, | ||
minLength: 1, | ||
minItems: 1, | ||
}, | ||
@@ -95,8 +73,7 @@ ], | ||
function checkGenericTypeArgument(node) { | ||
var _a, _b; | ||
// only matches T<..., void, ...> | ||
// extra check for precaution | ||
/* istanbul ignore next */ | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) !== utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation || | ||
((_b = node.parent.parent) === null || _b === void 0 ? void 0 : _b.type) !== utils_1.AST_NODE_TYPES.TSTypeReference) { | ||
if (node.parent.type !== utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation || | ||
node.parent.parent.type !== utils_1.AST_NODE_TYPES.TSTypeReference) { | ||
return; | ||
@@ -106,3 +83,3 @@ } | ||
if (Array.isArray(allowInGenericTypeArguments)) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const fullyQualifiedName = sourceCode | ||
@@ -148,19 +125,13 @@ .getText(node.parent.parent.typeName) | ||
function isValidUnionType(node) { | ||
return node.types.every(member => { | ||
var _a, _b; | ||
return validUnionMembers.includes(member.type) || | ||
// allows any T<..., void, ...> here, checked by checkGenericTypeArgument | ||
(member.type === utils_1.AST_NODE_TYPES.TSTypeReference && | ||
((_a = member.typeParameters) === null || _a === void 0 ? void 0 : _a.type) === | ||
utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation && | ||
((_b = member.typeParameters) === null || _b === void 0 ? void 0 : _b.params.map(param => param.type).includes(utils_1.AST_NODE_TYPES.TSVoidKeyword))); | ||
}); | ||
return node.types.every(member => validUnionMembers.includes(member.type) || | ||
// allows any T<..., void, ...> here, checked by checkGenericTypeArgument | ||
(member.type === utils_1.AST_NODE_TYPES.TSTypeReference && | ||
member.typeArguments?.type === | ||
utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation && | ||
member.typeArguments.params | ||
.map(param => param.type) | ||
.includes(utils_1.AST_NODE_TYPES.TSVoidKeyword))); | ||
} | ||
return { | ||
TSVoidKeyword(node) { | ||
var _a, _b; | ||
/* istanbul ignore next */ | ||
if (!((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent)) { | ||
return; | ||
} | ||
// checks T<..., void, ...> against specification of allowInGenericArguments option | ||
@@ -175,3 +146,3 @@ if (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeParameterInstantiation && | ||
node.parent.type === utils_1.AST_NODE_TYPES.TSTypeParameter && | ||
((_b = node.parent.default) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSVoidKeyword) { | ||
node.parent.default?.type === utils_1.AST_NODE_TYPES.TSVoidKeyword) { | ||
checkDefaultVoid(node, node.parent); | ||
@@ -178,0 +149,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-loop-func'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-loop-func', | ||
@@ -36,3 +14,2 @@ meta: { | ||
description: 'Disallow function declarations that contain unsafe references inside loop statements', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -59,3 +36,3 @@ }, | ||
} | ||
const references = context.getScope().through; | ||
const references = (0, eslint_utils_1.getScope)(context).through; | ||
const unsafeRefs = references | ||
@@ -144,7 +121,6 @@ .filter(r => !isSafe(loopNode, r)) | ||
function isSafe(loopNode, reference) { | ||
var _a; | ||
const variable = reference.resolved; | ||
const definition = variable === null || variable === void 0 ? void 0 : variable.defs[0]; | ||
const declaration = definition === null || definition === void 0 ? void 0 : definition.parent; | ||
const kind = (declaration === null || declaration === void 0 ? void 0 : declaration.type) === utils_1.AST_NODE_TYPES.VariableDeclaration | ||
const definition = variable?.defs[0]; | ||
const declaration = definition?.parent; | ||
const kind = declaration?.type === utils_1.AST_NODE_TYPES.VariableDeclaration | ||
? declaration.kind | ||
@@ -190,10 +166,9 @@ : ''; | ||
function isSafeReference(upperRef) { | ||
var _a; | ||
const id = upperRef.identifier; | ||
return (!upperRef.isWrite() || | ||
(((_a = variable === null || variable === void 0 ? void 0 : variable.scope) === null || _a === void 0 ? void 0 : _a.variableScope) === upperRef.from.variableScope && | ||
(variable?.scope.variableScope === upperRef.from.variableScope && | ||
id.range[0] < border)); | ||
} | ||
return (_a = variable === null || variable === void 0 ? void 0 : variable.references.every(isSafeReference)) !== null && _a !== void 0 ? _a : false; | ||
return variable?.references.every(isSafeReference) ?? false; | ||
} | ||
//# sourceMappingURL=no-loop-func.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.maybeGetESLintCoreRule)('no-loss-of-precision'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-loss-of-precision', | ||
@@ -36,8 +12,8 @@ meta: { | ||
description: 'Disallow literal numbers that lose precision', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
extendsBaseRule: true, | ||
}, | ||
hasSuggestions: baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.hasSuggestions, | ||
hasSuggestions: baseRule?.meta.hasSuggestions, | ||
schema: [], | ||
messages: (_a = baseRule === null || baseRule === void 0 ? void 0 : baseRule.meta.messages) !== null && _a !== void 0 ? _a : { noLossOfPrecision: '' }, | ||
messages: baseRule?.meta.messages ?? { noLossOfPrecision: '' }, | ||
}, | ||
@@ -56,3 +32,6 @@ defaultOptions: [], | ||
Literal(node) { | ||
rules.Literal(Object.assign(Object.assign({}, node), { raw: isSeparatedNumeric(node) ? node.raw.replace(/_/g, '') : node.raw })); | ||
rules.Literal({ | ||
...node, | ||
raw: isSeparatedNumeric(node) ? node.raw.replace(/_/g, '') : node.raw, | ||
}); | ||
}, | ||
@@ -59,0 +38,0 @@ }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-magic-numbers'); | ||
// Extend base schema with additional property to ignore TS numeric literal types | ||
const schema = util.deepMerge( | ||
const schema = (0, util_1.deepMerge)( | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument -- https://github.com/microsoft/TypeScript/issues/17002 | ||
@@ -51,3 +28,3 @@ Array.isArray(baseRule.meta.schema) | ||
}); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-magic-numbers', | ||
@@ -58,3 +35,2 @@ meta: { | ||
description: 'Disallow magic numbers', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -80,3 +56,2 @@ }, | ||
Literal(node) { | ||
var _a; | ||
// If it’s not a numeric literal we’re not interested | ||
@@ -115,3 +90,3 @@ if (typeof node.value !== 'number' && typeof node.value !== 'bigint') { | ||
let raw = node.raw; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
// the base rule only shows the operator for negative numbers | ||
@@ -140,4 +115,3 @@ // https://github.com/eslint/eslint/blob/9dfc8501fb1956c90dc11e6377b4cb38a6bea65d/lib/rules/no-magic-numbers.js#L126 | ||
function getLiteralParent(node) { | ||
var _a; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
['-', '+'].includes(node.parent.operator)) { | ||
@@ -155,4 +129,3 @@ return node.parent.parent; | ||
function isGrandparentTSTypeAliasDeclaration(node) { | ||
var _a, _b; | ||
return ((_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration; | ||
return node.parent?.parent?.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration; | ||
} | ||
@@ -166,4 +139,3 @@ /** | ||
function isGrandparentTSUnionType(node) { | ||
var _a, _b; | ||
if (((_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSUnionType) { | ||
if (node.parent?.parent?.type === utils_1.AST_NODE_TYPES.TSUnionType) { | ||
return isGrandparentTSTypeAliasDeclaration(node.parent); | ||
@@ -181,3 +153,3 @@ } | ||
const parent = getLiteralParent(node); | ||
return (parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.TSEnumMember; | ||
return parent?.type === utils_1.AST_NODE_TYPES.TSEnumMember; | ||
} | ||
@@ -191,4 +163,3 @@ /** | ||
function isParentTSLiteralType(node) { | ||
var _a; | ||
return ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSLiteralType; | ||
return node.parent?.type === utils_1.AST_NODE_TYPES.TSLiteralType; | ||
} | ||
@@ -202,5 +173,4 @@ /** | ||
function isTSNumericLiteralType(node) { | ||
var _a; | ||
// For negative numbers, use the parent node | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
if (node.parent?.type === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
node.parent.operator === '-') { | ||
@@ -231,3 +201,3 @@ node = node.parent; | ||
const parent = getLiteralParent(node); | ||
if ((parent === null || parent === void 0 ? void 0 : parent.type) === utils_1.AST_NODE_TYPES.PropertyDefinition && parent.readonly) { | ||
if (parent?.type === utils_1.AST_NODE_TYPES.PropertyDefinition && parent.readonly) { | ||
return true; | ||
@@ -244,3 +214,2 @@ } | ||
function isAncestorTSIndexedAccessType(node) { | ||
var _a, _b, _c; | ||
// Handle unary expressions (eg. -4) | ||
@@ -250,8 +219,8 @@ let ancestor = getLiteralParent(node); | ||
// intersection (eg. 1 & 2) | ||
while (((_a = ancestor === null || ancestor === void 0 ? void 0 : ancestor.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSUnionType || | ||
((_b = ancestor === null || ancestor === void 0 ? void 0 : ancestor.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.TSIntersectionType) { | ||
while (ancestor?.parent?.type === utils_1.AST_NODE_TYPES.TSUnionType || | ||
ancestor?.parent?.type === utils_1.AST_NODE_TYPES.TSIntersectionType) { | ||
ancestor = ancestor.parent; | ||
} | ||
return ((_c = ancestor === null || ancestor === void 0 ? void 0 : ancestor.parent) === null || _c === void 0 ? void 0 : _c.type) === utils_1.AST_NODE_TYPES.TSIndexedAccessType; | ||
return ancestor?.parent?.type === utils_1.AST_NODE_TYPES.TSIndexedAccessType; | ||
} | ||
//# sourceMappingURL=no-magic-numbers.js.map |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-meaningless-void-operator', | ||
@@ -61,5 +62,5 @@ meta: { | ||
create(context, [{ checkNever }]) { | ||
const parserServices = utils_1.ESLintUtils.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = utils_1.ESLintUtils.getParserServices(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
@@ -73,4 +74,3 @@ 'UnaryExpression[operator="void"]'(node) { | ||
}; | ||
const argTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.argument); | ||
const argType = checker.getTypeAtLocation(argTsNode); | ||
const argType = services.getTypeAtLocation(node.argument); | ||
const unionParts = tsutils.unionTypeParts(argType); | ||
@@ -77,0 +77,0 @@ if (unionParts.every(part => part.flags & (ts.TypeFlags.Void | ts.TypeFlags.Undefined))) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-misused-new', | ||
@@ -34,3 +11,3 @@ meta: { | ||
description: 'Enforce valid definition of `new` and `constructor`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -95,4 +72,3 @@ schema: [], | ||
if (node.value.type === utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) { | ||
if (node.parent && | ||
isMatchingParentType(node.parent.parent, node.value.returnType)) { | ||
if (isMatchingParentType(node.parent.parent, node.value.returnType)) { | ||
context.report({ | ||
@@ -99,0 +75,0 @@ node, |
@@ -27,7 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
function parseChecksVoidReturn(checksVoidReturn) { | ||
var _a, _b, _c, _d, _e; | ||
switch (checksVoidReturn) { | ||
@@ -47,11 +46,11 @@ case false: | ||
return { | ||
arguments: (_a = checksVoidReturn.arguments) !== null && _a !== void 0 ? _a : true, | ||
attributes: (_b = checksVoidReturn.attributes) !== null && _b !== void 0 ? _b : true, | ||
properties: (_c = checksVoidReturn.properties) !== null && _c !== void 0 ? _c : true, | ||
returns: (_d = checksVoidReturn.returns) !== null && _d !== void 0 ? _d : true, | ||
variables: (_e = checksVoidReturn.variables) !== null && _e !== void 0 ? _e : true, | ||
arguments: checksVoidReturn.arguments ?? true, | ||
attributes: checksVoidReturn.attributes ?? true, | ||
properties: checksVoidReturn.properties ?? true, | ||
returns: checksVoidReturn.returns ?? true, | ||
variables: checksVoidReturn.variables ?? true, | ||
}; | ||
} | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-misused-promises', | ||
@@ -61,3 +60,3 @@ meta: { | ||
description: 'Disallow Promises in places not designed to handle them', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -77,2 +76,3 @@ }, | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
@@ -114,4 +114,4 @@ checksConditionals: { | ||
create(context, [{ checksConditionals, checksVoidReturn, checksSpreads }]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const checkedNodes = new Set(); | ||
@@ -131,15 +131,22 @@ const conditionalChecks = { | ||
const voidReturnChecks = checksVoidReturn | ||
? Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (checksVoidReturn.arguments && { | ||
CallExpression: checkArguments, | ||
NewExpression: checkArguments, | ||
})), (checksVoidReturn.attributes && { | ||
JSXAttribute: checkJSXAttribute, | ||
})), (checksVoidReturn.properties && { | ||
Property: checkProperty, | ||
})), (checksVoidReturn.returns && { | ||
ReturnStatement: checkReturnStatement, | ||
})), (checksVoidReturn.variables && { | ||
AssignmentExpression: checkAssignment, | ||
VariableDeclarator: checkVariableDeclaration, | ||
})) : {}; | ||
? { | ||
...(checksVoidReturn.arguments && { | ||
CallExpression: checkArguments, | ||
NewExpression: checkArguments, | ||
}), | ||
...(checksVoidReturn.attributes && { | ||
JSXAttribute: checkJSXAttribute, | ||
}), | ||
...(checksVoidReturn.properties && { | ||
Property: checkProperty, | ||
}), | ||
...(checksVoidReturn.returns && { | ||
ReturnStatement: checkReturnStatement, | ||
}), | ||
...(checksVoidReturn.variables && { | ||
AssignmentExpression: checkAssignment, | ||
VariableDeclarator: checkVariableDeclaration, | ||
}), | ||
} | ||
: {}; | ||
const spreadChecks = { | ||
@@ -176,3 +183,3 @@ SpreadElement: checkSpread, | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (isAlwaysThenable(checker, tsNode)) { | ||
@@ -186,3 +193,3 @@ context.report({ | ||
function checkArguments(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
const voidArgs = voidFunctionArguments(checker, tsNode); | ||
@@ -196,3 +203,3 @@ if (voidArgs.size === 0) { | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(argument); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(argument); | ||
if (returnsThenable(checker, tsNode)) { | ||
@@ -207,4 +214,4 @@ context.report({ | ||
function checkAssignment(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const varType = checker.getTypeAtLocation(tsNode.left); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
const varType = services.getTypeAtLocation(node.left); | ||
if (!isVoidReturningFunctionType(checker, tsNode.left, varType)) { | ||
@@ -221,7 +228,7 @@ return; | ||
function checkVariableDeclaration(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (tsNode.initializer === undefined || node.init == null) { | ||
return; | ||
} | ||
const varType = checker.getTypeAtLocation(tsNode.name); | ||
const varType = services.getTypeAtLocation(node.id); | ||
if (!isVoidReturningFunctionType(checker, tsNode.initializer, varType)) { | ||
@@ -238,3 +245,3 @@ return; | ||
function checkProperty(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (ts.isPropertyAssignment(tsNode)) { | ||
@@ -298,3 +305,3 @@ const contextualType = checker.getContextualType(tsNode.initializer); | ||
function checkReturnStatement(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (tsNode.expression === undefined || node.argument == null) { | ||
@@ -318,4 +325,4 @@ return; | ||
} | ||
const expressionContainer = parserServices.esTreeNodeToTSNodeMap.get(node.value); | ||
const expression = parserServices.esTreeNodeToTSNodeMap.get(node.value.expression); | ||
const expressionContainer = services.esTreeNodeToTSNodeMap.get(node.value); | ||
const expression = services.esTreeNodeToTSNodeMap.get(node.value.expression); | ||
const contextualType = checker.getContextualType(expressionContainer); | ||
@@ -332,3 +339,3 @@ if (contextualType !== undefined && | ||
function checkSpread(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (isSometimesThenable(checker, tsNode.expression)) { | ||
@@ -341,3 +348,7 @@ context.report({ | ||
} | ||
return Object.assign(Object.assign(Object.assign({}, (checksConditionals ? conditionalChecks : {})), (checksVoidReturn ? voidReturnChecks : {})), (checksSpreads ? spreadChecks : {})); | ||
return { | ||
...(checksConditionals ? conditionalChecks : {}), | ||
...(checksVoidReturn ? voidReturnChecks : {}), | ||
...(checksSpreads ? spreadChecks : {}), | ||
}; | ||
}, | ||
@@ -452,3 +463,3 @@ }); | ||
// 'param: MaybeVoidFunction' | ||
type = util.getTypeArguments(type, checker)[0]; | ||
type = checker.getTypeArguments(type)[0]; | ||
for (let i = index; i < node.arguments.length; i++) { | ||
@@ -461,3 +472,3 @@ checkThenableOrVoidArgument(checker, node, type, i, thenableReturnIndices, voidReturnIndices); | ||
// add the index of the second tuple parameter to 'voidReturnIndices' | ||
const typeArgs = util.getTypeArguments(type, checker); | ||
const typeArgs = checker.getTypeArguments(type); | ||
for (let i = index; i < node.arguments.length && i - index < typeArgs.length; i++) { | ||
@@ -515,3 +526,3 @@ checkThenableOrVoidArgument(checker, node, typeArgs[i - index], i, thenableReturnIndices, voidReturnIndices); | ||
} | ||
hadVoidReturn || (hadVoidReturn = tsutils.isTypeFlagSet(returnType, ts.TypeFlags.Void)); | ||
hadVoidReturn ||= tsutils.isTypeFlagSet(returnType, ts.TypeFlags.Void); | ||
} | ||
@@ -518,0 +529,0 @@ } |
@@ -28,5 +28,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
var AllowedType; | ||
@@ -38,3 +39,3 @@ (function (AllowedType) { | ||
})(AllowedType || (AllowedType = {})); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-mixed-enums', | ||
@@ -55,6 +56,5 @@ meta: { | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const typeChecker = parserServices.program.getTypeChecker(); | ||
function collectNodeDefinitions(node) { | ||
var _a, _b, _c, _d, _e; | ||
const { name } = node.id; | ||
@@ -65,4 +65,4 @@ const found = { | ||
}; | ||
let scope = context.getScope(); | ||
for (const definition of (_c = (_b = (_a = scope.upper) === null || _a === void 0 ? void 0 : _a.set.get(name)) === null || _b === void 0 ? void 0 : _b.defs) !== null && _c !== void 0 ? _c : []) { | ||
let scope = (0, eslint_utils_1.getScope)(context); | ||
for (const definition of scope.upper?.set.get(name)?.defs ?? []) { | ||
if (definition.node.type === utils_1.AST_NODE_TYPES.TSEnumDeclaration && | ||
@@ -76,3 +76,3 @@ definition.node.range[0] < node.range[0] && | ||
while (scope) { | ||
(_e = (_d = scope.set.get(name)) === null || _d === void 0 ? void 0 : _d.defs) === null || _e === void 0 ? void 0 : _e.forEach(definition => { | ||
scope.set.get(name)?.defs.forEach(definition => { | ||
if (definition.type === scope_manager_1.DefinitionType.ImportBinding) { | ||
@@ -92,5 +92,4 @@ found.imports.push(definition.node); | ||
function getTypeFromImported(imported) { | ||
var _a; | ||
const type = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(imported)); | ||
const valueDeclaration = (_a = type.getSymbol()) === null || _a === void 0 ? void 0 : _a.valueDeclaration; | ||
const valueDeclaration = type.getSymbol()?.valueDeclaration; | ||
if (!valueDeclaration || | ||
@@ -173,3 +172,2 @@ !ts.isEnumDeclaration(valueDeclaration) || | ||
TSEnumDeclaration(node) { | ||
var _a; | ||
if (!node.members.length) { | ||
@@ -188,9 +186,8 @@ return; | ||
if (currentType === AllowedType.Number) { | ||
desiredType !== null && desiredType !== void 0 ? desiredType : (desiredType = currentType); | ||
desiredType ??= currentType; | ||
} | ||
if (currentType !== desiredType && | ||
(currentType !== undefined || desiredType === AllowedType.String)) { | ||
if (currentType !== desiredType) { | ||
context.report({ | ||
messageId: 'mixed', | ||
node: (_a = member.initializer) !== null && _a !== void 0 ? _a : member, | ||
node: member.initializer ?? member, | ||
}); | ||
@@ -197,0 +194,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-namespace', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow TypeScript namespaces', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -64,6 +42,5 @@ messages: { | ||
create(context, [{ allowDeclarations, allowDefinitionFiles }]) { | ||
const filename = context.getFilename(); | ||
const filename = (0, eslint_utils_1.getFilename)(context); | ||
function isDeclaration(node) { | ||
if (node.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration && | ||
node.declare === true) { | ||
if (node.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration && node.declare) { | ||
return true; | ||
@@ -74,6 +51,5 @@ } | ||
return { | ||
"TSModuleDeclaration[global!=true][id.type='Identifier']"(node) { | ||
if ((node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration) || | ||
(allowDefinitionFiles && util.isDefinitionFile(filename)) || | ||
"TSModuleDeclaration[global!=true][id.type!='Literal']"(node) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration || | ||
(allowDefinitionFiles && (0, util_1.isDefinitionFile)(filename)) || | ||
(allowDeclarations && isDeclaration(node))) { | ||
@@ -80,0 +56,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
function hasAssignmentBeforeNode(variable, node) { | ||
@@ -38,5 +16,5 @@ return (variable.references.some(ref => ref.isWrite() && ref.identifier.range[1] < node.range[1]) || | ||
const variableDeclarator = definition.node; | ||
return (variableDeclarator.definite === true || variableDeclarator.init != null); | ||
return variableDeclarator.definite || variableDeclarator.init != null; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-non-null-asserted-nullish-coalescing', | ||
@@ -61,3 +39,3 @@ meta: { | ||
if (node.expression.type === utils_1.TSESTree.AST_NODE_TYPES.Identifier) { | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
const identifier = node.expression; | ||
@@ -69,3 +47,3 @@ const variable = utils_1.ASTUtils.findVariable(scope, identifier.name); | ||
} | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
context.report({ | ||
@@ -91,3 +69,3 @@ node, | ||
fix(fixer) { | ||
const exclamationMark = util.nullThrows(sourceCode.getLastToken(node, utils_1.ASTUtils.isNonNullAssertionPunctuator), util.NullThrowsReasons.MissingToken('!', 'Non-null Assertion')); | ||
const exclamationMark = (0, util_1.nullThrows)(sourceCode.getLastToken(node, utils_1.ASTUtils.isNonNullAssertionPunctuator), util_1.NullThrowsReasons.MissingToken('!', 'Non-null Assertion')); | ||
return fixer.remove(exclamationMark); | ||
@@ -94,0 +72,0 @@ }, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const semver = __importStar(require("semver")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const is3dot9 = semver.satisfies(ts.version, `>= 3.9.0 || >= 3.9.1-rc || >= 3.9.0-beta`, { | ||
includePrerelease: true, | ||
}); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-non-null-asserted-optional-chain', | ||
@@ -39,3 +10,3 @@ meta: { | ||
description: 'Disallow non-null assertions after an optional chain expression', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -51,11 +22,3 @@ hasSuggestions: true, | ||
create(context) { | ||
// TS3.9 made a breaking change to how non-null works with optional chains. | ||
// Pre-3.9, `x?.y!.z` means `(x?.y).z` - i.e. it essentially scrubbed the optionality from the chain | ||
// Post-3.9, `x?.y!.z` means `x?.y!.z` - i.e. it just asserts that the property `y` is non-null, not the result of `x?.y`. | ||
// This means that for > 3.9, x?.y!.z is valid! | ||
// | ||
// NOTE: these cases are still invalid for 3.9: | ||
// - x?.y.z! | ||
// - (x?.y)!.z | ||
const baseSelectors = { | ||
return { | ||
// non-nulling a wrapped chain will scrub all nulls introduced by the chain | ||
@@ -103,50 +66,4 @@ // (x?.y)! | ||
}; | ||
if (is3dot9) { | ||
return baseSelectors; | ||
} | ||
return Object.assign(Object.assign({}, baseSelectors), { [[ | ||
// > :not(ChainExpression) because that case is handled by a previous selector | ||
'MemberExpression > TSNonNullExpression.object > :not(ChainExpression)', | ||
'CallExpression > TSNonNullExpression.callee > :not(ChainExpression)', | ||
].join(', ')](child) { | ||
// selector guarantees this assertion | ||
const node = child.parent; | ||
let current = child; | ||
while (current) { | ||
switch (current.type) { | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
if (current.optional) { | ||
// found an optional chain! stop traversing | ||
break; | ||
} | ||
current = current.object; | ||
continue; | ||
case utils_1.AST_NODE_TYPES.CallExpression: | ||
if (current.optional) { | ||
// found an optional chain! stop traversing | ||
break; | ||
} | ||
current = current.callee; | ||
continue; | ||
default: | ||
// something that's not a ChainElement, which means this is not an optional chain we want to check | ||
return; | ||
} | ||
} | ||
context.report({ | ||
node, | ||
messageId: 'noNonNullOptionalChain', | ||
// use a suggestion instead of a fixer, because this can obviously break type checks | ||
suggest: [ | ||
{ | ||
messageId: 'suggestRemovingNonNull', | ||
fix(fixer) { | ||
return fixer.removeRange([node.range[1] - 1, node.range[1]]); | ||
}, | ||
}, | ||
], | ||
}); | ||
} }); | ||
}, | ||
}); | ||
//# sourceMappingURL=no-non-null-asserted-optional-chain.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-non-null-assertion', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow non-null assertions using the `!` postfix operator', | ||
recommended: 'warn', | ||
recommended: 'strict', | ||
}, | ||
@@ -46,10 +24,9 @@ hasSuggestions: true, | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
TSNonNullExpression(node) { | ||
var _a, _b; | ||
const suggest = []; | ||
function convertTokenToOptional(replacement) { | ||
return (fixer) => { | ||
const operator = sourceCode.getTokenAfter(node.expression, util.isNonNullAssertionPunctuator); | ||
const operator = sourceCode.getTokenAfter(node.expression, util_1.isNonNullAssertionPunctuator); | ||
if (operator) { | ||
@@ -63,3 +40,3 @@ return fixer.replaceText(operator, replacement); | ||
return (fixer) => { | ||
const operator = sourceCode.getTokenAfter(node.expression, util.isNonNullAssertionPunctuator); | ||
const operator = sourceCode.getTokenAfter(node.expression, util_1.isNonNullAssertionPunctuator); | ||
if (operator) { | ||
@@ -71,3 +48,3 @@ return fixer.remove(operator); | ||
} | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.MemberExpression && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
node.parent.object === node) { | ||
@@ -107,3 +84,3 @@ if (!node.parent.optional) { | ||
} | ||
else if (((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.CallExpression && | ||
else if (node.parent.type === utils_1.AST_NODE_TYPES.CallExpression && | ||
node.parent.callee === node) { | ||
@@ -110,0 +87,0 @@ if (!node.parent.optional) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-redeclare', | ||
@@ -34,3 +13,2 @@ meta: { | ||
description: 'Disallow variable redeclaration', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -65,3 +43,3 @@ }, | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const CLASS_DECLARATION_MERGE_NODES = new Set([ | ||
@@ -81,3 +59,3 @@ utils_1.AST_NODE_TYPES.TSInterfaceDeclaration, | ||
function* iterateDeclarations(variable) { | ||
if ((options === null || options === void 0 ? void 0 : options.builtinGlobals) && | ||
if (options.builtinGlobals && | ||
'eslintImplicitGlobalSetting' in variable && | ||
@@ -94,3 +72,3 @@ (variable.eslintImplicitGlobalSetting === 'readonly' || | ||
node: comment, | ||
loc: util.getNameLocationInGlobalDirectiveComment(sourceCode, comment, variable.name), | ||
loc: (0, util_1.getNameLocationInGlobalDirectiveComment)(sourceCode, comment, variable.name), | ||
}; | ||
@@ -195,3 +173,3 @@ } | ||
function checkForBlock(node) { | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
/* | ||
@@ -207,6 +185,6 @@ * In ES5, some node type such as `BlockStatement` doesn't have that scope. | ||
Program() { | ||
const scope = context.getScope(); | ||
const scope = (0, eslint_utils_1.getScope)(context); | ||
findVariablesInScope(scope); | ||
// Node.js or ES modules has a special scope. | ||
if (scope.type === 'global' && | ||
if (scope.type === scope_manager_1.ScopeType.global && | ||
scope.childScopes[0] && | ||
@@ -213,0 +191,0 @@ // The special scope's block is the Program node. |
@@ -27,5 +27,5 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const literalToPrimitiveTypeFlags = { | ||
@@ -85,24 +85,28 @@ [ts.TypeFlags.BigIntLiteral]: ts.TypeFlags.BigInt, | ||
} | ||
if (util.isTypeBigIntLiteralType(type)) { | ||
if ((0, util_1.isTypeBigIntLiteralType)(type)) { | ||
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`; | ||
} | ||
if (type.isLiteral()) { | ||
// eslint-disable-next-line @typescript-eslint/no-base-to-string | ||
return type.value.toString(); | ||
} | ||
if (util.isTypeAnyType(type)) { | ||
if ((0, util_1.isTypeAnyType)(type)) { | ||
return 'any'; | ||
} | ||
if (util.isTypeNeverType(type)) { | ||
if ((0, util_1.isTypeNeverType)(type)) { | ||
return 'never'; | ||
} | ||
if (util.isTypeUnknownType(type)) { | ||
if ((0, util_1.isTypeUnknownType)(type)) { | ||
return 'unknown'; | ||
} | ||
if (util.isTypeTemplateLiteralType(type)) { | ||
if ((0, util_1.isTypeTemplateLiteralType)(type)) { | ||
return 'template literal type'; | ||
} | ||
if (tsutils.isBooleanLiteralType(type, true)) { | ||
if ((0, util_1.isTypeBigIntLiteralType)(type)) { | ||
return `${type.value.negative ? '-' : ''}${type.value.base10Value}n`; | ||
} | ||
if (tsutils.isTrueLiteralType(type)) { | ||
return 'true'; | ||
} | ||
if (tsutils.isBooleanLiteralType(type, false)) { | ||
if (tsutils.isFalseLiteralType(type)) { | ||
return 'false'; | ||
@@ -144,7 +148,4 @@ } | ||
function isNodeInsideReturnType(node) { | ||
var _a; | ||
return !!(((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSTypeAnnotation && | ||
node.parent.parent && | ||
(util.isFunctionType(node.parent.parent) || | ||
util.isFunction(node.parent.parent))); | ||
return !!(node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAnnotation && | ||
((0, util_1.isFunctionType)(node.parent.parent) || (0, util_1.isFunction)(node.parent.parent))); | ||
} | ||
@@ -157,8 +158,8 @@ /** | ||
type.types.length === 2 && | ||
tsutils.isBooleanLiteralType(type.types[0], false) && | ||
tsutils.isBooleanLiteralType(type.types[1], true) | ||
tsutils.isFalseLiteralType(type.types[0]) && | ||
tsutils.isTrueLiteralType(type.types[1]) | ||
? [type] | ||
: tsutils.unionTypeParts(type); | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-redundant-type-constituents', | ||
@@ -168,3 +169,3 @@ meta: { | ||
description: 'Disallow members of unions and intersections that do nothing or override type information', | ||
recommended: false, | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -183,3 +184,3 @@ }, | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const typesCache = new Map(); | ||
@@ -209,5 +210,3 @@ function getTypeNodeTypePartFlags(typeNode) { | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(typeNode); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const nodeType = checker.getTypeAtLocation(tsNode); | ||
const nodeType = services.getTypeAtLocation(typeNode); | ||
const typeParts = unionTypePartsUnlessBoolean(nodeType); | ||
@@ -364,3 +363,3 @@ return typeParts.map(typePart => ({ | ||
for (const [typeNode, typeFlagsWithText] of overriddenTypeNodes) { | ||
const grouped = util.arrayGroupByToMap(typeFlagsWithText, pair => pair.primitiveTypeFlag); | ||
const grouped = (0, util_1.arrayGroupByToMap)(typeFlagsWithText, pair => pair.primitiveTypeFlag); | ||
for (const [primitiveTypeFlag, pairs] of grouped) { | ||
@@ -367,0 +366,0 @@ context.report({ |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-require-imports', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Disallow invocation of `require()`', | ||
recommended: false, | ||
}, | ||
@@ -46,6 +23,6 @@ schema: [], | ||
'CallExpression[callee.name="require"]'(node) { | ||
const variable = utils_1.ASTUtils.findVariable(context.getScope(), 'require'); | ||
const variable = utils_1.ASTUtils.findVariable((0, eslint_utils_1.getScope)(context), 'require'); | ||
// ignore non-global require usage as it's something user-land custom instead | ||
// of the commonjs standard | ||
if (!(variable === null || variable === void 0 ? void 0 : variable.identifiers.length)) { | ||
if (!variable?.identifiers.length) { | ||
context.report({ | ||
@@ -52,0 +29,0 @@ node, |
@@ -6,2 +6,3 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const ignore_1 = __importDefault(require("ignore")); | ||
@@ -11,41 +12,85 @@ const util_1 = require("../util"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-restricted-imports'); | ||
// In some versions of eslint, the base rule has a completely incompatible schema | ||
// This helper function is to safely try to get parts of the schema. If it's not | ||
// possible, we'll fallback to less strict checks. | ||
const tryAccess = (getter, fallback) => { | ||
try { | ||
return getter(); | ||
} | ||
catch { | ||
return fallback; | ||
} | ||
}; | ||
const baseSchema = baseRule.meta.schema; | ||
const allowTypeImportsOptionSchema = { | ||
allowTypeImports: { | ||
type: 'boolean', | ||
default: false, | ||
description: 'Disallow value imports, but allow type-only imports.', | ||
}, | ||
}; | ||
const schemaForMergeArrayOfStringsOrObjects = { | ||
const arrayOfStringsOrObjects = { | ||
type: 'array', | ||
items: { | ||
anyOf: [ | ||
{}, | ||
{ type: 'string' }, | ||
{ | ||
properties: allowTypeImportsOptionSchema, | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1] | ||
.properties, undefined), | ||
...allowTypeImportsOptionSchema, | ||
}, | ||
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.paths.items.anyOf[1] | ||
.required, undefined), | ||
}, | ||
], | ||
}, | ||
uniqueItems: true, | ||
}; | ||
const schemaForMergeArrayOfStringsOrObjectPatterns = { | ||
const arrayOfStringsOrObjectPatterns = { | ||
anyOf: [ | ||
{}, | ||
{ | ||
type: 'array', | ||
items: { | ||
properties: allowTypeImportsOptionSchema, | ||
type: 'string', | ||
}, | ||
uniqueItems: true, | ||
}, | ||
], | ||
}; | ||
const schema = (0, util_1.deepMerge)(Object.assign({}, baseRule.meta.schema), { | ||
anyOf: [ | ||
schemaForMergeArrayOfStringsOrObjects, | ||
{ | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
paths: schemaForMergeArrayOfStringsOrObjects, | ||
patterns: schemaForMergeArrayOfStringsOrObjectPatterns, | ||
...tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items | ||
.properties, undefined), | ||
...allowTypeImportsOptionSchema, | ||
}, | ||
required: tryAccess(() => baseSchema.anyOf[1].items[0].properties.patterns.anyOf[1].items | ||
.required, []), | ||
}, | ||
uniqueItems: true, | ||
}, | ||
], | ||
}); | ||
}; | ||
const schema = { | ||
anyOf: [ | ||
arrayOfStringsOrObjects, | ||
{ | ||
type: 'array', | ||
items: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
paths: arrayOfStringsOrObjects, | ||
patterns: arrayOfStringsOrObjectPatterns, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
additionalItems: false, | ||
}, | ||
], | ||
}; | ||
function isObjectOfPaths(obj) { | ||
@@ -87,3 +132,2 @@ return Object.prototype.hasOwnProperty.call(obj, 'paths'); | ||
description: 'Disallow specified modules when loaded by `import`', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -130,17 +174,45 @@ }, | ||
} | ||
function checkImportNode(node) { | ||
if (node.importKind === 'type' || | ||
(node.specifiers.length > 0 && | ||
node.specifiers.every(specifier => specifier.type === utils_1.AST_NODE_TYPES.ImportSpecifier && | ||
specifier.importKind === 'type'))) { | ||
const importSource = node.source.value.trim(); | ||
if (!isAllowedTypeImportPath(importSource) && | ||
!isAllowedTypeImportPattern(importSource)) { | ||
return rules.ImportDeclaration(node); | ||
} | ||
} | ||
else { | ||
return rules.ImportDeclaration(node); | ||
} | ||
} | ||
return { | ||
ImportDeclaration(node) { | ||
if (node.importKind === 'type') { | ||
const importSource = node.source.value.trim(); | ||
if (!isAllowedTypeImportPath(importSource) && | ||
!isAllowedTypeImportPattern(importSource)) { | ||
return rules.ImportDeclaration(node); | ||
} | ||
TSImportEqualsDeclaration(node) { | ||
if (node.moduleReference.type === | ||
utils_1.AST_NODE_TYPES.TSExternalModuleReference && | ||
node.moduleReference.expression.type === utils_1.AST_NODE_TYPES.Literal && | ||
typeof node.moduleReference.expression.value === 'string') { | ||
const synthesizedImport = { | ||
...node, | ||
type: utils_1.AST_NODE_TYPES.ImportDeclaration, | ||
source: node.moduleReference.expression, | ||
assertions: [], | ||
attributes: [], | ||
specifiers: [ | ||
{ | ||
...node.id, | ||
type: utils_1.AST_NODE_TYPES.ImportDefaultSpecifier, | ||
local: node.id, | ||
}, | ||
], | ||
}; | ||
return checkImportNode(synthesizedImport); | ||
} | ||
else { | ||
return rules.ImportDeclaration(node); | ||
} | ||
}, | ||
ImportDeclaration: checkImportNode, | ||
'ExportNamedDeclaration[source]'(node) { | ||
if (node.exportKind === 'type') { | ||
if (node.exportKind === 'type' || | ||
(node.specifiers.length > 0 && | ||
node.specifiers.every(specifier => specifier.exportKind === 'type'))) { | ||
const importSource = node.source.value.trim(); | ||
@@ -147,0 +219,0 @@ if (!isAllowedTypeImportPath(importSource) && |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const allowedFunctionVariableDefTypes = new Set([ | ||
@@ -34,3 +12,3 @@ utils_1.AST_NODE_TYPES.TSCallSignatureDeclaration, | ||
]); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-shadow', | ||
@@ -41,3 +19,2 @@ meta: { | ||
description: 'Disallow variable declarations from shadowing variables declared in the outer scope', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -53,2 +30,3 @@ }, | ||
hoist: { | ||
type: 'string', | ||
enum: ['all', 'functions', 'never'], | ||
@@ -106,3 +84,3 @@ }, | ||
function isTypeImport(definition) { | ||
return ((definition === null || definition === void 0 ? void 0 : definition.type) === scope_manager_1.DefinitionType.ImportBinding && | ||
return (definition?.type === scope_manager_1.DefinitionType.ImportBinding && | ||
(definition.parent.importKind === 'type' || | ||
@@ -120,3 +98,3 @@ (definition.node.type === utils_1.AST_NODE_TYPES.ImportSpecifier && | ||
} | ||
const [firstDefinition] = shadowed.defs; | ||
const firstDefinition = shadowed.defs.at(0); | ||
const isShadowedValue = !('isValueVariable' in shadowed) || | ||
@@ -153,17 +131,16 @@ !firstDefinition || | ||
const typeParameter = variable.identifiers[0].parent; | ||
if ((typeParameter === null || typeParameter === void 0 ? void 0 : typeParameter.type) !== utils_1.AST_NODE_TYPES.TSTypeParameter) { | ||
if (typeParameter.type !== utils_1.AST_NODE_TYPES.TSTypeParameter) { | ||
return false; | ||
} | ||
const typeParameterDecl = typeParameter.parent; | ||
if ((typeParameterDecl === null || typeParameterDecl === void 0 ? void 0 : typeParameterDecl.type) !== utils_1.AST_NODE_TYPES.TSTypeParameterDeclaration) { | ||
if (typeParameterDecl.type !== utils_1.AST_NODE_TYPES.TSTypeParameterDeclaration) { | ||
return false; | ||
} | ||
const functionExpr = typeParameterDecl.parent; | ||
if (!functionExpr || | ||
(functionExpr.type !== utils_1.AST_NODE_TYPES.FunctionExpression && | ||
functionExpr.type !== utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression)) { | ||
if (functionExpr.type !== utils_1.AST_NODE_TYPES.FunctionExpression && | ||
functionExpr.type !== utils_1.AST_NODE_TYPES.TSEmptyBodyFunctionExpression) { | ||
return false; | ||
} | ||
const methodDefinition = functionExpr.parent; | ||
if ((methodDefinition === null || methodDefinition === void 0 ? void 0 : methodDefinition.type) !== utils_1.AST_NODE_TYPES.MethodDefinition) { | ||
if (methodDefinition.type !== utils_1.AST_NODE_TYPES.MethodDefinition) { | ||
return false; | ||
@@ -173,3 +150,3 @@ } | ||
} | ||
function isGenericOfClassDecl(variable) { | ||
function isGenericOfClass(variable) { | ||
if (!('isTypeVariable' in variable)) { | ||
@@ -186,14 +163,15 @@ // this shouldn't happen... | ||
const typeParameter = variable.identifiers[0].parent; | ||
if ((typeParameter === null || typeParameter === void 0 ? void 0 : typeParameter.type) !== utils_1.AST_NODE_TYPES.TSTypeParameter) { | ||
if (typeParameter.type !== utils_1.AST_NODE_TYPES.TSTypeParameter) { | ||
return false; | ||
} | ||
const typeParameterDecl = typeParameter.parent; | ||
if ((typeParameterDecl === null || typeParameterDecl === void 0 ? void 0 : typeParameterDecl.type) !== utils_1.AST_NODE_TYPES.TSTypeParameterDeclaration) { | ||
if (typeParameterDecl.type !== utils_1.AST_NODE_TYPES.TSTypeParameterDeclaration) { | ||
return false; | ||
} | ||
const classDecl = typeParameterDecl.parent; | ||
return (classDecl === null || classDecl === void 0 ? void 0 : classDecl.type) === utils_1.AST_NODE_TYPES.ClassDeclaration; | ||
return (classDecl.type === utils_1.AST_NODE_TYPES.ClassDeclaration || | ||
classDecl.type === utils_1.AST_NODE_TYPES.ClassExpression); | ||
} | ||
function isGenericOfAStaticMethodShadow(variable, shadowed) { | ||
return (isGenericOfStaticMethod(variable) && isGenericOfClassDecl(shadowed)); | ||
return isGenericOfStaticMethod(variable) && isGenericOfClass(shadowed); | ||
} | ||
@@ -205,3 +183,2 @@ function isImportDeclaration(definition) { | ||
return (scope.type === scope_manager_1.ScopeType.tsModule && | ||
scope.block.type === utils_1.AST_NODE_TYPES.TSModuleDeclaration && | ||
scope.block.id.type === utils_1.AST_NODE_TYPES.Literal && | ||
@@ -211,3 +188,2 @@ scope.block.id.value === name); | ||
function isExternalDeclarationMerging(scope, variable, shadowed) { | ||
var _a; | ||
const [firstDefinition] = shadowed.defs; | ||
@@ -219,3 +195,3 @@ const [secondDefinition] = variable.defs; | ||
secondDefinition.node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration && | ||
((_a = secondDefinition.node.parent) === null || _a === void 0 ? void 0 : _a.type) === | ||
secondDefinition.node.parent.type === | ||
utils_1.AST_NODE_TYPES.ExportNamedDeclaration); | ||
@@ -229,3 +205,3 @@ } | ||
function isAllowed(variable) { | ||
return options.allow.indexOf(variable.name) !== -1; | ||
return options.allow.includes(variable.name); | ||
} | ||
@@ -287,3 +263,3 @@ /** | ||
const upper = scope.upper; | ||
if ((upper === null || upper === void 0 ? void 0 : upper.type) === 'function-expression-name') { | ||
if (upper?.type === scope_manager_1.ScopeType.functionExpressionName) { | ||
return upper.upper; | ||
@@ -300,4 +276,3 @@ } | ||
function isInitPatternNode(variable, shadowedVariable) { | ||
var _a, _b, _c, _d; | ||
const outerDef = shadowedVariable.defs[0]; | ||
const outerDef = shadowedVariable.defs.at(0); | ||
if (!outerDef) { | ||
@@ -326,4 +301,4 @@ return false; | ||
} | ||
if ((((_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ForInStatement || | ||
((_d = (_c = node.parent) === null || _c === void 0 ? void 0 : _c.parent) === null || _d === void 0 ? void 0 : _d.type) === utils_1.AST_NODE_TYPES.ForOfStatement) && | ||
if ((node.parent.parent?.type === utils_1.AST_NODE_TYPES.ForInStatement || | ||
node.parent.parent?.type === utils_1.AST_NODE_TYPES.ForOfStatement) && | ||
isInRange(node.parent.parent.right, location)) { | ||
@@ -365,9 +340,8 @@ return true; | ||
function isOnInitializer(variable, scopeVar) { | ||
var _a; | ||
const outerScope = scopeVar.scope; | ||
const outerDef = scopeVar.defs[0]; | ||
const outer = (_a = outerDef === null || outerDef === void 0 ? void 0 : outerDef.parent) === null || _a === void 0 ? void 0 : _a.range; | ||
const outerDef = scopeVar.defs.at(0); | ||
const outer = outerDef?.parent?.range; | ||
const innerScope = variable.scope; | ||
const innerDef = variable.defs[0]; | ||
const inner = innerDef === null || innerDef === void 0 ? void 0 : innerDef.name.range; | ||
const innerDef = variable.defs.at(0); | ||
const inner = innerDef?.name.range; | ||
return !!(outer && | ||
@@ -388,4 +362,4 @@ inner && | ||
function getNameRange(variable) { | ||
const def = variable.defs[0]; | ||
return def === null || def === void 0 ? void 0 : def.name.range; | ||
const def = variable.defs.at(0); | ||
return def?.name.range; | ||
} | ||
@@ -399,3 +373,3 @@ /** | ||
function isInTdz(variable, scopeVar) { | ||
const outerDef = scopeVar.defs[0]; | ||
const outerDef = scopeVar.defs.at(0); | ||
const inner = getNameRange(variable); | ||
@@ -417,3 +391,3 @@ const outer = getNameRange(scopeVar); | ||
function getDeclaredLocation(variable) { | ||
const identifier = variable.identifiers[0]; | ||
const identifier = variable.identifiers.at(0); | ||
if (identifier) { | ||
@@ -426,7 +400,5 @@ return { | ||
} | ||
else { | ||
return { | ||
global: true, | ||
}; | ||
} | ||
return { | ||
global: true, | ||
}; | ||
} | ||
@@ -496,17 +468,20 @@ /** | ||
const location = getDeclaredLocation(shadowed); | ||
context.report(Object.assign({ node: variable.identifiers[0] }, (location.global | ||
? { | ||
messageId: 'noShadowGlobal', | ||
data: { | ||
name: variable.name, | ||
}, | ||
} | ||
: { | ||
messageId: 'noShadow', | ||
data: { | ||
name: variable.name, | ||
shadowedLine: location.line, | ||
shadowedColumn: location.column, | ||
}, | ||
}))); | ||
context.report({ | ||
node: variable.identifiers[0], | ||
...(location.global | ||
? { | ||
messageId: 'noShadowGlobal', | ||
data: { | ||
name: variable.name, | ||
}, | ||
} | ||
: { | ||
messageId: 'noShadow', | ||
data: { | ||
name: variable.name, | ||
shadowedLine: location.line, | ||
shadowedColumn: location.column, | ||
}, | ||
}), | ||
}); | ||
} | ||
@@ -517,3 +492,3 @@ } | ||
'Program:exit'() { | ||
const globalScope = context.getScope(); | ||
const globalScope = (0, eslint_utils_1.getScope)(context); | ||
const stack = globalScope.childScopes.slice(); | ||
@@ -520,0 +495,0 @@ while (stack.length) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-this-alias', | ||
@@ -34,3 +11,3 @@ meta: { | ||
description: 'Disallow aliasing `this`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -37,0 +14,0 @@ schema: [ |
@@ -28,4 +28,4 @@ "use strict"; | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-throw-literal', | ||
@@ -66,7 +66,5 @@ meta: { | ||
create(context, [options]) { | ||
const parserServices = util.getParserServices(context); | ||
const program = parserServices.program; | ||
const checker = program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
function isErrorLike(type) { | ||
var _a; | ||
if (type.isIntersection()) { | ||
@@ -83,6 +81,6 @@ return type.types.some(isErrorLike); | ||
if (symbol.getName() === 'Error') { | ||
const declarations = (_a = symbol.getDeclarations()) !== null && _a !== void 0 ? _a : []; | ||
const declarations = symbol.getDeclarations() ?? []; | ||
for (const declaration of declarations) { | ||
const sourceFile = declaration.getSourceFile(); | ||
if (program.isSourceFileDefaultLibrary(sourceFile)) { | ||
if (services.program.isSourceFileDefaultLibrary(sourceFile)) { | ||
return true; | ||
@@ -106,4 +104,3 @@ } | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const type = services.getTypeAtLocation(node); | ||
if (type.flags & ts.TypeFlags.Undefined) { | ||
@@ -113,6 +110,6 @@ context.report({ node, messageId: 'undef' }); | ||
} | ||
if (options.allowThrowingAny && util.isTypeAnyType(type)) { | ||
if (options.allowThrowingAny && (0, util_1.isTypeAnyType)(type)) { | ||
return; | ||
} | ||
if (options.allowThrowingUnknown && util.isTypeUnknownType(type)) { | ||
if (options.allowThrowingUnknown && (0, util_1.isTypeUnknownType)(type)) { | ||
return; | ||
@@ -119,0 +116,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const enumValues = [ | ||
'always', | ||
'never', | ||
'in-unions', | ||
'in-intersections', | ||
'in-unions-and-intersections', | ||
]; | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-type-alias', | ||
meta: { | ||
deprecated: true, | ||
type: 'suggestion', | ||
@@ -42,3 +13,2 @@ docs: { | ||
// too opinionated to be recommended | ||
recommended: false, | ||
}, | ||
@@ -51,2 +21,18 @@ messages: { | ||
{ | ||
$defs: { | ||
expandedOptions: { | ||
type: 'string', | ||
enum: [ | ||
'always', | ||
'never', | ||
'in-unions', | ||
'in-intersections', | ||
'in-unions-and-intersections', | ||
], | ||
}, | ||
simpleOptions: { | ||
type: 'string', | ||
enum: ['always', 'never'], | ||
}, | ||
}, | ||
type: 'object', | ||
@@ -56,31 +42,31 @@ properties: { | ||
description: 'Whether to allow direct one-to-one type aliases.', | ||
enum: enumValues, | ||
$ref: '#/items/0/$defs/expandedOptions', | ||
}, | ||
allowCallbacks: { | ||
description: 'Whether to allow type aliases for callbacks.', | ||
enum: ['always', 'never'], | ||
$ref: '#/items/0/$defs/simpleOptions', | ||
}, | ||
allowConditionalTypes: { | ||
description: 'Whether to allow type aliases for conditional types.', | ||
enum: ['always', 'never'], | ||
$ref: '#/items/0/$defs/simpleOptions', | ||
}, | ||
allowConstructors: { | ||
description: 'Whether to allow type aliases with constructors.', | ||
enum: ['always', 'never'], | ||
$ref: '#/items/0/$defs/simpleOptions', | ||
}, | ||
allowLiterals: { | ||
description: 'Whether to allow type aliases with object literal types.', | ||
enum: enumValues, | ||
$ref: '#/items/0/$defs/expandedOptions', | ||
}, | ||
allowMappedTypes: { | ||
description: 'Whether to allow type aliases with mapped types.', | ||
enum: enumValues, | ||
$ref: '#/items/0/$defs/expandedOptions', | ||
}, | ||
allowTupleTypes: { | ||
description: 'Whether to allow type aliases with tuple types.', | ||
enum: enumValues, | ||
$ref: '#/items/0/$defs/expandedOptions', | ||
}, | ||
allowGenerics: { | ||
description: 'Whether to allow type aliases with generic types.', | ||
enum: ['always', 'never'], | ||
$ref: '#/items/0/$defs/simpleOptions', | ||
}, | ||
@@ -183,3 +169,3 @@ }, | ||
return (type.node.type === utils_1.AST_NODE_TYPES.TSTypeReference && | ||
type.node.typeParameters !== undefined); | ||
type.node.typeArguments !== undefined); | ||
}; | ||
@@ -186,0 +172,0 @@ const checkAndReport = (optionValue, isTopLevel, type, label) => { |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unnecessary-boolean-literal-compare', | ||
@@ -72,5 +73,4 @@ meta: { | ||
create(context, [options]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function getBooleanComparison(node) { | ||
@@ -81,8 +81,14 @@ const comparison = deconstructComparison(node); | ||
} | ||
const expressionType = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(comparison.expression)); | ||
const expressionType = services.getTypeAtLocation(comparison.expression); | ||
if (isBooleanType(expressionType)) { | ||
return Object.assign(Object.assign({}, comparison), { expressionIsNullableBoolean: false }); | ||
return { | ||
...comparison, | ||
expressionIsNullableBoolean: false, | ||
}; | ||
} | ||
if (isNullableBoolean(expressionType)) { | ||
return Object.assign(Object.assign({}, comparison), { expressionIsNullableBoolean: true }); | ||
return { | ||
...comparison, | ||
expressionIsNullableBoolean: true, | ||
}; | ||
} | ||
@@ -169,3 +175,3 @@ return undefined; | ||
// 3. negated - is expression negated | ||
const isUnaryNegation = node.parent != null && nodeIsUnaryNegation(node.parent); | ||
const isUnaryNegation = nodeIsUnaryNegation(node.parent); | ||
const shouldNegate = comparison.negated !== comparison.literalBooleanInComparison; | ||
@@ -178,3 +184,3 @@ const mutatedNode = isUnaryNegation ? node.parent : node; | ||
// if the expression `exp` is not a strong precedence node, wrap it in parentheses | ||
if (!util.isStrongPrecedenceNode(comparison.expression)) { | ||
if (!(0, util_1.isStrongPrecedenceNode)(comparison.expression)) { | ||
yield fixer.insertTextBefore(mutatedNode, '('); | ||
@@ -181,0 +187,0 @@ yield fixer.insertTextAfter(mutatedNode, ')'); |
@@ -27,3 +27,4 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils_1 = require("tsutils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
@@ -33,4 +34,10 @@ const util_1 = require("../util"); | ||
// #region | ||
const isTruthyLiteral = (type) => (0, tsutils_1.isBooleanLiteralType)(type, true) || ((0, tsutils_1.isLiteralType)(type) && !!type.value); | ||
const isPossiblyFalsy = (type) => (0, tsutils_1.unionTypeParts)(type) | ||
const isTruthyLiteral = (type) => tsutils.isTrueLiteralType(type) || | ||
// || type. | ||
(type.isLiteral() && !!type.value); | ||
const isPossiblyFalsy = (type) => tsutils | ||
.unionTypeParts(type) | ||
// Intersections like `string & {}` can also be possibly falsy, | ||
// requiring us to look into the intersection. | ||
.flatMap(type => tsutils.intersectionTypeParts(type)) | ||
// PossiblyFalsy flag includes literal values, so exclude ones that | ||
@@ -40,15 +47,20 @@ // are definitely truthy | ||
.some(type => (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.PossiblyFalsy)); | ||
const isPossiblyTruthy = (type) => (0, tsutils_1.unionTypeParts)(type).some(type => !(0, tsutils_1.isFalsyType)(type)); | ||
const isPossiblyTruthy = (type) => tsutils | ||
.unionTypeParts(type) | ||
.map(type => tsutils.intersectionTypeParts(type)) | ||
.some(intersectionParts => | ||
// It is possible to define intersections that are always falsy, | ||
// like `"" & { __brand: string }`. | ||
intersectionParts.every(type => !tsutils.isFalsyType(type))); | ||
// Nullish utilities | ||
const nullishFlag = ts.TypeFlags.Undefined | ts.TypeFlags.Null; | ||
const isNullishType = (type) => (0, util_1.isTypeFlagSet)(type, nullishFlag); | ||
const isPossiblyNullish = (type) => (0, tsutils_1.unionTypeParts)(type).some(isNullishType); | ||
const isAlwaysNullish = (type) => (0, tsutils_1.unionTypeParts)(type).every(isNullishType); | ||
const isPossiblyNullish = (type) => tsutils.unionTypeParts(type).some(isNullishType); | ||
const isAlwaysNullish = (type) => tsutils.unionTypeParts(type).every(isNullishType); | ||
// isLiteralType only covers numbers and strings, this is a more exhaustive check. | ||
const isLiteral = (type) => (0, tsutils_1.isBooleanLiteralType)(type, true) || | ||
(0, tsutils_1.isBooleanLiteralType)(type, false) || | ||
const isLiteral = (type) => tsutils.isBooleanLiteralType(type) || | ||
type.flags === ts.TypeFlags.Undefined || | ||
type.flags === ts.TypeFlags.Null || | ||
type.flags === ts.TypeFlags.Void || | ||
(0, tsutils_1.isLiteralType)(type); | ||
type.isLiteral(); | ||
exports.default = (0, util_1.createRule)({ | ||
@@ -101,7 +113,7 @@ name: 'no-unnecessary-condition', | ||
create(context, [{ allowConstantLoopConditions, allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing, },]) { | ||
const service = (0, util_1.getParserServices)(context); | ||
const checker = service.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const compilerOptions = service.program.getCompilerOptions(); | ||
const isStrictNullChecks = (0, tsutils_1.isStrictCompilerOptionEnabled)(compilerOptions, 'strictNullChecks'); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks'); | ||
if (!isStrictNullChecks && | ||
@@ -117,12 +129,8 @@ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing !== true) { | ||
} | ||
function getNodeType(node) { | ||
const tsNode = service.esTreeNodeToTSNodeMap.get(node); | ||
return (0, util_1.getConstrainedTypeAtLocation)(checker, tsNode); | ||
} | ||
function nodeIsArrayType(node) { | ||
const nodeType = getNodeType(node); | ||
const nodeType = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
return checker.isArrayType(nodeType); | ||
} | ||
function nodeIsTupleType(node) { | ||
const nodeType = getNodeType(node); | ||
const nodeType = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
return checker.isTupleType(nodeType); | ||
@@ -168,6 +176,8 @@ } | ||
} | ||
const type = getNodeType(node); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
// Conditional is always necessary if it involves: | ||
// `any` or `unknown` or a naked type variable | ||
if ((0, tsutils_1.unionTypeParts)(type).some(part => (0, util_1.isTypeAnyType)(part) || | ||
if (tsutils | ||
.unionTypeParts(type) | ||
.some(part => (0, util_1.isTypeAnyType)(part) || | ||
(0, util_1.isTypeUnknownType)(part) || | ||
@@ -192,5 +202,5 @@ (0, util_1.isTypeFlagSet)(part, ts.TypeFlags.TypeVariable))) { | ||
function checkNodeForNullish(node) { | ||
const type = getNodeType(node); | ||
// Conditional is always necessary if it involves `any` or `unknown` | ||
if ((0, util_1.isTypeAnyType)(type) || (0, util_1.isTypeUnknownType)(type)) { | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
// Conditional is always necessary if it involves `any`, `unknown` or a naked type parameter | ||
if ((0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown | ts.TypeFlags.TypeParameter)) { | ||
return; | ||
@@ -244,4 +254,4 @@ } | ||
} | ||
const leftType = getNodeType(node.left); | ||
const rightType = getNodeType(node.right); | ||
const leftType = (0, util_1.getConstrainedTypeAtLocation)(services, node.left); | ||
const rightType = (0, util_1.getConstrainedTypeAtLocation)(services, node.right); | ||
if (isLiteral(leftType) && isLiteral(rightType)) { | ||
@@ -306,3 +316,3 @@ context.report({ node, messageId: 'literalBooleanExpression' }); | ||
if (allowConstantLoopConditions && | ||
(0, tsutils_1.isBooleanLiteralType)(getNodeType(node.test), true)) { | ||
tsutils.isTrueLiteralType((0, util_1.getConstrainedTypeAtLocation)(services, node.test))) { | ||
return; | ||
@@ -333,5 +343,4 @@ } | ||
// Inline defined functions | ||
if ((callback.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression || | ||
callback.type === utils_1.AST_NODE_TYPES.FunctionExpression) && | ||
callback.body) { | ||
if (callback.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression || | ||
callback.type === utils_1.AST_NODE_TYPES.FunctionExpression) { | ||
// Two special cases, where we can directly check the node that's returned: | ||
@@ -354,3 +363,5 @@ // () => something | ||
// Otherwise just do type analysis on the function as a whole. | ||
const returnTypes = (0, tsutils_1.getCallSignaturesOfType)(getNodeType(callback)).map(sig => sig.getReturnType()); | ||
const returnTypes = tsutils | ||
.getCallSignaturesOfType((0, util_1.getConstrainedTypeAtLocation)(services, callback)) | ||
.map(sig => sig.getReturnType()); | ||
/* istanbul ignore if */ if (returnTypes.length === 0) { | ||
@@ -408,6 +419,5 @@ // Not a callable function | ||
const typeName = (0, util_1.getTypeName)(checker, propertyType); | ||
return !!((typeName === 'string' && | ||
checker.getIndexInfoOfType(objType, ts.IndexKind.String)) || | ||
(typeName === 'number' && | ||
checker.getIndexInfoOfType(objType, ts.IndexKind.Number))); | ||
return !!checker | ||
.getIndexInfosOfType(objType) | ||
.find(info => (0, util_1.getTypeName)(checker, info.keyType) === typeName); | ||
} | ||
@@ -423,3 +433,3 @@ // Checks whether a member expression is nullable or not regardless of it's previous node. | ||
function isNullableOriginFromPrev(node) { | ||
const prevType = getNodeType(node.object); | ||
const prevType = (0, util_1.getConstrainedTypeAtLocation)(services, node.object); | ||
const property = node.property; | ||
@@ -429,3 +439,3 @@ if (prevType.isUnion() && (0, util_1.isIdentifier)(property)) { | ||
if (node.computed) { | ||
const propertyType = getNodeType(node.property); | ||
const propertyType = (0, util_1.getConstrainedTypeAtLocation)(services, node.property); | ||
return isNullablePropertyType(type, propertyType); | ||
@@ -444,3 +454,3 @@ } | ||
function isOptionableExpression(node) { | ||
const type = getNodeType(node); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
const isOwnNullable = node.type === utils_1.AST_NODE_TYPES.MemberExpression | ||
@@ -447,0 +457,0 @@ ? !isNullableOriginFromPrev(node) |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unnecessary-qualifier', | ||
@@ -36,3 +37,2 @@ meta: { | ||
description: 'Disallow unnecessary namespace qualifiers', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -51,7 +51,6 @@ }, | ||
let currentFailedNamespaceExpression = null; | ||
const parserServices = util.getParserServices(context); | ||
const esTreeNodeToTSNodeMap = parserServices.esTreeNodeToTSNodeMap; | ||
const program = parserServices.program; | ||
const checker = program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const esTreeNodeToTSNodeMap = services.esTreeNodeToTSNodeMap; | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function tryGetAliasedSymbol(symbol, checker) { | ||
@@ -63,4 +62,3 @@ return tsutils.isSymbolFlagSet(symbol, ts.SymbolFlags.Alias) | ||
function symbolIsNamespaceInScope(symbol) { | ||
var _a; | ||
const symbolDeclarations = (_a = symbol.getDeclarations()) !== null && _a !== void 0 ? _a : []; | ||
const symbolDeclarations = symbol.getDeclarations() ?? []; | ||
if (symbolDeclarations.some(decl => namespacesInScope.some(ns => ns === decl))) { | ||
@@ -73,3 +71,2 @@ return true; | ||
function getSymbolInScope(node, flags, name) { | ||
// TODO:PERF `getSymbolsInScope` gets a long list. Is there a better way? | ||
const scope = checker.getSymbolsInScope(node, flags); | ||
@@ -82,5 +79,3 @@ return scope.find(scopeSymbol => scopeSymbol.name === name); | ||
function qualifierIsUnnecessary(qualifier, name) { | ||
const tsQualifier = esTreeNodeToTSNodeMap.get(qualifier); | ||
const tsName = esTreeNodeToTSNodeMap.get(name); | ||
const namespaceSymbol = checker.getSymbolAtLocation(tsQualifier); | ||
const namespaceSymbol = services.getSymbolAtLocation(qualifier); | ||
if (namespaceSymbol === undefined || | ||
@@ -90,3 +85,3 @@ !symbolIsNamespaceInScope(namespaceSymbol)) { | ||
} | ||
const accessedSymbol = checker.getSymbolAtLocation(tsName); | ||
const accessedSymbol = services.getSymbolAtLocation(name); | ||
if (accessedSymbol === undefined) { | ||
@@ -96,2 +91,3 @@ return false; | ||
// If the symbol in scope is different, the qualifier is necessary. | ||
const tsQualifier = esTreeNodeToTSNodeMap.get(qualifier); | ||
const fromScope = getSymbolInScope(tsQualifier, accessedSymbol.flags, sourceCode.getText(name)); | ||
@@ -137,3 +133,5 @@ return (fromScope === undefined || symbolsAreEqual(accessedSymbol, fromScope)); | ||
return { | ||
TSModuleDeclaration: enterDeclaration, | ||
'TSModuleDeclaration > TSModuleBlock'(node) { | ||
enterDeclaration(node.parent); | ||
}, | ||
TSEnumDeclaration: enterDeclaration, | ||
@@ -140,0 +138,0 @@ 'ExportNamedDeclaration[declaration.type="TSModuleDeclaration"]': enterDeclaration, |
@@ -26,7 +26,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unnecessary-type-arguments', | ||
@@ -48,9 +47,9 @@ meta: { | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
function getTypeForComparison(type) { | ||
if (util.isTypeReferenceType(type)) { | ||
if ((0, util_1.isTypeReferenceType)(type)) { | ||
return { | ||
type: type.target, | ||
typeArguments: util.getTypeArguments(type, checker), | ||
typeArguments: checker.getTypeArguments(type), | ||
}; | ||
@@ -67,4 +66,4 @@ } | ||
const arg = esParameters.params[i]; | ||
const param = typeParameters[i]; | ||
if (!(param === null || param === void 0 ? void 0 : param.default)) { | ||
const param = typeParameters.at(i); | ||
if (!param?.default) { | ||
return; | ||
@@ -74,4 +73,3 @@ } | ||
const defaultType = checker.getTypeAtLocation(param.default); | ||
const argTsNode = parserServices.esTreeNodeToTSNodeMap.get(arg); | ||
const argType = checker.getTypeAtLocation(argTsNode); | ||
const argType = services.getTypeAtLocation(arg); | ||
// this check should handle some of the most simple cases of like strings, numbers, etc | ||
@@ -104,3 +102,3 @@ if (defaultType !== argType) { | ||
TSTypeParameterInstantiation(node) { | ||
const expression = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const expression = services.esTreeNodeToTSNodeMap.get(node); | ||
const typeParameters = getTypeParametersFromNode(expression, checker); | ||
@@ -144,3 +142,3 @@ if (typeParameters) { | ||
const sig = checker.getResolvedSignature(node); | ||
const sigDecl = sig === null || sig === void 0 ? void 0 : sig.getDeclaration(); | ||
const sigDecl = sig?.getDeclaration(); | ||
if (!sigDecl) { | ||
@@ -147,0 +145,0 @@ return ts.isNewExpression(node) |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils_1 = require("tsutils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unnecessary-type-assertion', | ||
@@ -36,3 +37,3 @@ meta: { | ||
description: 'Disallow type assertions that do not change the type of an expression', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -48,2 +49,3 @@ }, | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
@@ -64,6 +66,6 @@ typesToIgnore: { | ||
create(context, [options]) { | ||
const sourceCode = context.getSourceCode(); | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const compilerOptions = parserServices.program.getCompilerOptions(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
/** | ||
@@ -100,3 +102,3 @@ * Sometimes tuple types don't have ObjectFlags.Tuple set, like when they're being matched against an inferred type. | ||
function isPossiblyUsedBeforeAssigned(node) { | ||
const declaration = util.getDeclaration(checker, node); | ||
const declaration = (0, util_1.getDeclaration)(services, node); | ||
if (!declaration) { | ||
@@ -108,6 +110,6 @@ // don't know what the declaration is for some reason, so just assume the worst | ||
// non-strict mode doesn't care about used before assigned errors | ||
(0, tsutils_1.isStrictCompilerOptionEnabled)(compilerOptions, 'strictNullChecks') && | ||
tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks') && | ||
// ignore class properties as they are compile time guarded | ||
// also ignore function arguments as they can't be used before defined | ||
(0, tsutils_1.isVariableDeclaration)(declaration) && | ||
ts.isVariableDeclaration(declaration) && | ||
// is it `const x!: number` | ||
@@ -119,3 +121,3 @@ declaration.initializer === undefined && | ||
const declarationType = checker.getTypeFromTypeNode(declaration.type); | ||
const type = util.getConstrainedTypeAtLocation(checker, node); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
if (declarationType === type) { | ||
@@ -139,4 +141,3 @@ // possibly used before assigned, so just skip it | ||
TSNonNullExpression(node) { | ||
var _a; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.AssignmentExpression && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression && | ||
node.parent.operator === '=') { | ||
@@ -161,6 +162,6 @@ if (node.parent.left === node) { | ||
} | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(checker, originalNode.expression); | ||
if (!util.isNullableType(type)) { | ||
if (isPossiblyUsedBeforeAssigned(originalNode.expression)) { | ||
const originalNode = services.esTreeNodeToTSNodeMap.get(node); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node.expression); | ||
if (!(0, util_1.isNullableType)(type)) { | ||
if (isPossiblyUsedBeforeAssigned(node.expression)) { | ||
return; | ||
@@ -182,10 +183,10 @@ } | ||
// so figure out if the variable is used in a place that accepts nullable types | ||
const contextualType = util.getContextualType(checker, originalNode); | ||
const contextualType = (0, util_1.getContextualType)(checker, originalNode); | ||
if (contextualType) { | ||
// in strict mode you can't assign null to undefined, so we have to make sure that | ||
// the two types share a nullable type | ||
const typeIncludesUndefined = util.isTypeFlagSet(type, ts.TypeFlags.Undefined); | ||
const typeIncludesNull = util.isTypeFlagSet(type, ts.TypeFlags.Null); | ||
const contextualTypeIncludesUndefined = util.isTypeFlagSet(contextualType, ts.TypeFlags.Undefined); | ||
const contextualTypeIncludesNull = util.isTypeFlagSet(contextualType, ts.TypeFlags.Null); | ||
const typeIncludesUndefined = (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Undefined); | ||
const typeIncludesNull = (0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Null); | ||
const contextualTypeIncludesUndefined = (0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Undefined); | ||
const contextualTypeIncludesNull = (0, util_1.isTypeFlagSet)(contextualType, ts.TypeFlags.Null); | ||
// make sure that the parent accepts the same types | ||
@@ -215,12 +216,10 @@ // i.e. assigning `string | null | undefined` to `string | undefined` is invalid | ||
'TSAsExpression, TSTypeAssertion'(node) { | ||
var _a; | ||
if (((_a = options.typesToIgnore) === null || _a === void 0 ? void 0 : _a.includes(sourceCode.getText(node.typeAnnotation))) || | ||
if (options.typesToIgnore?.includes(sourceCode.getText(node.typeAnnotation)) || | ||
isConstAssertion(node.typeAnnotation)) { | ||
return; | ||
} | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const castType = checker.getTypeAtLocation(originalNode); | ||
if ((0, tsutils_1.isTypeFlagSet)(castType, ts.TypeFlags.Literal) || | ||
((0, tsutils_1.isObjectType)(castType) && | ||
((0, tsutils_1.isObjectFlagSet)(castType, ts.ObjectFlags.Tuple) || | ||
const castType = services.getTypeAtLocation(node); | ||
if ((0, util_1.isTypeFlagSet)(castType, ts.TypeFlags.Literal) || | ||
(tsutils.isObjectType(castType) && | ||
(tsutils.isObjectFlagSet(castType, ts.ObjectFlags.Tuple) || | ||
couldBeTupleType(castType)))) { | ||
@@ -231,3 +230,3 @@ // It's not always safe to remove a cast to a literal type or tuple | ||
} | ||
const uncastType = checker.getTypeAtLocation(originalNode.expression); | ||
const uncastType = services.getTypeAtLocation(node.expression); | ||
if (uncastType === castType) { | ||
@@ -238,5 +237,5 @@ context.report({ | ||
fix(fixer) { | ||
if (originalNode.kind === ts.SyntaxKind.TypeAssertionExpression) { | ||
if (node.type === utils_1.AST_NODE_TYPES.TSTypeAssertion) { | ||
const closingAngleBracket = sourceCode.getTokenAfter(node.typeAnnotation); | ||
return (closingAngleBracket === null || closingAngleBracket === void 0 ? void 0 : closingAngleBracket.value) === '>' | ||
return closingAngleBracket?.value === '>' | ||
? fixer.removeRange([ | ||
@@ -243,0 +242,0 @@ node.range[0], |
@@ -27,13 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const semver = __importStar(require("semver")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const path_1 = require("path"); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const is3dot5 = semver.satisfies(ts.version, `>= 3.5.0 || >= 3.5.1-rc || >= 3.5.0-beta`, { | ||
includePrerelease: true, | ||
}); | ||
const is3dot9 = is3dot5 && | ||
semver.satisfies(ts.version, `>= 3.9.0 || >= 3.9.1-rc || >= 3.9.0-beta`, { | ||
includePrerelease: true, | ||
}); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unnecessary-type-constraint', | ||
@@ -43,3 +37,3 @@ meta: { | ||
description: 'Disallow unnecessary constraints on generic types', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -56,20 +50,26 @@ hasSuggestions: true, | ||
create(context) { | ||
if (!is3dot5) { | ||
return {}; | ||
} | ||
// In theory, we could use the type checker for more advanced constraint types... | ||
// ...but in practice, these types are rare, and likely not worth requiring type info. | ||
// https://github.com/typescript-eslint/typescript-eslint/pull/2516#discussion_r495731858 | ||
const unnecessaryConstraints = is3dot9 | ||
? new Map([ | ||
[utils_1.AST_NODE_TYPES.TSAnyKeyword, 'any'], | ||
[utils_1.AST_NODE_TYPES.TSUnknownKeyword, 'unknown'], | ||
]) | ||
: new Map([[utils_1.AST_NODE_TYPES.TSUnknownKeyword, 'unknown']]); | ||
const inJsx = context.getFilename().toLowerCase().endsWith('tsx'); | ||
const source = context.getSourceCode(); | ||
const unnecessaryConstraints = new Map([ | ||
[utils_1.AST_NODE_TYPES.TSAnyKeyword, 'any'], | ||
[utils_1.AST_NODE_TYPES.TSUnknownKeyword, 'unknown'], | ||
]); | ||
function checkRequiresGenericDeclarationDisambiguation(filename) { | ||
const pathExt = (0, path_1.extname)(filename).toLocaleLowerCase(); | ||
switch (pathExt) { | ||
case ts.Extension.Cts: | ||
case ts.Extension.Mts: | ||
case ts.Extension.Tsx: | ||
return true; | ||
default: | ||
return false; | ||
} | ||
} | ||
const requiresGenericDeclarationDisambiguation = checkRequiresGenericDeclarationDisambiguation((0, eslint_utils_1.getFilename)(context)); | ||
const source = (0, eslint_utils_1.getSourceCode)(context); | ||
const checkNode = (node, inArrowFunction) => { | ||
const constraint = unnecessaryConstraints.get(node.constraint.type); | ||
function shouldAddTrailingComma() { | ||
if (!inArrowFunction || !inJsx) { | ||
if (!inArrowFunction || !requiresGenericDeclarationDisambiguation) { | ||
return false; | ||
@@ -76,0 +76,0 @@ } |
@@ -28,6 +28,5 @@ "use strict"; | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
class FunctionSignature { | ||
static create(checker, tsNode) { | ||
var _a; | ||
const signature = checker.getResolvedSignature(tsNode); | ||
@@ -43,3 +42,3 @@ if (!signature) { | ||
const type = checker.getTypeOfSymbolAtLocation(param, tsNode); | ||
const decl = (_a = param.getDeclarations()) === null || _a === void 0 ? void 0 : _a[0]; | ||
const decl = param.getDeclarations()?.[0]; | ||
if (decl && ts.isParameter(decl) && decl.dotDotDotToken) { | ||
@@ -49,3 +48,3 @@ // is a rest param | ||
restType = { | ||
type: util.getTypeArguments(type, checker)[0], | ||
type: checker.getTypeArguments(type)[0], | ||
kind: 0 /* RestTypeKind.Array */, | ||
@@ -57,3 +56,3 @@ index: i, | ||
restType = { | ||
typeArguments: util.getTypeArguments(type, checker), | ||
typeArguments: checker.getTypeArguments(type), | ||
kind: 1 /* RestTypeKind.Tuple */, | ||
@@ -116,3 +115,3 @@ index: i, | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-argument', | ||
@@ -123,3 +122,3 @@ meta: { | ||
description: 'Disallow calling a function with a value with type `any`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -137,4 +136,4 @@ }, | ||
create(context) { | ||
const { program, esTreeNodeToTSNodeMap } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
return { | ||
@@ -146,6 +145,6 @@ 'CallExpression, NewExpression'(node) { | ||
// ignore any-typed calls as these are caught by no-unsafe-call | ||
if (util.isTypeAnyType(checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(node.callee)))) { | ||
if ((0, util_1.isTypeAnyType)(services.getTypeAtLocation(node.callee))) { | ||
return; | ||
} | ||
const tsNode = esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
const signature = FunctionSignature.create(checker, tsNode); | ||
@@ -159,4 +158,4 @@ if (!signature) { | ||
case utils_1.AST_NODE_TYPES.SpreadElement: { | ||
const spreadArgType = checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(argument.argument)); | ||
if (util.isTypeAnyType(spreadArgType)) { | ||
const spreadArgType = services.getTypeAtLocation(argument.argument); | ||
if ((0, util_1.isTypeAnyType)(spreadArgType)) { | ||
// foo(...any) | ||
@@ -168,3 +167,3 @@ context.report({ | ||
} | ||
else if (util.isTypeAnyArrayType(spreadArgType, checker)) { | ||
else if ((0, util_1.isTypeAnyArrayType)(spreadArgType, checker)) { | ||
// foo(...any[]) | ||
@@ -179,3 +178,3 @@ // TODO - we could break down the spread and compare the array type against each argument | ||
// foo(...[tuple1, tuple2]) | ||
const spreadTypeArguments = util.getTypeArguments(spreadArgType, checker); | ||
const spreadTypeArguments = checker.getTypeArguments(spreadArgType); | ||
for (const tupleType of spreadTypeArguments) { | ||
@@ -186,3 +185,3 @@ const parameterType = signature.getNextParameterType(); | ||
} | ||
const result = util.isUnsafeAssignment(tupleType, parameterType, checker, | ||
const result = (0, util_1.isUnsafeAssignment)(tupleType, parameterType, checker, | ||
// we can't pass the individual tuple members in here as this will most likely be a spread variable | ||
@@ -220,4 +219,4 @@ // not a spread array | ||
} | ||
const argumentType = checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(argument)); | ||
const result = util.isUnsafeAssignment(argumentType, parameterType, checker, argument); | ||
const argumentType = services.getTypeAtLocation(argument); | ||
const result = (0, util_1.isUnsafeAssignment)(argumentType, parameterType, checker, argument); | ||
if (result) { | ||
@@ -224,0 +223,0 @@ context.report({ |
@@ -27,6 +27,5 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-assignment', | ||
@@ -37,3 +36,3 @@ meta: { | ||
description: 'Disallow assigning a value with type `any` to variables and properties', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -56,5 +55,5 @@ }, | ||
create(context) { | ||
const { program, esTreeNodeToTSNodeMap } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const compilerOptions = program.getCompilerOptions(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'noImplicitThis'); | ||
@@ -66,4 +65,4 @@ // returns true if the assignment reported | ||
} | ||
const senderTsNode = esTreeNodeToTSNodeMap.get(senderNode); | ||
const senderType = checker.getTypeAtLocation(senderTsNode); | ||
const senderTsNode = services.esTreeNodeToTSNodeMap.get(senderNode); | ||
const senderType = services.getTypeAtLocation(senderNode); | ||
return checkArrayDestructure(receiverNode, senderType, senderTsNode); | ||
@@ -75,3 +74,3 @@ } | ||
// const [x] = ([] as any[]); | ||
if (util.isTypeAnyArrayType(senderType, checker)) { | ||
if ((0, util_1.isTypeAnyArrayType)(senderType, checker)) { | ||
context.report({ | ||
@@ -86,3 +85,3 @@ node: receiverNode, | ||
} | ||
const tupleElements = util.getTypeArguments(senderType, checker); | ||
const tupleElements = checker.getTypeArguments(senderType); | ||
// tuple with any | ||
@@ -105,3 +104,3 @@ // const [x] = [1 as any]; | ||
// check for the any type first so we can handle [[[x]]] = [any] | ||
if (util.isTypeAnyType(senderType)) { | ||
if ((0, util_1.isTypeAnyType)(senderType)) { | ||
context.report({ | ||
@@ -128,4 +127,4 @@ node: receiverElement, | ||
} | ||
const senderTsNode = esTreeNodeToTSNodeMap.get(senderNode); | ||
const senderType = checker.getTypeAtLocation(senderTsNode); | ||
const senderTsNode = services.esTreeNodeToTSNodeMap.get(senderNode); | ||
const senderType = services.getTypeAtLocation(senderNode); | ||
return checkObjectDestructure(receiverNode, senderType, senderTsNode); | ||
@@ -148,3 +147,3 @@ } | ||
let key; | ||
if (receiverProperty.computed === false) { | ||
if (!receiverProperty.computed) { | ||
key = | ||
@@ -171,3 +170,3 @@ receiverProperty.key.type === utils_1.AST_NODE_TYPES.Identifier | ||
// check for the any type first so we can handle {x: {y: z}} = {x: any} | ||
if (util.isTypeAnyType(senderType)) { | ||
if ((0, util_1.isTypeAnyType)(senderType)) { | ||
context.report({ | ||
@@ -190,11 +189,11 @@ node: receiverProperty.value, | ||
function checkAssignment(receiverNode, senderNode, reportingNode, comparisonType) { | ||
var _a; | ||
const receiverTsNode = esTreeNodeToTSNodeMap.get(receiverNode); | ||
const receiverTsNode = services.esTreeNodeToTSNodeMap.get(receiverNode); | ||
const receiverType = comparisonType === 2 /* ComparisonType.Contextual */ | ||
? (_a = util.getContextualType(checker, receiverTsNode)) !== null && _a !== void 0 ? _a : checker.getTypeAtLocation(receiverTsNode) | ||
: checker.getTypeAtLocation(receiverTsNode); | ||
const senderType = checker.getTypeAtLocation(esTreeNodeToTSNodeMap.get(senderNode)); | ||
if (util.isTypeAnyType(senderType)) { | ||
? (0, util_1.getContextualType)(checker, receiverTsNode) ?? | ||
services.getTypeAtLocation(receiverNode) | ||
: services.getTypeAtLocation(receiverNode); | ||
const senderType = services.getTypeAtLocation(senderNode); | ||
if ((0, util_1.isTypeAnyType)(senderType)) { | ||
// handle cases when we assign any ==> unknown. | ||
if (util.isTypeUnknownType(receiverType)) { | ||
if ((0, util_1.isTypeUnknownType)(receiverType)) { | ||
return false; | ||
@@ -207,3 +206,3 @@ } | ||
if (thisExpression && | ||
util.isTypeAnyType(util.getConstrainedTypeAtLocation(checker, esTreeNodeToTSNodeMap.get(thisExpression)))) { | ||
(0, util_1.isTypeAnyType)((0, util_1.getConstrainedTypeAtLocation)(services, thisExpression))) { | ||
messageId = 'anyAssignmentThis'; | ||
@@ -221,3 +220,3 @@ } | ||
} | ||
const result = util.isUnsafeAssignment(senderType, receiverType, checker, senderNode); | ||
const result = (0, util_1.isUnsafeAssignment)(senderType, receiverType, checker, senderNode); | ||
if (!result) { | ||
@@ -246,3 +245,3 @@ return false; | ||
'VariableDeclarator[init != null]'(node) { | ||
const init = util.nullThrows(node.init, util.NullThrowsReasons.MissingToken(node.type, 'init')); | ||
const init = (0, util_1.nullThrows)(node.init, util_1.NullThrowsReasons.MissingToken(node.type, 'init')); | ||
let didReport = checkAssignment(node.id, init, node, getComparisonType(node.id.typeAnnotation)); | ||
@@ -278,6 +277,4 @@ if (!didReport) { | ||
'ArrayExpression > SpreadElement'(node) { | ||
const resetNode = esTreeNodeToTSNodeMap.get(node.argument); | ||
const restType = checker.getTypeAtLocation(resetNode); | ||
if (util.isTypeAnyType(restType) || | ||
util.isTypeAnyArrayType(restType, checker)) { | ||
const restType = services.getTypeAtLocation(node.argument); | ||
if ((0, util_1.isTypeAnyType)(restType) || (0, util_1.isTypeAnyArrayType)(restType, checker)) { | ||
context.report({ | ||
@@ -290,3 +287,3 @@ node: node, | ||
'JSXAttribute[value != null]'(node) { | ||
const value = util.nullThrows(node.value, util.NullThrowsReasons.MissingToken(node.type, 'value')); | ||
const value = (0, util_1.nullThrows)(node.value, util_1.NullThrowsReasons.MissingToken(node.type, 'value')); | ||
if (value.type !== utils_1.AST_NODE_TYPES.JSXExpressionContainer || | ||
@@ -293,0 +290,0 @@ value.expression.type === utils_1.AST_NODE_TYPES.JSXEmptyExpression) { |
@@ -26,6 +26,5 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-call', | ||
@@ -36,3 +35,3 @@ meta: { | ||
description: 'Disallow calling a value with type `any`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -53,10 +52,8 @@ }, | ||
create(context) { | ||
const { program, esTreeNodeToTSNodeMap } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const compilerOptions = program.getCompilerOptions(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'noImplicitThis'); | ||
function checkCall(node, reportingNode, messageId) { | ||
const tsNode = esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(checker, tsNode); | ||
if (util.isTypeAnyType(type)) { | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
if ((0, util_1.isTypeAnyType)(type)) { | ||
if (!isNoImplicitThis) { | ||
@@ -66,3 +63,3 @@ // `this()` or `this.foo()` or `this.foo[bar]()` | ||
if (thisExpression && | ||
util.isTypeAnyType(util.getConstrainedTypeAtLocation(checker, esTreeNodeToTSNodeMap.get(thisExpression)))) { | ||
(0, util_1.isTypeAnyType)((0, util_1.getConstrainedTypeAtLocation)(services, thisExpression))) { | ||
messageId = 'unsafeCallThis'; | ||
@@ -69,0 +66,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-declaration-merging', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow unsafe declaration merging', | ||
recommended: 'strict', | ||
recommended: 'recommended', | ||
requiresTypeChecking: false, | ||
@@ -66,3 +44,3 @@ }, | ||
// but we want the outer scope within which merged variables will sit | ||
const currentScope = context.getScope().upper; | ||
const currentScope = (0, eslint_utils_1.getScope)(context).upper; | ||
if (currentScope == null) { | ||
@@ -75,3 +53,3 @@ return; | ||
TSInterfaceDeclaration(node) { | ||
checkUnsafeDeclaration(context.getScope(), node.id, utils_1.AST_NODE_TYPES.ClassDeclaration); | ||
checkUnsafeDeclaration((0, eslint_utils_1.getScope)(context), node.id, utils_1.AST_NODE_TYPES.ClassDeclaration); | ||
}, | ||
@@ -78,0 +56,0 @@ }; |
@@ -27,6 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-member-access', | ||
@@ -37,3 +37,3 @@ meta: { | ||
description: 'Disallow member access on a value with type `any`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -53,7 +53,6 @@ }, | ||
create(context) { | ||
const { program, esTreeNodeToTSNodeMap } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const compilerOptions = program.getCompilerOptions(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'noImplicitThis'); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const stateCache = new Map(); | ||
@@ -74,5 +73,4 @@ function checkMemberExpression(node) { | ||
} | ||
const tsNode = esTreeNodeToTSNodeMap.get(node.object); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const state = util.isTypeAnyType(type) ? 1 /* State.Unsafe */ : 2 /* State.Safe */; | ||
const type = services.getTypeAtLocation(node.object); | ||
const state = (0, util_1.isTypeAnyType)(type) ? 1 /* State.Unsafe */ : 2 /* State.Safe */; | ||
stateCache.set(node, state); | ||
@@ -86,3 +84,3 @@ if (state === 1 /* State.Unsafe */) { | ||
if (thisExpression && | ||
util.isTypeAnyType(util.getConstrainedTypeAtLocation(checker, esTreeNodeToTSNodeMap.get(thisExpression)))) { | ||
(0, util_1.isTypeAnyType)((0, util_1.getConstrainedTypeAtLocation)(services, thisExpression))) { | ||
messageId = 'unsafeThisMemberExpression'; | ||
@@ -92,3 +90,3 @@ } | ||
context.report({ | ||
node, | ||
node: node.property, | ||
messageId, | ||
@@ -116,5 +114,4 @@ data: { | ||
} | ||
const tsNode = esTreeNodeToTSNodeMap.get(node); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
if (util.isTypeAnyType(type)) { | ||
const type = services.getTypeAtLocation(node); | ||
if ((0, util_1.isTypeAnyType)(type)) { | ||
const propertyName = sourceCode.getText(node); | ||
@@ -121,0 +118,0 @@ context.report({ |
@@ -27,6 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util_1 = require("../util"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unsafe-return', | ||
@@ -37,3 +37,3 @@ meta: { | ||
description: 'Disallow returning a value with type `any` from a function', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -53,5 +53,5 @@ }, | ||
create(context) { | ||
const { program, esTreeNodeToTSNodeMap } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
const compilerOptions = program.getCompilerOptions(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'noImplicitThis'); | ||
@@ -73,4 +73,4 @@ function getParentFunctionNode(node) { | ||
function checkReturn(returnNode, reportingNode = returnNode) { | ||
const tsNode = esTreeNodeToTSNodeMap.get(returnNode); | ||
const anyType = util.isAnyOrAnyArrayTypeDiscriminated(tsNode, checker); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(returnNode); | ||
const anyType = (0, util_1.isAnyOrAnyArrayTypeDiscriminated)(tsNode, checker); | ||
const functionNode = getParentFunctionNode(returnNode); | ||
@@ -81,4 +81,4 @@ /* istanbul ignore if */ if (!functionNode) { | ||
// function has an explicit return type, so ensure it's a safe return | ||
const returnNodeType = util.getConstrainedTypeAtLocation(checker, esTreeNodeToTSNodeMap.get(returnNode)); | ||
const functionTSNode = esTreeNodeToTSNodeMap.get(functionNode); | ||
const returnNodeType = (0, util_1.getConstrainedTypeAtLocation)(services, returnNode); | ||
const functionTSNode = services.esTreeNodeToTSNodeMap.get(functionNode); | ||
// function expressions will not have their return type modified based on receiver typing | ||
@@ -88,7 +88,8 @@ // so we have to use the contextual typing in these cases, i.e. | ||
// the return type of the arrow function is Set<any> even though the variable is typed as Set<string> | ||
let functionType = tsutils.isExpression(functionTSNode) | ||
? util.getContextualType(checker, functionTSNode) | ||
: checker.getTypeAtLocation(functionTSNode); | ||
let functionType = ts.isFunctionExpression(functionTSNode) || | ||
ts.isArrowFunction(functionTSNode) | ||
? (0, util_1.getContextualType)(checker, functionTSNode) | ||
: services.getTypeAtLocation(functionNode); | ||
if (!functionType) { | ||
functionType = checker.getTypeAtLocation(functionTSNode); | ||
functionType = services.getTypeAtLocation(functionNode); | ||
} | ||
@@ -99,3 +100,4 @@ // If there is an explicit type annotation *and* that type matches the actual | ||
for (const signature of functionType.getCallSignatures()) { | ||
if (returnNodeType === signature.getReturnType()) { | ||
if (returnNodeType === signature.getReturnType() || | ||
(0, util_1.isTypeFlagSet)(signature.getReturnType(), ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { | ||
return; | ||
@@ -105,3 +107,3 @@ } | ||
} | ||
if (anyType !== util.AnyType.Safe) { | ||
if (anyType !== util_1.AnyType.Safe) { | ||
// Allow cases when the declared return type of the function is either unknown or unknown[] | ||
@@ -111,8 +113,8 @@ // and the function is returning any or any[]. | ||
const functionReturnType = signature.getReturnType(); | ||
if (anyType === util.AnyType.Any && | ||
util.isTypeUnknownType(functionReturnType)) { | ||
if (anyType === util_1.AnyType.Any && | ||
(0, util_1.isTypeUnknownType)(functionReturnType)) { | ||
return; | ||
} | ||
if (anyType === util.AnyType.AnyArray && | ||
util.isTypeUnknownArrayType(functionReturnType, checker)) { | ||
if (anyType === util_1.AnyType.AnyArray && | ||
(0, util_1.isTypeUnknownArrayType)(functionReturnType, checker)) { | ||
return; | ||
@@ -126,3 +128,3 @@ } | ||
if (thisExpression && | ||
util.isTypeAnyType(util.getConstrainedTypeAtLocation(checker, esTreeNodeToTSNodeMap.get(thisExpression)))) { | ||
(0, util_1.isTypeAnyType)((0, util_1.getConstrainedTypeAtLocation)(services, thisExpression))) { | ||
messageId = 'unsafeReturnThis'; | ||
@@ -136,3 +138,3 @@ } | ||
data: { | ||
type: anyType === util.AnyType.Any ? 'any' : 'any[]', | ||
type: anyType === util_1.AnyType.Any ? 'any' : 'any[]', | ||
}, | ||
@@ -143,3 +145,3 @@ }); | ||
const functionReturnType = signature.getReturnType(); | ||
const result = util.isUnsafeAssignment(returnNodeType, functionReturnType, checker, returnNode); | ||
const result = (0, util_1.isUnsafeAssignment)(returnNodeType, functionReturnType, checker, returnNode); | ||
if (!result) { | ||
@@ -146,0 +148,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-unused-expressions'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unused-expressions', | ||
@@ -37,3 +13,2 @@ meta: { | ||
description: 'Disallow unused expressions', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -43,6 +18,3 @@ }, | ||
schema: baseRule.meta.schema, | ||
// TODO: this rule has only had messages since v7.0 - remove this when we remove support for v6 | ||
messages: (_a = baseRule.meta.messages) !== null && _a !== void 0 ? _a : { | ||
unusedExpression: 'Expected an assignment or function call and instead saw an expression.', | ||
}, | ||
messages: baseRule.meta.messages, | ||
}, | ||
@@ -75,2 +47,10 @@ defaultOptions: [ | ||
} | ||
if (node.expression.type === | ||
utils_1.TSESTree.AST_NODE_TYPES.TSInstantiationExpression) { | ||
rules.ExpressionStatement({ | ||
...node, | ||
expression: node.expression.expression, | ||
}); | ||
return; | ||
} | ||
rules.ExpressionStatement(node); | ||
@@ -77,0 +57,0 @@ }, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-unused-vars', | ||
@@ -35,3 +13,3 @@ meta: { | ||
description: 'Disallow unused variables', | ||
recommended: 'warn', | ||
recommended: 'recommended', | ||
extendsBaseRule: true, | ||
@@ -43,2 +21,3 @@ }, | ||
{ | ||
type: 'string', | ||
enum: ['all', 'local'], | ||
@@ -50,2 +29,3 @@ }, | ||
vars: { | ||
type: 'string', | ||
enum: ['all', 'local'], | ||
@@ -57,2 +37,3 @@ }, | ||
args: { | ||
type: 'string', | ||
enum: ['all', 'after-used', 'none'], | ||
@@ -67,2 +48,3 @@ }, | ||
caughtErrors: { | ||
type: 'string', | ||
enum: ['all', 'none'], | ||
@@ -88,7 +70,6 @@ }, | ||
create(context, [firstOption]) { | ||
const filename = context.getFilename(); | ||
const sourceCode = context.getSourceCode(); | ||
const filename = (0, eslint_utils_1.getFilename)(context); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const MODULE_DECL_CACHE = new Map(); | ||
const options = (() => { | ||
var _a, _b, _c, _d; | ||
const options = { | ||
@@ -100,26 +81,23 @@ vars: 'all', | ||
}; | ||
if (firstOption) { | ||
if (typeof firstOption === 'string') { | ||
options.vars = firstOption; | ||
if (typeof firstOption === 'string') { | ||
options.vars = firstOption; | ||
} | ||
else { | ||
options.vars = firstOption.vars ?? options.vars; | ||
options.args = firstOption.args ?? options.args; | ||
options.ignoreRestSiblings = | ||
firstOption.ignoreRestSiblings ?? options.ignoreRestSiblings; | ||
options.caughtErrors = firstOption.caughtErrors ?? options.caughtErrors; | ||
if (firstOption.varsIgnorePattern) { | ||
options.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern, 'u'); | ||
} | ||
else { | ||
options.vars = (_a = firstOption.vars) !== null && _a !== void 0 ? _a : options.vars; | ||
options.args = (_b = firstOption.args) !== null && _b !== void 0 ? _b : options.args; | ||
options.ignoreRestSiblings = | ||
(_c = firstOption.ignoreRestSiblings) !== null && _c !== void 0 ? _c : options.ignoreRestSiblings; | ||
options.caughtErrors = | ||
(_d = firstOption.caughtErrors) !== null && _d !== void 0 ? _d : options.caughtErrors; | ||
if (firstOption.varsIgnorePattern) { | ||
options.varsIgnorePattern = new RegExp(firstOption.varsIgnorePattern, 'u'); | ||
} | ||
if (firstOption.argsIgnorePattern) { | ||
options.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern, 'u'); | ||
} | ||
if (firstOption.caughtErrorsIgnorePattern) { | ||
options.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern, 'u'); | ||
} | ||
if (firstOption.destructuredArrayIgnorePattern) { | ||
options.destructuredArrayIgnorePattern = new RegExp(firstOption.destructuredArrayIgnorePattern, 'u'); | ||
} | ||
if (firstOption.argsIgnorePattern) { | ||
options.argsIgnorePattern = new RegExp(firstOption.argsIgnorePattern, 'u'); | ||
} | ||
if (firstOption.caughtErrorsIgnorePattern) { | ||
options.caughtErrorsIgnorePattern = new RegExp(firstOption.caughtErrorsIgnorePattern, 'u'); | ||
} | ||
if (firstOption.destructuredArrayIgnorePattern) { | ||
options.destructuredArrayIgnorePattern = new RegExp(firstOption.destructuredArrayIgnorePattern, 'u'); | ||
} | ||
} | ||
@@ -129,3 +107,2 @@ return options; | ||
function collectUnusedVariables() { | ||
var _a, _b, _c, _d, _e; | ||
/** | ||
@@ -137,5 +114,4 @@ * Checks whether a node is a sibling of the rest property or not. | ||
function hasRestSibling(node) { | ||
var _a; | ||
return (node.type === utils_1.AST_NODE_TYPES.Property && | ||
((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ObjectPattern && | ||
node.parent.type === utils_1.AST_NODE_TYPES.ObjectPattern && | ||
node.parent.properties[node.parent.properties.length - 1].type === | ||
@@ -164,3 +140,3 @@ utils_1.AST_NODE_TYPES.RestElement); | ||
const def = variable.defs[0]; | ||
const params = context.getDeclaredVariables(def.node); | ||
const params = (0, eslint_utils_1.getDeclaredVariables)(context, def.node); | ||
const posteriorParams = params.slice(params.indexOf(variable) + 1); | ||
@@ -170,3 +146,3 @@ // If any used parameters occur after this parameter, do not report. | ||
} | ||
const unusedVariablesOriginal = util.collectUnusedVariables(context); | ||
const unusedVariablesOriginal = (0, util_1.collectUnusedVariables)(context); | ||
const unusedVariablesReturn = []; | ||
@@ -185,8 +161,8 @@ for (const variable of unusedVariablesOriginal) { | ||
} | ||
const refUsedInArrayPatterns = variable.references.some(ref => { var _a; return ((_a = ref.identifier.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ArrayPattern; }); | ||
const refUsedInArrayPatterns = variable.references.some(ref => ref.identifier.parent.type === utils_1.AST_NODE_TYPES.ArrayPattern); | ||
// skip elements of array destructuring patterns | ||
if ((((_a = def.name.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ArrayPattern || | ||
if ((def.name.parent.type === utils_1.AST_NODE_TYPES.ArrayPattern || | ||
refUsedInArrayPatterns) && | ||
'name' in def.name && | ||
((_b = options.destructuredArrayIgnorePattern) === null || _b === void 0 ? void 0 : _b.test(def.name.name))) { | ||
options.destructuredArrayIgnorePattern?.test(def.name.name)) { | ||
continue; | ||
@@ -201,3 +177,3 @@ } | ||
if ('name' in def.name && | ||
((_c = options.caughtErrorsIgnorePattern) === null || _c === void 0 ? void 0 : _c.test(def.name.name))) { | ||
options.caughtErrorsIgnorePattern?.test(def.name.name)) { | ||
continue; | ||
@@ -213,3 +189,3 @@ } | ||
if ('name' in def.name && | ||
((_d = options.argsIgnorePattern) === null || _d === void 0 ? void 0 : _d.test(def.name.name))) { | ||
options.argsIgnorePattern?.test(def.name.name)) { | ||
continue; | ||
@@ -219,3 +195,3 @@ } | ||
if (options.args === 'after-used' && | ||
util.isFunction(def.name.parent) && | ||
(0, util_1.isFunction)(def.name.parent) && | ||
!isAfterLastUsedArg(variable)) { | ||
@@ -228,3 +204,3 @@ continue; | ||
if ('name' in def.name && | ||
((_e = options.varsIgnorePattern) === null || _e === void 0 ? void 0 : _e.test(def.name.name))) { | ||
options.varsIgnorePattern?.test(def.name.name)) { | ||
continue; | ||
@@ -248,3 +224,3 @@ } | ||
[ambientDeclarationSelector(utils_1.AST_NODE_TYPES.Program, true)](node) { | ||
if (!util.isDefinitionFile(filename)) { | ||
if (!(0, util_1.isDefinitionFile)(filename)) { | ||
return; | ||
@@ -258,3 +234,3 @@ } | ||
if (node.id.type === utils_1.AST_NODE_TYPES.Identifier) { | ||
let scope = context.getScope(); | ||
let scope = (0, eslint_utils_1.getScope)(context); | ||
if (scope.upper) { | ||
@@ -275,4 +251,3 @@ scope = scope.upper; | ||
[ambientDeclarationSelector('TSModuleDeclaration[declare = true] > TSModuleBlock', false)](node) { | ||
var _a; | ||
const moduleDecl = util.nullThrows((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent, util.NullThrowsReasons.MissingParent); | ||
const moduleDecl = (0, util_1.nullThrows)(node.parent.parent, util_1.NullThrowsReasons.MissingParent); | ||
// declared ambient modules with an `export =` statement will only export that one thing | ||
@@ -295,4 +270,3 @@ // all other statements are not automatically exported in this case | ||
function getDefinedMessageData(unusedVar) { | ||
var _a; | ||
const defType = (_a = unusedVar === null || unusedVar === void 0 ? void 0 : unusedVar.defs[0]) === null || _a === void 0 ? void 0 : _a.type; | ||
const defType = unusedVar.defs[0]?.type; | ||
let type; | ||
@@ -331,7 +305,6 @@ let pattern; | ||
function getAssignedMessageData(unusedVar) { | ||
var _a; | ||
const def = unusedVar.defs[0]; | ||
const def = unusedVar.defs.at(0); | ||
let additional = ''; | ||
if (options.destructuredArrayIgnorePattern && | ||
((_a = def === null || def === void 0 ? void 0 : def.name.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ArrayPattern) { | ||
def?.name.parent.type === utils_1.AST_NODE_TYPES.ArrayPattern) { | ||
additional = `. Allowed unused elements of array destructuring patterns must match ${options.destructuredArrayIgnorePattern.toString()}`; | ||
@@ -370,3 +343,3 @@ } | ||
node: programNode, | ||
loc: util.getNameLocationInGlobalDirectiveComment(sourceCode, directiveComment, unusedVar.name), | ||
loc: (0, util_1.getNameLocationInGlobalDirectiveComment)(sourceCode, directiveComment, unusedVar.name), | ||
messageId: 'unusedVar', | ||
@@ -384,3 +357,3 @@ data: getDefinedMessageData(unusedVar), | ||
} | ||
if (node.body && node.body.type === utils_1.AST_NODE_TYPES.TSModuleBlock) { | ||
if (node.body) { | ||
for (const statement of node.body.body) { | ||
@@ -414,3 +387,2 @@ if (statement.type === utils_1.AST_NODE_TYPES.TSExportAssignment) { | ||
function markDeclarationChildAsUsed(node) { | ||
var _a; | ||
const identifiers = []; | ||
@@ -425,3 +397,3 @@ switch (node.type) { | ||
case utils_1.AST_NODE_TYPES.TSModuleDeclaration: | ||
if (((_a = node.id) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Identifier) { | ||
if (node.id?.type === utils_1.AST_NODE_TYPES.Identifier) { | ||
identifiers.push(node.id); | ||
@@ -438,3 +410,3 @@ } | ||
} | ||
let scope = context.getScope(); | ||
let scope = (0, eslint_utils_1.getScope)(context); | ||
const shouldUseUpperScope = [ | ||
@@ -441,0 +413,0 @@ utils_1.AST_NODE_TYPES.TSModuleDeclaration, |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const SENTINEL_TYPE = /^(?:(?:Function|Class)(?:Declaration|Expression)|ArrowFunctionExpression|CatchClause|ImportDeclaration|ExportNamedDeclaration)$/; | ||
@@ -100,5 +78,4 @@ /** | ||
function isNamedExports(reference) { | ||
var _a; | ||
const { identifier } = reference; | ||
return (((_a = identifier.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ExportSpecifier && | ||
return (identifier.parent.type === utils_1.AST_NODE_TYPES.ExportSpecifier && | ||
identifier.parent.local === identifier); | ||
@@ -115,5 +92,2 @@ } | ||
case utils_1.AST_NODE_TYPES.Identifier: | ||
if (!node.parent) { | ||
return false; | ||
} | ||
return referenceContainsTypeQuery(node.parent); | ||
@@ -143,6 +117,3 @@ default: | ||
function isClassRefInClassDecorator(variable, reference) { | ||
if (variable.defs[0].type !== scope_manager_1.DefinitionType.ClassName) { | ||
return false; | ||
} | ||
if (!variable.defs[0].node.decorators || | ||
if (variable.defs[0].type !== scope_manager_1.DefinitionType.ClassName || | ||
variable.defs[0].node.decorators.length === 0) { | ||
@@ -170,3 +141,2 @@ return false; | ||
function isInInitializer(variable, reference) { | ||
var _a; | ||
if (variable.scope !== reference.from) { | ||
@@ -182,5 +152,4 @@ return false; | ||
} | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) && | ||
(node.parent.parent.type === utils_1.AST_NODE_TYPES.ForInStatement || | ||
node.parent.parent.type === utils_1.AST_NODE_TYPES.ForOfStatement) && | ||
if ((node.parent.parent?.type === utils_1.AST_NODE_TYPES.ForInStatement || | ||
node.parent.parent?.type === utils_1.AST_NODE_TYPES.ForOfStatement) && | ||
isInRange(node.parent.parent.right, location)) { | ||
@@ -203,3 +172,3 @@ return true; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-use-before-define', | ||
@@ -210,3 +179,2 @@ meta: { | ||
description: 'Disallow the use of variables before they are defined', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -221,2 +189,3 @@ }, | ||
{ | ||
type: 'string', | ||
enum: ['nofunc'], | ||
@@ -331,3 +300,3 @@ }, | ||
Program() { | ||
findVariablesInScope(context.getScope()); | ||
findVariablesInScope((0, eslint_utils_1.getScope)(context)); | ||
}, | ||
@@ -334,0 +303,0 @@ }; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
@@ -40,5 +16,3 @@ const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('no-useless-constructor'); | ||
case 'public': | ||
if (node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.ClassBody && | ||
node.parent.parent && | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.ClassBody && | ||
'superClass' in node.parent.parent && | ||
@@ -56,9 +30,6 @@ node.parent.parent.superClass) { | ||
function checkParams(node) { | ||
return !node.value.params.some(param => { | ||
var _a; | ||
return param.type === utils_1.AST_NODE_TYPES.TSParameterProperty || | ||
((_a = param.decorators) === null || _a === void 0 ? void 0 : _a.length); | ||
}); | ||
return !node.value.params.some(param => param.type === utils_1.AST_NODE_TYPES.TSParameterProperty || | ||
param.decorators.length); | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-useless-constructor', | ||
@@ -74,6 +45,3 @@ meta: { | ||
schema: baseRule.meta.schema, | ||
// TODO: this rule has only had messages since v7.0 - remove this when we remove support for v6 | ||
messages: (_a = baseRule.meta.messages) !== null && _a !== void 0 ? _a : { | ||
noUselessConstructor: 'Useless constructor.', | ||
}, | ||
messages: baseRule.meta.messages, | ||
}, | ||
@@ -85,5 +53,3 @@ defaultOptions: [], | ||
MethodDefinition(node) { | ||
if (node.value && | ||
node.value.type === utils_1.AST_NODE_TYPES.FunctionExpression && | ||
node.value.body && | ||
if (node.value.type === utils_1.AST_NODE_TYPES.FunctionExpression && | ||
checkAccessibility(node) && | ||
@@ -90,0 +56,0 @@ checkParams(node)) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
function isEmptyExport(node) { | ||
@@ -42,3 +20,3 @@ return (node.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration && | ||
]); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-useless-empty-export', | ||
@@ -48,3 +26,2 @@ meta: { | ||
description: "Disallow empty exports that don't change anything in a module file", | ||
recommended: false, | ||
}, | ||
@@ -61,2 +38,8 @@ fixable: 'code', | ||
create(context) { | ||
// In a definition file, export {} is necessary to make the module properly | ||
// encapsulated, even when there are other exports | ||
// https://github.com/typescript-eslint/typescript-eslint/issues/4975 | ||
if ((0, util_1.isDefinitionFile)((0, eslint_utils_1.getFilename)(context))) { | ||
return {}; | ||
} | ||
function checkNode(node) { | ||
@@ -66,10 +49,7 @@ if (!Array.isArray(node.body)) { | ||
} | ||
let emptyExport; | ||
const emptyExports = []; | ||
let foundOtherExport = false; | ||
for (const statement of node.body) { | ||
if (isEmptyExport(statement)) { | ||
emptyExport = statement; | ||
if (foundOtherExport) { | ||
break; | ||
} | ||
emptyExports.push(statement); | ||
} | ||
@@ -80,8 +60,10 @@ else if (exportOrImportNodeTypes.has(statement.type)) { | ||
} | ||
if (emptyExport && foundOtherExport) { | ||
context.report({ | ||
fix: fixer => fixer.remove(emptyExport), | ||
messageId: 'uselessExport', | ||
node: emptyExport, | ||
}); | ||
if (foundOtherExport) { | ||
for (const emptyExport of emptyExports) { | ||
context.report({ | ||
fix: fixer => fixer.remove(emptyExport), | ||
messageId: 'uselessExport', | ||
node: emptyExport, | ||
}); | ||
} | ||
} | ||
@@ -88,0 +70,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'no-var-requires', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow `require` statements except in import statements', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -46,17 +24,15 @@ messages: { | ||
'CallExpression[callee.name="require"]'(node) { | ||
var _a; | ||
const parent = ((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ChainExpression | ||
const parent = node.parent.type === utils_1.AST_NODE_TYPES.ChainExpression | ||
? node.parent.parent | ||
: node.parent; | ||
if (parent && | ||
[ | ||
utils_1.AST_NODE_TYPES.CallExpression, | ||
utils_1.AST_NODE_TYPES.MemberExpression, | ||
utils_1.AST_NODE_TYPES.NewExpression, | ||
utils_1.AST_NODE_TYPES.TSAsExpression, | ||
utils_1.AST_NODE_TYPES.TSTypeAssertion, | ||
utils_1.AST_NODE_TYPES.VariableDeclarator, | ||
].includes(parent.type)) { | ||
const variable = utils_1.ASTUtils.findVariable(context.getScope(), 'require'); | ||
if (!(variable === null || variable === void 0 ? void 0 : variable.identifiers.length)) { | ||
if ([ | ||
utils_1.AST_NODE_TYPES.CallExpression, | ||
utils_1.AST_NODE_TYPES.MemberExpression, | ||
utils_1.AST_NODE_TYPES.NewExpression, | ||
utils_1.AST_NODE_TYPES.TSAsExpression, | ||
utils_1.AST_NODE_TYPES.TSTypeAssertion, | ||
utils_1.AST_NODE_TYPES.VariableDeclarator, | ||
].includes(parent.type)) { | ||
const variable = utils_1.ASTUtils.findVariable((0, eslint_utils_1.getScope)(context), 'require'); | ||
if (!variable?.identifiers.length) { | ||
context.report({ | ||
@@ -63,0 +39,0 @@ node, |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'non-nullable-type-assertion-style', | ||
@@ -36,3 +37,3 @@ meta: { | ||
description: 'Enforce non-null assertions over explicit type casts', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
requiresTypeChecking: true, | ||
@@ -49,7 +50,6 @@ }, | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const getTypesIfNotLoose = (node) => { | ||
const type = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node)); | ||
const type = services.getTypeAtLocation(node); | ||
if (tsutils.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { | ||
@@ -73,5 +73,3 @@ return undefined; | ||
} | ||
else { | ||
return ((type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0); | ||
} | ||
return (type.flags & (ts.TypeFlags.Null | ts.TypeFlags.Undefined)) !== 0; | ||
}; | ||
@@ -115,5 +113,9 @@ const sameTypeWithoutNullish = (assertedTypes, originalTypes) => { | ||
if (sameTypeWithoutNullish(assertedTypes, originalTypes)) { | ||
const expressionSourceCode = sourceCode.getText(node.expression); | ||
const higherPrecedenceThanUnary = (0, util_1.getOperatorPrecedence)(services.esTreeNodeToTSNodeMap.get(node.expression).kind, ts.SyntaxKind.Unknown) > util_1.OperatorPrecedence.Unary; | ||
context.report({ | ||
fix(fixer) { | ||
return fixer.replaceText(node, `${sourceCode.getText(node.expression)}!`); | ||
return fixer.replaceText(node, higherPrecedenceThanUnary | ||
? `${expressionSourceCode}!` | ||
: `(${expressionSourceCode})!`); | ||
}, | ||
@@ -120,0 +122,0 @@ messageId: 'preferNonNullAssertion', |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -10,7 +11,9 @@ const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
// eslint-disable-next-line eslint-plugin/prefer-message-ids,eslint-plugin/require-meta-type,eslint-plugin/require-meta-schema,eslint-plugin/require-meta-fixable -- all in base rule - https://github.com/not-an-aardvark/eslint-plugin-eslint-plugin/issues/274 | ||
meta: Object.assign(Object.assign({}, baseRule.meta), { docs: { | ||
meta: { | ||
...baseRule.meta, | ||
docs: { | ||
description: 'Enforce consistent spacing inside braces', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
} }), | ||
}, | ||
}, | ||
defaultOptions: ['never'], | ||
@@ -21,3 +24,3 @@ create(context) { | ||
const spaced = firstOption === 'always'; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
/** | ||
@@ -47,5 +50,5 @@ * Determines whether an option is set, relative to the spacing option. | ||
function reportNoBeginningSpace(node, token) { | ||
const nextToken = context | ||
.getSourceCode() | ||
.getTokenAfter(token, { includeComments: true }); | ||
const nextToken = (0, eslint_utils_1.getSourceCode)(context).getTokenAfter(token, { | ||
includeComments: true, | ||
}); | ||
context.report({ | ||
@@ -69,5 +72,5 @@ node, | ||
function reportNoEndingSpace(node, token) { | ||
const previousToken = context | ||
.getSourceCode() | ||
.getTokenBefore(token, { includeComments: true }); | ||
const previousToken = (0, eslint_utils_1.getSourceCode)(context).getTokenBefore(token, { | ||
includeComments: true, | ||
}); | ||
context.report({ | ||
@@ -195,3 +198,5 @@ node, | ||
const rules = baseRule.create(context); | ||
return Object.assign(Object.assign({}, rules), { TSMappedType(node) { | ||
return { | ||
...rules, | ||
TSMappedType(node) { | ||
const first = sourceCode.getFirstToken(node); | ||
@@ -220,5 +225,6 @@ const last = sourceCode.getLastToken(node); | ||
validateBraceSpacing(node, first, second, penultimate, last); | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=object-curly-spacing.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const LT = `[${Array.from(new Set(['\r\n', '\r', '\n', '\u2028', '\u2029'])).join('')}]`; | ||
@@ -40,4 +18,3 @@ const PADDING_LINE_SEQUENCE = new RegExp(String.raw `^(\s*?${LT})\s*${LT}(\s*;?)$`, 'u'); | ||
test(node, sourceCode) { | ||
var _a; | ||
const isSameKeyword = ((_a = sourceCode.getFirstToken(node)) === null || _a === void 0 ? void 0 : _a.value) === keyword; | ||
const isSameKeyword = sourceCode.getFirstToken(node)?.value === keyword; | ||
const isSameType = Array.isArray(type) | ||
@@ -96,5 +73,3 @@ ? type.some(val => val === node.type) | ||
function skipChainExpression(node) { | ||
return node && node.type === utils_1.AST_NODE_TYPES.ChainExpression | ||
? node.expression | ||
: node; | ||
return node.type === utils_1.AST_NODE_TYPES.ChainExpression ? node.expression : node; | ||
} | ||
@@ -118,3 +93,3 @@ /** | ||
} | ||
return util.isFunction(node); | ||
return (0, util_1.isFunction)(node); | ||
} | ||
@@ -132,5 +107,5 @@ } | ||
if (node.type === utils_1.AST_NODE_TYPES.VariableDeclaration) { | ||
const declaration = node.declarations[0]; | ||
if (declaration === null || declaration === void 0 ? void 0 : declaration.init) { | ||
let call = declaration === null || declaration === void 0 ? void 0 : declaration.init; | ||
const declaration = node.declarations.at(0); | ||
if (declaration?.init) { | ||
let call = declaration.init; | ||
while (call.type === utils_1.AST_NODE_TYPES.MemberExpression) { | ||
@@ -169,4 +144,4 @@ call = call.object; | ||
// Checks the last token is a closing brace of blocks. | ||
const lastToken = sourceCode.getLastToken(node, util.isNotSemicolonToken); | ||
const belongingNode = lastToken && util.isClosingBraceToken(lastToken) | ||
const lastToken = sourceCode.getLastToken(node, util_1.isNotSemicolonToken); | ||
const belongingNode = lastToken && (0, util_1.isClosingBraceToken)(lastToken) | ||
? sourceCode.getNodeByRangeIndex(lastToken.range[0]) | ||
@@ -185,10 +160,9 @@ : null; | ||
function isDirective(node, sourceCode) { | ||
var _a, _b; | ||
return (node.type === utils_1.AST_NODE_TYPES.ExpressionStatement && | ||
(((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Program || | ||
(((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.BlockStatement && | ||
util.isFunction(node.parent.parent))) && | ||
(node.parent.type === utils_1.AST_NODE_TYPES.Program || | ||
(node.parent.type === utils_1.AST_NODE_TYPES.BlockStatement && | ||
(0, util_1.isFunction)(node.parent.parent))) && | ||
node.expression.type === utils_1.AST_NODE_TYPES.Literal && | ||
typeof node.expression.value === 'string' && | ||
!util.isParenthesized(node.expression, sourceCode)); | ||
!(0, util_1.isParenthesized)(node.expression, sourceCode)); | ||
} | ||
@@ -273,3 +247,3 @@ /** | ||
prevToken.range[0] >= node.range[0] && | ||
util.isSemicolonToken(semiToken) && | ||
(0, util_1.isSemicolonToken)(semiToken) && | ||
semiToken.loc.start.line !== prevToken.loc.end.line && | ||
@@ -327,4 +301,3 @@ semiToken.loc.end.line === nextToken.loc.start.line; | ||
const end = nextToken.range[0]; | ||
const text = context | ||
.getSourceCode() | ||
const text = (0, eslint_utils_1.getSourceCode)(context) | ||
.text.slice(start, end) | ||
@@ -357,3 +330,3 @@ .replace(PADDING_LINE_SEQUENCE, replacerToRemovePaddingLines); | ||
fix(fixer) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
let prevToken = getActualLastToken(prevNode, sourceCode); | ||
@@ -383,3 +356,3 @@ const nextToken = sourceCode.getFirstTokenBetween(prevToken, nextNode, { | ||
filter(token) { | ||
if (util.isTokenOnSameLine(prevToken, token)) { | ||
if ((0, util_1.isTokenOnSameLine)(prevToken, token)) { | ||
prevToken = token; | ||
@@ -391,3 +364,3 @@ return false; | ||
}) || nextNode; | ||
const insertText = util.isTokenOnSameLine(prevToken, nextToken) | ||
const insertText = (0, util_1.isTokenOnSameLine)(prevToken, nextToken) | ||
? '\n\n' | ||
@@ -475,3 +448,3 @@ : '\n'; | ||
//------------------------------------------------------------------------------ | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'padding-line-between-statements', | ||
@@ -482,3 +455,2 @@ meta: { | ||
description: 'Require or disallow padding lines between statements', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -488,5 +460,7 @@ }, | ||
hasSuggestions: false, | ||
// This is intentionally an array schema as you can pass 0..n config objects | ||
schema: { | ||
$defs: { | ||
paddingType: { | ||
type: 'string', | ||
enum: Object.keys(PaddingTypes), | ||
@@ -496,6 +470,12 @@ }, | ||
anyOf: [ | ||
{ enum: Object.keys(StatementTypes) }, | ||
{ | ||
type: 'string', | ||
enum: Object.keys(StatementTypes), | ||
}, | ||
{ | ||
type: 'array', | ||
items: { enum: Object.keys(StatementTypes) }, | ||
items: { | ||
type: 'string', | ||
enum: Object.keys(StatementTypes), | ||
}, | ||
minItems: 1, | ||
@@ -509,2 +489,3 @@ uniqueItems: true, | ||
type: 'array', | ||
additionalItems: false, | ||
items: { | ||
@@ -520,3 +501,2 @@ type: 'object', | ||
}, | ||
additionalItems: false, | ||
}, | ||
@@ -530,5 +510,5 @@ messages: { | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
// eslint-disable-next-line no-restricted-syntax -- We need all raw options. | ||
const configureList = context.options || []; | ||
const configureList = context.options; | ||
let scopeInfo = null; | ||
@@ -535,0 +515,0 @@ /** |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'parameter-properties', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Require or disallow parameter properties in class constructors', | ||
recommended: false, | ||
}, | ||
@@ -41,36 +18,34 @@ messages: { | ||
}, | ||
schema: { | ||
$defs: { | ||
modifier: { | ||
enum: [ | ||
'readonly', | ||
'private', | ||
'protected', | ||
'public', | ||
'private readonly', | ||
'protected readonly', | ||
'public readonly', | ||
], | ||
schema: [ | ||
{ | ||
$defs: { | ||
modifier: { | ||
type: 'string', | ||
enum: [ | ||
'readonly', | ||
'private', | ||
'protected', | ||
'public', | ||
'private readonly', | ||
'protected readonly', | ||
'public readonly', | ||
], | ||
}, | ||
}, | ||
}, | ||
prefixItems: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
allow: { | ||
type: 'array', | ||
items: { | ||
$ref: '#/$defs/modifier', | ||
}, | ||
minItems: 1, | ||
type: 'object', | ||
properties: { | ||
allow: { | ||
type: 'array', | ||
items: { | ||
$ref: '#/items/0/$defs/modifier', | ||
}, | ||
prefer: { | ||
enum: ['class-property', 'parameter-property'], | ||
}, | ||
}, | ||
additionalProperties: false, | ||
prefer: { | ||
type: 'string', | ||
enum: ['class-property', 'parameter-property'], | ||
}, | ||
}, | ||
], | ||
type: 'array', | ||
}, | ||
additionalProperties: false, | ||
}, | ||
], | ||
}, | ||
@@ -134,3 +109,3 @@ defaultOptions: [ | ||
} | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function typeAnnotationsMatch(classProperty, constructorParameter) { | ||
@@ -176,3 +151,2 @@ if (!classProperty.typeAnnotation || | ||
'MethodDefinition[kind="constructor"]'(node) { | ||
var _a, _b; | ||
for (const parameter of node.value.params) { | ||
@@ -183,3 +157,3 @@ if (parameter.type === utils_1.AST_NODE_TYPES.Identifier) { | ||
} | ||
for (const statement of (_b = (_a = node.value.body) === null || _a === void 0 ? void 0 : _a.body) !== null && _b !== void 0 ? _b : []) { | ||
for (const statement of node.value.body?.body ?? []) { | ||
if (statement.type !== utils_1.AST_NODE_TYPES.ExpressionStatement || | ||
@@ -186,0 +160,0 @@ statement.expression.type !== utils_1.AST_NODE_TYPES.AssignmentExpression || |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-as-const', | ||
@@ -34,3 +11,3 @@ meta: { | ||
description: 'Enforce the use of `as const` over literal type', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -37,0 +14,0 @@ fixable: 'code', |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-enum-initializers', | ||
@@ -33,3 +11,2 @@ meta: { | ||
description: 'Require each enum member value to be explicitly initialized', | ||
recommended: false, | ||
}, | ||
@@ -45,3 +22,3 @@ hasSuggestions: true, | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function TSEnumDeclaration(node) { | ||
@@ -48,0 +25,0 @@ const { members } = node; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-for-of', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Enforce the use of `for-of` loop over the standard `for` loop where possible', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -45,3 +23,3 @@ messages: { | ||
function isSingleVariableDeclaration(node) { | ||
return ((node === null || node === void 0 ? void 0 : node.type) === utils_1.AST_NODE_TYPES.VariableDeclaration && | ||
return (node?.type === utils_1.AST_NODE_TYPES.VariableDeclaration && | ||
node.kind !== 'const' && | ||
@@ -60,3 +38,3 @@ node.declarations.length === 1); | ||
function isLessThanLengthExpression(node, name) { | ||
if ((node === null || node === void 0 ? void 0 : node.type) === utils_1.AST_NODE_TYPES.BinaryExpression && | ||
if (node?.type === utils_1.AST_NODE_TYPES.BinaryExpression && | ||
node.operator === '<' && | ||
@@ -102,3 +80,2 @@ isMatchingIdentifier(node.left, name) && | ||
function isAssignee(node) { | ||
var _a; | ||
const parent = node.parent; | ||
@@ -135,3 +112,3 @@ if (!parent) { | ||
parent.value === node && | ||
((_a = parent.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ObjectExpression && | ||
parent.parent.type === utils_1.AST_NODE_TYPES.ObjectExpression && | ||
isAssignee(parent.parent)) { | ||
@@ -143,3 +120,3 @@ return true; | ||
function isIndexOnlyUsedWithArray(body, indexVar, arrayExpression) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const arrayText = sourceCode.getText(arrayExpression); | ||
@@ -150,4 +127,3 @@ return indexVar.references.every(reference => { | ||
return (!contains(body, id) || | ||
(node !== undefined && | ||
node.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
(node.type === utils_1.AST_NODE_TYPES.MemberExpression && | ||
node.object.type !== utils_1.AST_NODE_TYPES.ThisExpression && | ||
@@ -175,3 +151,3 @@ node.property === id && | ||
} | ||
const [indexVar] = context.getDeclaredVariables(node.init); | ||
const [indexVar] = (0, eslint_utils_1.getDeclaredVariables)(context, node.init); | ||
if (isIncrement(node.update, indexName) && | ||
@@ -178,0 +154,0 @@ isIndexOnlyUsedWithArray(node.body, indexVar, arrayExpression)) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.phrases = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.phrases = { | ||
@@ -33,3 +11,3 @@ [utils_1.AST_NODE_TYPES.TSTypeLiteral]: 'Type literal', | ||
}; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-function-type', | ||
@@ -39,3 +17,3 @@ meta: { | ||
description: 'Enforce using function types instead of interfaces with call signatures', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -52,3 +30,3 @@ fixable: 'code', | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
/** | ||
@@ -59,3 +37,3 @@ * Checks if there the interface has exactly one supertype that isn't named 'Function' | ||
function hasOneSupertype(node) { | ||
if (!node.extends || node.extends.length === 0) { | ||
if (node.extends.length === 0) { | ||
return false; | ||
@@ -94,3 +72,3 @@ } | ||
member.returnType !== undefined) { | ||
if ((tsThisTypes === null || tsThisTypes === void 0 ? void 0 : tsThisTypes.length) && | ||
if (tsThisTypes?.length && | ||
node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) { | ||
@@ -108,4 +86,3 @@ // the message can be confusing if we don't point directly to the `this` node instead of the whole member | ||
} | ||
const fixable = node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration; | ||
const fixable = node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration; | ||
const fix = fixable | ||
@@ -139,4 +116,3 @@ ? null | ||
} | ||
const isParentExported = node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration; | ||
const isParentExported = node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration; | ||
if (node.type === utils_1.AST_NODE_TYPES.TSInterfaceDeclaration && | ||
@@ -143,0 +119,0 @@ isParentExported) { |
@@ -28,2 +28,3 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const ts = __importStar(require("typescript")); | ||
@@ -49,5 +50,5 @@ const util_1 = require("../util"); | ||
create(context) { | ||
const globalScope = context.getScope(); | ||
const globalScope = (0, eslint_utils_1.getScope)(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const types = services.program.getTypeChecker(); | ||
const checker = services.program.getTypeChecker(); | ||
function isNumber(node, value) { | ||
@@ -123,7 +124,22 @@ const evaluated = (0, util_1.getStaticValue)(node, globalScope); | ||
} | ||
function escapeString(str) { | ||
const EscapeMap = { | ||
'\0': '\\0', | ||
"'": "\\'", | ||
'\\': '\\\\', | ||
'\n': '\\n', | ||
'\r': '\\r', | ||
'\v': '\\v', | ||
'\t': '\\t', | ||
'\f': '\\f', | ||
// "\b" cause unexpected replacements | ||
// '\b': '\\b', | ||
}; | ||
const replaceRegex = new RegExp(Object.values(EscapeMap).join('|'), 'g'); | ||
return str.replace(replaceRegex, char => EscapeMap[char]); | ||
} | ||
function checkArrayIndexOf(node, allowFixing) { | ||
var _a, _b, _c; | ||
// Check if the comparison is equivalent to `includes()`. | ||
const callNode = node.parent; | ||
const compareNode = (((_a = callNode.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ChainExpression | ||
const compareNode = (callNode.parent.type === utils_1.AST_NODE_TYPES.ChainExpression | ||
? callNode.parent.parent | ||
@@ -136,5 +152,5 @@ : callNode.parent); | ||
// Get the symbol of `indexOf` method. | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node.property); | ||
const indexofMethodDeclarations = (_b = types | ||
.getSymbolAtLocation(tsNode)) === null || _b === void 0 ? void 0 : _b.getDeclarations(); | ||
const indexofMethodDeclarations = services | ||
.getSymbolAtLocation(node.property) | ||
?.getDeclarations(); | ||
if (indexofMethodDeclarations == null || | ||
@@ -148,7 +164,7 @@ indexofMethodDeclarations.length === 0) { | ||
const typeDecl = instanceofMethodDecl.parent; | ||
const type = types.getTypeAtLocation(typeDecl); | ||
const includesMethodDecl = (_c = type | ||
.getProperty('includes')) === null || _c === void 0 ? void 0 : _c.getDeclarations(); | ||
if (includesMethodDecl == null || | ||
!includesMethodDecl.some(includesMethodDecl => hasSameParameters(includesMethodDecl, instanceofMethodDecl))) { | ||
const type = checker.getTypeAtLocation(typeDecl); | ||
const includesMethodDecl = type | ||
.getProperty('includes') | ||
?.getDeclarations(); | ||
if (!includesMethodDecl?.some(includesMethodDecl => hasSameParameters(includesMethodDecl, instanceofMethodDecl))) { | ||
return; | ||
@@ -158,11 +174,15 @@ } | ||
// Report it. | ||
context.report(Object.assign({ node: compareNode, messageId: 'preferIncludes' }, (allowFixing && { | ||
*fix(fixer) { | ||
if (negative) { | ||
yield fixer.insertTextBefore(callNode, '!'); | ||
} | ||
yield fixer.replaceText(node.property, 'includes'); | ||
yield fixer.removeRange([callNode.range[1], compareNode.range[1]]); | ||
}, | ||
}))); | ||
context.report({ | ||
node: compareNode, | ||
messageId: 'preferIncludes', | ||
...(allowFixing && { | ||
*fix(fixer) { | ||
if (negative) { | ||
yield fixer.insertTextBefore(callNode, '!'); | ||
} | ||
yield fixer.replaceText(node.property, 'includes'); | ||
yield fixer.removeRange([callNode.range[1], compareNode.range[1]]); | ||
}, | ||
}), | ||
}); | ||
} | ||
@@ -179,6 +199,5 @@ return { | ||
// /bar/.test(foo) | ||
'CallExpression > MemberExpression.callee[property.name="test"][computed=false]'(node) { | ||
var _a; | ||
'CallExpression[arguments.length=1] > MemberExpression.callee[property.name="test"][computed=false]'(node) { | ||
const callNode = node.parent; | ||
const text = callNode.arguments.length === 1 ? parseRegExp(node.object) : null; | ||
const text = parseRegExp(node.object); | ||
if (text == null) { | ||
@@ -189,6 +208,6 @@ return; | ||
const argument = callNode.arguments[0]; | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(argument); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(types, tsNode); | ||
const includesMethodDecl = (_a = type | ||
.getProperty('includes')) === null || _a === void 0 ? void 0 : _a.getDeclarations(); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, argument); | ||
const includesMethodDecl = type | ||
.getProperty('includes') | ||
?.getDeclarations(); | ||
if (includesMethodDecl == null) { | ||
@@ -208,2 +227,3 @@ return; | ||
yield fixer.removeRange([callNode.range[0], argNode.range[0]]); | ||
yield fixer.removeRange([argNode.range[1], callNode.range[1]]); | ||
if (needsParen) { | ||
@@ -213,3 +233,3 @@ yield fixer.insertTextBefore(argNode, '('); | ||
} | ||
yield fixer.insertTextAfter(argNode, `${node.optional ? '?.' : '.'}includes('${text}'`); | ||
yield fixer.insertTextAfter(argNode, `${node.optional ? '?.' : '.'}includes('${escapeString(text)}')`); | ||
}, | ||
@@ -216,0 +236,0 @@ }); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-namespace-keyword', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Require using `namespace` keyword over `module` keyword to declare custom TypeScript modules', | ||
recommended: 'error', | ||
recommended: 'stylistic', | ||
}, | ||
@@ -45,7 +23,7 @@ fixable: 'code', | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
return { | ||
TSModuleDeclaration(node) { | ||
// Do nothing if the name is a string. | ||
if (!node.id || node.id.type === utils_1.AST_NODE_TYPES.Literal) { | ||
if (node.id.type === utils_1.AST_NODE_TYPES.Literal) { | ||
return; | ||
@@ -52,0 +30,0 @@ } |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-nullish-coalescing', | ||
@@ -36,4 +37,4 @@ meta: { | ||
docs: { | ||
description: 'Enforce using the nullish coalescing operator instead of logical chaining', | ||
recommended: 'strict', | ||
description: 'Enforce using the nullish coalescing operator instead of logical assignments or chaining', | ||
recommended: 'stylistic', | ||
requiresTypeChecking: true, | ||
@@ -52,6 +53,6 @@ }, | ||
properties: { | ||
ignoreConditionalTests: { | ||
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: { | ||
type: 'boolean', | ||
}, | ||
ignoreTernaryTests: { | ||
ignoreConditionalTests: { | ||
type: 'boolean', | ||
@@ -62,3 +63,20 @@ }, | ||
}, | ||
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: { | ||
ignorePrimitives: { | ||
oneOf: [ | ||
{ | ||
type: 'object', | ||
properties: { | ||
bigint: { type: 'boolean' }, | ||
boolean: { type: 'boolean' }, | ||
number: { type: 'boolean' }, | ||
string: { type: 'boolean' }, | ||
}, | ||
}, | ||
{ | ||
type: 'boolean', | ||
enum: [true], | ||
}, | ||
], | ||
}, | ||
ignoreTernaryTests: { | ||
type: 'boolean', | ||
@@ -73,12 +91,18 @@ }, | ||
{ | ||
ignoreConditionalTests: true, | ||
ignoreTernaryTests: true, | ||
ignoreMixedLogicalExpressions: true, | ||
allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, | ||
ignoreConditionalTests: false, | ||
ignoreTernaryTests: false, | ||
ignoreMixedLogicalExpressions: false, | ||
ignorePrimitives: { | ||
bigint: false, | ||
boolean: false, | ||
number: false, | ||
string: false, | ||
}, | ||
}, | ||
], | ||
create(context, [{ ignoreConditionalTests, ignoreTernaryTests, ignoreMixedLogicalExpressions, allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing, },]) { | ||
const parserServices = util.getParserServices(context); | ||
create(context, [{ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing, ignoreConditionalTests, ignoreMixedLogicalExpressions, ignorePrimitives, ignoreTernaryTests, },]) { | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const compilerOptions = parserServices.program.getCompilerOptions(); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
@@ -158,14 +182,14 @@ const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks'); | ||
for (const testNode of nodesInsideTestExpression) { | ||
if (util.isNullLiteral(testNode)) { | ||
if ((0, util_1.isNullLiteral)(testNode)) { | ||
hasNullCheck = true; | ||
} | ||
else if (util.isUndefinedIdentifier(testNode)) { | ||
else if ((0, util_1.isUndefinedIdentifier)(testNode)) { | ||
hasUndefinedCheck = true; | ||
} | ||
else if ((operator === '!==' || operator === '!=') && | ||
util.isNodeEqual(testNode, node.consequent)) { | ||
(0, util_1.isNodeEqual)(testNode, node.consequent)) { | ||
identifier = testNode; | ||
} | ||
else if ((operator === '===' || operator === '==') && | ||
util.isNodeEqual(testNode, node.alternate)) { | ||
(0, util_1.isNodeEqual)(testNode, node.alternate)) { | ||
identifier = testNode; | ||
@@ -191,3 +215,3 @@ } | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const flags = util.getTypeFlags(type); | ||
const flags = (0, util_1.getTypeFlags)(type); | ||
if (flags & (ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { | ||
@@ -226,3 +250,3 @@ return false; | ||
const type = checker.getTypeAtLocation(tsNode.left); | ||
const isNullish = util.isNullableType(type, { allowUndefined: true }); | ||
const isNullish = (0, util_1.isNullableType)(type, { allowUndefined: true }); | ||
if (!isNullish) { | ||
@@ -238,9 +262,26 @@ return; | ||
} | ||
const barBarOperator = util.nullThrows(sourceCode.getTokenAfter(node.left, token => token.type === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
token.value === node.operator), util.NullThrowsReasons.MissingToken('operator', node.type)); | ||
const ignorableFlags = [ | ||
(ignorePrimitives === true || ignorePrimitives.bigint) && | ||
ts.TypeFlags.BigInt, | ||
(ignorePrimitives === true || ignorePrimitives.boolean) && | ||
ts.TypeFlags.BooleanLiteral, | ||
(ignorePrimitives === true || ignorePrimitives.number) && | ||
ts.TypeFlags.Number, | ||
(ignorePrimitives === true || ignorePrimitives.string) && | ||
ts.TypeFlags.String, | ||
] | ||
.filter((flag) => typeof flag === 'number') | ||
.reduce((previous, flag) => previous | flag, 0); | ||
if (type.flags !== ts.TypeFlags.Null && | ||
type.flags !== ts.TypeFlags.Undefined && | ||
type.types.some(t => tsutils.isTypeFlagSet(t, ignorableFlags))) { | ||
return; | ||
} | ||
const barBarOperator = (0, util_1.nullThrows)(sourceCode.getTokenAfter(node.left, token => token.type === utils_1.AST_TOKEN_TYPES.Punctuator && | ||
token.value === node.operator), util_1.NullThrowsReasons.MissingToken('operator', node.type)); | ||
function* fix(fixer) { | ||
if (node.parent && util.isLogicalOrOperator(node.parent)) { | ||
if ((0, util_1.isLogicalOrOperator)(node.parent)) { | ||
// '&&' and '??' operations cannot be mixed without parentheses (e.g. a && b ?? c) | ||
if (node.left.type === utils_1.AST_NODE_TYPES.LogicalExpression && | ||
!util.isLogicalOrOperator(node.left.left)) { | ||
!(0, util_1.isLogicalOrOperator)(node.left.left)) { | ||
yield fixer.insertTextBefore(node.left.right, '('); | ||
@@ -305,3 +346,3 @@ } | ||
seen.add(current); | ||
if (current && current.type === utils_1.AST_NODE_TYPES.LogicalExpression) { | ||
if (current.type === utils_1.AST_NODE_TYPES.LogicalExpression) { | ||
if (current.operator === '&&') { | ||
@@ -308,0 +349,0 @@ return true; |
@@ -27,21 +27,8 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils_1 = require("tsutils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
/* | ||
The AST is always constructed such the first element is always the deepest element. | ||
I.e. for this code: `foo && foo.bar && foo.bar.baz && foo.bar.baz.buzz` | ||
The AST will look like this: | ||
{ | ||
left: { | ||
left: { | ||
left: foo | ||
right: foo.bar | ||
} | ||
right: foo.bar.baz | ||
} | ||
right: foo.bar.baz.buzz | ||
} | ||
*/ | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
const analyzeChain_1 = require("./prefer-optional-chain-utils/analyzeChain"); | ||
const gatherLogicalOperands_1 = require("./prefer-optional-chain-utils/gatherLogicalOperands"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-optional-chain', | ||
@@ -52,4 +39,6 @@ meta: { | ||
description: 'Enforce using concise optional chain expressions instead of chained logical ands, negated logical ors, or empty objects', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
requiresTypeChecking: true, | ||
}, | ||
fixable: 'code', | ||
hasSuggestions: true, | ||
@@ -60,9 +49,61 @@ messages: { | ||
}, | ||
schema: [], | ||
schema: [ | ||
{ | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
checkAny: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `any` when inspecting "loose boolean" operands.', | ||
}, | ||
checkUnknown: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `unknown` when inspecting "loose boolean" operands.', | ||
}, | ||
checkString: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `string` when inspecting "loose boolean" operands.', | ||
}, | ||
checkNumber: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `number` when inspecting "loose boolean" operands.', | ||
}, | ||
checkBoolean: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `boolean` when inspecting "loose boolean" operands.', | ||
}, | ||
checkBigInt: { | ||
type: 'boolean', | ||
description: 'Check operands that are typed as `bigint` when inspecting "loose boolean" operands.', | ||
}, | ||
requireNullish: { | ||
type: 'boolean', | ||
description: 'Skip operands that are not typed with `null` and/or `undefined` when inspecting "loose boolean" operands.', | ||
}, | ||
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing: { | ||
type: 'boolean', | ||
description: 'Allow autofixers that will change the return type of the expression. This option is considered unsafe as it may break the build.', | ||
}, | ||
}, | ||
}, | ||
], | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const parserServices = util.getParserServices(context, true); | ||
defaultOptions: [ | ||
{ | ||
checkAny: true, | ||
checkUnknown: true, | ||
checkString: true, | ||
checkNumber: true, | ||
checkBoolean: true, | ||
checkBigInt: true, | ||
requireNullish: false, | ||
allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing: false, | ||
}, | ||
], | ||
create(context, [options]) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const seenLogicals = new Set(); | ||
return { | ||
// specific handling for `(foo ?? {}).bar` / `(foo || {}).bar` | ||
'LogicalExpression[operator="||"], LogicalExpression[operator="??"]'(node) { | ||
@@ -75,3 +116,2 @@ const leftNode = node.left; | ||
if (!isRightNodeAnEmptyObjectLiteral || | ||
!parentNode || | ||
parentNode.type !== utils_1.AST_NODE_TYPES.MemberExpression || | ||
@@ -81,14 +121,15 @@ parentNode.optional) { | ||
} | ||
seenLogicals.add(node); | ||
function isLeftSideLowerPrecedence() { | ||
const logicalTsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const leftTsNode = parserServices.esTreeNodeToTSNodeMap.get(leftNode); | ||
const operator = (0, tsutils_1.isBinaryExpression)(logicalTsNode) | ||
const operator = ts.isBinaryExpression(logicalTsNode) | ||
? logicalTsNode.operatorToken.kind | ||
: ts.SyntaxKind.Unknown; | ||
const leftPrecedence = util.getOperatorPrecedence(leftTsNode.kind, operator); | ||
return leftPrecedence < util.OperatorPrecedence.LeftHandSide; | ||
const leftPrecedence = (0, util_1.getOperatorPrecedence)(leftTsNode.kind, operator); | ||
return leftPrecedence < util_1.OperatorPrecedence.LeftHandSide; | ||
} | ||
context.report({ | ||
node: parentNode, | ||
messageId: 'optionalChainSuggest', | ||
messageId: 'preferOptionalChain', | ||
suggest: [ | ||
@@ -113,382 +154,28 @@ { | ||
}, | ||
[[ | ||
'LogicalExpression[operator="||"] > UnaryExpression[operator="!"] > Identifier', | ||
'LogicalExpression[operator="||"] > UnaryExpression[operator="!"] > MemberExpression', | ||
'LogicalExpression[operator="||"] > UnaryExpression[operator="!"] > ChainExpression > MemberExpression', | ||
'LogicalExpression[operator="||"] > UnaryExpression[operator="!"] > MetaProperty', | ||
].join(',')](initialIdentifierOrNotEqualsExpr) { | ||
// selector guarantees this cast | ||
const initialExpression = (initialIdentifierOrNotEqualsExpr.parent.type === | ||
utils_1.AST_NODE_TYPES.ChainExpression | ||
? initialIdentifierOrNotEqualsExpr.parent.parent | ||
: initialIdentifierOrNotEqualsExpr.parent).parent; | ||
if (initialExpression.left.type !== utils_1.AST_NODE_TYPES.UnaryExpression || | ||
initialExpression.left.argument !== initialIdentifierOrNotEqualsExpr) { | ||
// the node(identifier or member expression) is not the deepest left node | ||
'LogicalExpression[operator!="??"]'(node) { | ||
if (seenLogicals.has(node)) { | ||
return; | ||
} | ||
// walk up the tree to figure out how many logical expressions we can include | ||
let previous = initialExpression; | ||
let current = initialExpression; | ||
let previousLeftText = getText(initialIdentifierOrNotEqualsExpr); | ||
let optionallyChainedCode = previousLeftText; | ||
let expressionCount = 1; | ||
while (current.type === utils_1.AST_NODE_TYPES.LogicalExpression) { | ||
if (current.right.type !== utils_1.AST_NODE_TYPES.UnaryExpression || | ||
!isValidChainTarget(current.right.argument, | ||
// only allow unary '!' with identifiers for the first chain - !foo || !foo() | ||
expressionCount === 1)) { | ||
break; | ||
const { operands, newlySeenLogicals } = (0, gatherLogicalOperands_1.gatherLogicalOperands)(node, parserServices, options); | ||
for (const logical of newlySeenLogicals) { | ||
seenLogicals.add(logical); | ||
} | ||
let currentChain = []; | ||
for (const operand of operands) { | ||
if (operand.type === "Invalid" /* OperandValidity.Invalid */) { | ||
(0, analyzeChain_1.analyzeChain)(context, sourceCode, parserServices, options, node.operator, currentChain); | ||
currentChain = []; | ||
} | ||
const { rightText, shouldBreak } = breakIfInvalid({ | ||
rightNode: current.right.argument, | ||
previousLeftText, | ||
}); | ||
if (shouldBreak) { | ||
break; | ||
else { | ||
currentChain.push(operand); | ||
} | ||
let invalidOptionallyChainedPrivateProperty; | ||
({ | ||
invalidOptionallyChainedPrivateProperty, | ||
expressionCount, | ||
previousLeftText, | ||
optionallyChainedCode, | ||
previous, | ||
current, | ||
} = normalizeRepeatingPatterns(rightText, expressionCount, previousLeftText, optionallyChainedCode, previous, current)); | ||
if (invalidOptionallyChainedPrivateProperty) { | ||
return; | ||
} | ||
} | ||
reportIfMoreThanOne({ | ||
expressionCount, | ||
previous, | ||
optionallyChainedCode, | ||
sourceCode, | ||
context, | ||
shouldHandleChainedAnds: false, | ||
}); | ||
}, | ||
[[ | ||
'LogicalExpression[operator="&&"] > Identifier', | ||
'LogicalExpression[operator="&&"] > MemberExpression', | ||
'LogicalExpression[operator="&&"] > ChainExpression > MemberExpression', | ||
'LogicalExpression[operator="&&"] > MetaProperty', | ||
'LogicalExpression[operator="&&"] > BinaryExpression[operator="!=="]', | ||
'LogicalExpression[operator="&&"] > BinaryExpression[operator="!="]', | ||
].join(',')](initialIdentifierOrNotEqualsExpr) { | ||
var _a; | ||
// selector guarantees this cast | ||
const initialExpression = (((_a = initialIdentifierOrNotEqualsExpr.parent) === null || _a === void 0 ? void 0 : _a.type) === | ||
utils_1.AST_NODE_TYPES.ChainExpression | ||
? initialIdentifierOrNotEqualsExpr.parent.parent | ||
: initialIdentifierOrNotEqualsExpr.parent); | ||
if (initialExpression.left !== initialIdentifierOrNotEqualsExpr) { | ||
// the node(identifier or member expression) is not the deepest left node | ||
return; | ||
// make sure to check whatever's left | ||
if (currentChain.length > 0) { | ||
(0, analyzeChain_1.analyzeChain)(context, sourceCode, parserServices, options, node.operator, currentChain); | ||
} | ||
if (!isValidChainTarget(initialIdentifierOrNotEqualsExpr, true)) { | ||
return; | ||
} | ||
// walk up the tree to figure out how many logical expressions we can include | ||
let previous = initialExpression; | ||
let current = initialExpression; | ||
let previousLeftText = getText(initialIdentifierOrNotEqualsExpr); | ||
let optionallyChainedCode = previousLeftText; | ||
let expressionCount = 1; | ||
while (current.type === utils_1.AST_NODE_TYPES.LogicalExpression) { | ||
if (!isValidChainTarget(current.right, | ||
// only allow identifiers for the first chain - foo && foo() | ||
expressionCount === 1)) { | ||
break; | ||
} | ||
const { rightText, shouldBreak } = breakIfInvalid({ | ||
rightNode: current.right, | ||
previousLeftText, | ||
}); | ||
if (shouldBreak) { | ||
break; | ||
} | ||
let invalidOptionallyChainedPrivateProperty; | ||
({ | ||
invalidOptionallyChainedPrivateProperty, | ||
expressionCount, | ||
previousLeftText, | ||
optionallyChainedCode, | ||
previous, | ||
current, | ||
} = normalizeRepeatingPatterns(rightText, expressionCount, previousLeftText, optionallyChainedCode, previous, current)); | ||
if (invalidOptionallyChainedPrivateProperty) { | ||
return; | ||
} | ||
} | ||
reportIfMoreThanOne({ | ||
expressionCount, | ||
previous, | ||
optionallyChainedCode, | ||
sourceCode, | ||
context, | ||
shouldHandleChainedAnds: true, | ||
}); | ||
}, | ||
}; | ||
function breakIfInvalid({ previousLeftText, rightNode, }) { | ||
let shouldBreak = false; | ||
const rightText = getText(rightNode); | ||
// can't just use startsWith because of cases like foo && fooBar.baz; | ||
const matchRegex = new RegExp(`^${ | ||
// escape regex characters | ||
previousLeftText.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}[^a-zA-Z0-9_$]`); | ||
if (!matchRegex.test(rightText) && | ||
// handle redundant cases like foo.bar && foo.bar | ||
previousLeftText !== rightText) { | ||
shouldBreak = true; | ||
} | ||
return { shouldBreak, leftText: previousLeftText, rightText }; | ||
} | ||
function getText(node) { | ||
if (node.type === utils_1.AST_NODE_TYPES.BinaryExpression) { | ||
return getText( | ||
// isValidChainTarget ensures this is type safe | ||
node.left); | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { | ||
const calleeText = getText( | ||
// isValidChainTarget ensures this is type safe | ||
node.callee); | ||
// ensure that the call arguments are left untouched, or else we can break cases that _need_ whitespace: | ||
// - JSX: <Foo Needs Space Between Attrs /> | ||
// - Unary Operators: typeof foo, await bar, delete baz | ||
const closingParenToken = util.nullThrows(sourceCode.getLastToken(node), util.NullThrowsReasons.MissingToken('closing parenthesis', node.type)); | ||
const openingParenToken = util.nullThrows(sourceCode.getFirstTokenBetween(node.callee, closingParenToken, util.isOpeningParenToken), util.NullThrowsReasons.MissingToken('opening parenthesis', node.type)); | ||
const argumentsText = sourceCode.text.substring(openingParenToken.range[0], closingParenToken.range[1]); | ||
return `${calleeText}${argumentsText}`; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.Identifier || | ||
node.type === utils_1.AST_NODE_TYPES.PrivateIdentifier) { | ||
return node.name; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.MetaProperty) { | ||
return `${node.meta.name}.${node.property.name}`; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.ThisExpression) { | ||
return 'this'; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.ChainExpression) { | ||
/* istanbul ignore if */ if (node.expression.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) { | ||
// this shouldn't happen | ||
return ''; | ||
} | ||
return getText(node.expression); | ||
} | ||
if (node.object.type === utils_1.AST_NODE_TYPES.TSNonNullExpression) { | ||
// Not supported mixing with TSNonNullExpression | ||
return ''; | ||
} | ||
return getMemberExpressionText(node); | ||
} | ||
/** | ||
* Gets a normalized representation of the given MemberExpression | ||
*/ | ||
function getMemberExpressionText(node) { | ||
let objectText; | ||
// cases should match the list in ALLOWED_MEMBER_OBJECT_TYPES | ||
switch (node.object.type) { | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
objectText = getMemberExpressionText(node.object); | ||
break; | ||
case utils_1.AST_NODE_TYPES.CallExpression: | ||
case utils_1.AST_NODE_TYPES.Identifier: | ||
case utils_1.AST_NODE_TYPES.MetaProperty: | ||
case utils_1.AST_NODE_TYPES.ThisExpression: | ||
objectText = getText(node.object); | ||
break; | ||
/* istanbul ignore next */ | ||
default: | ||
return ''; | ||
} | ||
let propertyText; | ||
if (node.computed) { | ||
// cases should match the list in ALLOWED_COMPUTED_PROP_TYPES | ||
switch (node.property.type) { | ||
case utils_1.AST_NODE_TYPES.Identifier: | ||
propertyText = getText(node.property); | ||
break; | ||
case utils_1.AST_NODE_TYPES.Literal: | ||
case utils_1.AST_NODE_TYPES.TemplateLiteral: | ||
case utils_1.AST_NODE_TYPES.BinaryExpression: | ||
propertyText = sourceCode.getText(node.property); | ||
break; | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
propertyText = getMemberExpressionText(node.property); | ||
break; | ||
/* istanbul ignore next */ | ||
default: | ||
return ''; | ||
} | ||
return `${objectText}${node.optional ? '?.' : ''}[${propertyText}]`; | ||
} | ||
else { | ||
// cases should match the list in ALLOWED_NON_COMPUTED_PROP_TYPES | ||
switch (node.property.type) { | ||
case utils_1.AST_NODE_TYPES.Identifier: | ||
propertyText = getText(node.property); | ||
break; | ||
case utils_1.AST_NODE_TYPES.PrivateIdentifier: | ||
propertyText = '#' + getText(node.property); | ||
break; | ||
default: | ||
propertyText = sourceCode.getText(node.property); | ||
} | ||
return `${objectText}${node.optional ? '?.' : '.'}${propertyText}`; | ||
} | ||
} | ||
}, | ||
}); | ||
const ALLOWED_MEMBER_OBJECT_TYPES = new Set([ | ||
utils_1.AST_NODE_TYPES.CallExpression, | ||
utils_1.AST_NODE_TYPES.Identifier, | ||
utils_1.AST_NODE_TYPES.MemberExpression, | ||
utils_1.AST_NODE_TYPES.ThisExpression, | ||
utils_1.AST_NODE_TYPES.MetaProperty, | ||
]); | ||
const ALLOWED_COMPUTED_PROP_TYPES = new Set([ | ||
utils_1.AST_NODE_TYPES.Identifier, | ||
utils_1.AST_NODE_TYPES.Literal, | ||
utils_1.AST_NODE_TYPES.MemberExpression, | ||
utils_1.AST_NODE_TYPES.TemplateLiteral, | ||
]); | ||
const ALLOWED_NON_COMPUTED_PROP_TYPES = new Set([ | ||
utils_1.AST_NODE_TYPES.Identifier, | ||
utils_1.AST_NODE_TYPES.PrivateIdentifier, | ||
]); | ||
function reportIfMoreThanOne({ expressionCount, previous, optionallyChainedCode, sourceCode, context, shouldHandleChainedAnds, }) { | ||
if (expressionCount > 1) { | ||
if (shouldHandleChainedAnds && | ||
previous.right.type === utils_1.AST_NODE_TYPES.BinaryExpression) { | ||
let operator = previous.right.operator; | ||
if (previous.right.operator === '!==' && | ||
// TODO(#4820): Use the type checker to know whether this is `null` | ||
previous.right.right.type === utils_1.AST_NODE_TYPES.Literal && | ||
previous.right.right.raw === 'null') { | ||
// case like foo !== null && foo.bar !== null | ||
operator = '!='; | ||
} | ||
// case like foo && foo.bar !== someValue | ||
optionallyChainedCode += ` ${operator} ${sourceCode.getText(previous.right.right)}`; | ||
} | ||
context.report({ | ||
node: previous, | ||
messageId: 'preferOptionalChain', | ||
suggest: [ | ||
{ | ||
messageId: 'optionalChainSuggest', | ||
fix: (fixer) => [ | ||
fixer.replaceText(previous, `${shouldHandleChainedAnds ? '' : '!'}${optionallyChainedCode}`), | ||
], | ||
}, | ||
], | ||
}); | ||
} | ||
} | ||
function normalizeRepeatingPatterns(rightText, expressionCount, previousLeftText, optionallyChainedCode, previous, current) { | ||
const leftText = previousLeftText; | ||
let invalidOptionallyChainedPrivateProperty = false; | ||
// omit weird doubled up expression that make no sense like foo.bar && foo.bar | ||
if (rightText !== previousLeftText) { | ||
expressionCount += 1; | ||
previousLeftText = rightText; | ||
/* | ||
Diff the left and right text to construct the fix string | ||
There are the following cases: | ||
1) | ||
rightText === 'foo.bar.baz.buzz' | ||
leftText === 'foo.bar.baz' | ||
diff === '.buzz' | ||
2) | ||
rightText === 'foo.bar.baz.buzz()' | ||
leftText === 'foo.bar.baz' | ||
diff === '.buzz()' | ||
3) | ||
rightText === 'foo.bar.baz.buzz()' | ||
leftText === 'foo.bar.baz.buzz' | ||
diff === '()' | ||
4) | ||
rightText === 'foo.bar.baz[buzz]' | ||
leftText === 'foo.bar.baz' | ||
diff === '[buzz]' | ||
5) | ||
rightText === 'foo.bar.baz?.buzz' | ||
leftText === 'foo.bar.baz' | ||
diff === '?.buzz' | ||
*/ | ||
const diff = rightText.replace(leftText, ''); | ||
if (diff.startsWith('.#')) { | ||
// Do not handle direct optional chaining on private properties because of a typescript bug (https://github.com/microsoft/TypeScript/issues/42734) | ||
// We still allow in computed properties | ||
invalidOptionallyChainedPrivateProperty = true; | ||
} | ||
if (diff.startsWith('?')) { | ||
// item was "pre optional chained" | ||
optionallyChainedCode += diff; | ||
} | ||
else { | ||
const needsDot = diff.startsWith('(') || diff.startsWith('['); | ||
optionallyChainedCode += `?${needsDot ? '.' : ''}${diff}`; | ||
} | ||
} | ||
previous = current; | ||
current = util.nullThrows(current.parent, util.NullThrowsReasons.MissingParent); | ||
return { | ||
invalidOptionallyChainedPrivateProperty, | ||
expressionCount, | ||
previousLeftText, | ||
optionallyChainedCode, | ||
previous, | ||
current, | ||
}; | ||
} | ||
function isValidChainTarget(node, allowIdentifier) { | ||
if (node.type === utils_1.AST_NODE_TYPES.ChainExpression) { | ||
return isValidChainTarget(node.expression, allowIdentifier); | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.MemberExpression) { | ||
const isObjectValid = ALLOWED_MEMBER_OBJECT_TYPES.has(node.object.type) && | ||
// make sure to validate the expression is of our expected structure | ||
isValidChainTarget(node.object, true); | ||
const isPropertyValid = node.computed | ||
? ALLOWED_COMPUTED_PROP_TYPES.has(node.property.type) && | ||
// make sure to validate the member expression is of our expected structure | ||
(node.property.type === utils_1.AST_NODE_TYPES.MemberExpression | ||
? isValidChainTarget(node.property, allowIdentifier) | ||
: true) | ||
: ALLOWED_NON_COMPUTED_PROP_TYPES.has(node.property.type); | ||
return isObjectValid && isPropertyValid; | ||
} | ||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { | ||
return isValidChainTarget(node.callee, allowIdentifier); | ||
} | ||
if (allowIdentifier && | ||
(node.type === utils_1.AST_NODE_TYPES.Identifier || | ||
node.type === utils_1.AST_NODE_TYPES.ThisExpression || | ||
node.type === utils_1.AST_NODE_TYPES.MetaProperty)) { | ||
return true; | ||
} | ||
/* | ||
special case for the following, where we only want the left | ||
- foo !== null | ||
- foo != null | ||
- foo !== undefined | ||
- foo != undefined | ||
*/ | ||
return (node.type === utils_1.AST_NODE_TYPES.BinaryExpression && | ||
['!==', '!='].includes(node.operator) && | ||
isValidChainTarget(node.left, allowIdentifier) && | ||
(util.isUndefinedIdentifier(node.right) || util.isNullLiteral(node.right))); | ||
} | ||
//# sourceMappingURL=prefer-optional-chain.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-readonly-parameter-types', | ||
@@ -34,3 +11,2 @@ meta: { | ||
description: 'Require function parameters to be typed as `readonly` to prevent accidental mutation of inputs', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -42,7 +18,12 @@ }, | ||
additionalProperties: false, | ||
properties: Object.assign({ checkParameterProperties: { | ||
properties: { | ||
allow: util_1.readonlynessOptionsSchema.properties.allow, | ||
checkParameterProperties: { | ||
type: 'boolean', | ||
}, ignoreInferredTypes: { | ||
}, | ||
ignoreInferredTypes: { | ||
type: 'boolean', | ||
} }, util.readonlynessOptionsSchema.properties), | ||
}, | ||
treatMethodsAsReadonly: util_1.readonlynessOptionsSchema.properties.treatMethodsAsReadonly, | ||
}, | ||
}, | ||
@@ -55,7 +36,11 @@ ], | ||
defaultOptions: [ | ||
Object.assign({ checkParameterProperties: true, ignoreInferredTypes: false }, util.readonlynessOptionsDefaults), | ||
{ | ||
allow: util_1.readonlynessOptionsDefaults.allow, | ||
checkParameterProperties: true, | ||
ignoreInferredTypes: false, | ||
treatMethodsAsReadonly: util_1.readonlynessOptionsDefaults.treatMethodsAsReadonly, | ||
}, | ||
], | ||
create(context, [{ checkParameterProperties, ignoreInferredTypes, treatMethodsAsReadonly }]) { | ||
const { esTreeNodeToTSNodeMap, program } = util.getParserServices(context); | ||
const checker = program.getTypeChecker(); | ||
create(context, [{ allow, checkParameterProperties, ignoreInferredTypes, treatMethodsAsReadonly, },]) { | ||
const services = (0, util_1.getParserServices)(context); | ||
return { | ||
@@ -84,6 +69,6 @@ [[ | ||
} | ||
const tsNode = esTreeNodeToTSNodeMap.get(actualParam); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
const isReadOnly = util.isTypeReadonly(checker, type, { | ||
const type = services.getTypeAtLocation(actualParam); | ||
const isReadOnly = (0, util_1.isTypeReadonly)(services.program, type, { | ||
treatMethodsAsReadonly: treatMethodsAsReadonly, | ||
allow, | ||
}); | ||
@@ -90,0 +75,0 @@ if (!isReadOnly) { |
@@ -27,5 +27,5 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
@@ -38,3 +38,3 @@ const functionScopeBoundaries = [ | ||
].join(', '); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-readonly', | ||
@@ -44,3 +44,2 @@ meta: { | ||
description: "Require private members to be marked as `readonly` if they're never modified outside of the constructor", | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -54,3 +53,3 @@ }, | ||
{ | ||
allowAdditionalProperties: false, | ||
additionalProperties: false, | ||
properties: { | ||
@@ -68,4 +67,4 @@ onlyInlineLambdas: { | ||
create(context, [{ onlyInlineLambdas }]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const classScopeStack = []; | ||
@@ -124,3 +123,3 @@ function handlePropertyAccessExpression(node, parent, classScope) { | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
if (ts.isConstructorDeclaration(tsNode)) { | ||
@@ -134,9 +133,9 @@ return false; | ||
return { | ||
esNode: parserServices.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
nameNode: parserServices.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
esNode: services.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
nameNode: services.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
}; | ||
} | ||
return { | ||
esNode: parserServices.tsNodeToESTreeNodeMap.get(violatingNode), | ||
nameNode: parserServices.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
esNode: services.tsNodeToESTreeNodeMap.get(violatingNode), | ||
nameNode: services.tsNodeToESTreeNodeMap.get(violatingNode.name), | ||
}; | ||
@@ -146,7 +145,7 @@ } | ||
'ClassDeclaration, ClassExpression'(node) { | ||
classScopeStack.push(new ClassScope(checker, parserServices.esTreeNodeToTSNodeMap.get(node), onlyInlineLambdas)); | ||
classScopeStack.push(new ClassScope(checker, services.esTreeNodeToTSNodeMap.get(node), onlyInlineLambdas)); | ||
}, | ||
'ClassDeclaration, ClassExpression:exit'() { | ||
const finalizedClassScope = classScopeStack.pop(); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
for (const violatingNode of finalizedClassScope.finalizeUnmodifiedPrivateNonReadonlys()) { | ||
@@ -166,3 +165,3 @@ const { esNode, nameNode } = getEsNodesFromViolatingNode(violatingNode); | ||
if (classScopeStack.length !== 0 && !node.computed) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
handlePropertyAccessExpression(tsNode, tsNode.parent, classScopeStack[classScopeStack.length - 1]); | ||
@@ -173,3 +172,3 @@ } | ||
if (utils_1.ASTUtils.isConstructor(node)) { | ||
classScopeStack[classScopeStack.length - 1].enterConstructor(parserServices.esTreeNodeToTSNodeMap.get(node)); | ||
classScopeStack[classScopeStack.length - 1].enterConstructor(services.esTreeNodeToTSNodeMap.get(node)); | ||
} | ||
@@ -216,3 +215,4 @@ else if (isFunctionScopeBoundaryInStack(node)) { | ||
addDeclaredVariable(node) { | ||
if (!tsutils.isModifierFlagSet(node, ts.ModifierFlags.Private) || | ||
if (!(tsutils.isModifierFlagSet(node, ts.ModifierFlags.Private) || | ||
node.name.kind === ts.SyntaxKind.PrivateIdentifier) || | ||
tsutils.isModifierFlagSet(node, ts.ModifierFlags.Readonly) || | ||
@@ -219,0 +219,0 @@ ts.isComputedPropertyName(node.name)) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getMemberExpressionName = (member) => { | ||
@@ -38,3 +16,3 @@ if (!member.computed) { | ||
}; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-reduce-type-parameter', | ||
@@ -56,4 +34,4 @@ meta: { | ||
create(context) { | ||
const service = util.getParserServices(context); | ||
const checker = service.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
return { | ||
@@ -65,9 +43,7 @@ 'CallExpression > MemberExpression.callee'(callee) { | ||
const [, secondArg] = callee.parent.arguments; | ||
if (callee.parent.arguments.length < 2 || | ||
!util.isTypeAssertion(secondArg)) { | ||
if (callee.parent.arguments.length < 2 || !(0, util_1.isTypeAssertion)(secondArg)) { | ||
return; | ||
} | ||
// Get the symbol of the `reduce` method. | ||
const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); | ||
const calleeObjType = util.getConstrainedTypeAtLocation(checker, tsNode); | ||
const calleeObjType = (0, util_1.getConstrainedTypeAtLocation)(services, callee.object); | ||
// Check the owner type of the `reduce` method. | ||
@@ -89,6 +65,4 @@ if (checker.isArrayType(calleeObjType)) { | ||
]; | ||
if (!callee.parent.typeParameters) { | ||
fixes.push(fixer.insertTextAfter(callee, `<${context | ||
.getSourceCode() | ||
.getText(secondArg.typeAnnotation)}>`)); | ||
if (!callee.parent.typeArguments) { | ||
fixes.push(fixer.insertTextAfter(callee, `<${(0, eslint_utils_1.getSourceCode)(context).getText(secondArg.typeAnnotation)}>`)); | ||
} | ||
@@ -95,0 +69,0 @@ return fixes; |
@@ -27,3 +27,4 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
@@ -45,3 +46,2 @@ var ArgumentType; | ||
description: 'Enforce `RegExp#exec` over `String#match` if no global flag is provided', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -55,6 +55,6 @@ }, | ||
create(context) { | ||
const globalScope = context.getScope(); | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const typeChecker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const globalScope = (0, eslint_utils_1.getScope)(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
/** | ||
@@ -65,3 +65,3 @@ * Check if a given node type is a string. | ||
function isStringType(type) { | ||
return (0, util_1.getTypeName)(typeChecker, type) === 'string'; | ||
return (0, util_1.getTypeName)(checker, type) === 'string'; | ||
} | ||
@@ -73,3 +73,3 @@ /** | ||
function isRegExpType(type) { | ||
return (0, util_1.getTypeName)(typeChecker, type) === 'RegExp'; | ||
return (0, util_1.getTypeName)(checker, type) === 'RegExp'; | ||
} | ||
@@ -91,5 +91,4 @@ function collectArgumentTypes(types) { | ||
node.type === utils_1.AST_NODE_TYPES.NewExpression) { | ||
const [, flags] = node.arguments; | ||
return (flags && | ||
flags.type === utils_1.AST_NODE_TYPES.Literal && | ||
const flags = node.arguments.at(1); | ||
return !!(flags?.type === utils_1.AST_NODE_TYPES.Literal && | ||
typeof flags.value === 'string' && | ||
@@ -106,3 +105,3 @@ flags.value.includes('g')); | ||
const argumentValue = (0, util_1.getStaticValue)(argumentNode, globalScope); | ||
if (!isStringType(typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(objectNode)))) { | ||
if (!isStringType(services.getTypeAtLocation(objectNode))) { | ||
return; | ||
@@ -119,3 +118,9 @@ } | ||
typeof argumentNode.value === 'string') { | ||
const regExp = RegExp(argumentNode.value); | ||
let regExp; | ||
try { | ||
regExp = RegExp(argumentNode.value); | ||
} | ||
catch { | ||
return; | ||
} | ||
return context.report({ | ||
@@ -132,3 +137,3 @@ node: memberNode.property, | ||
} | ||
const argumentType = typeChecker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(argumentNode)); | ||
const argumentType = services.getTypeAtLocation(argumentNode); | ||
const argumentTypes = collectArgumentTypes(tsutils.unionTypeParts(argumentType)); | ||
@@ -135,0 +140,0 @@ switch (argumentTypes) { |
@@ -46,4 +46,4 @@ "use strict"; | ||
create(context) { | ||
const parserServices = (0, util_1.getParserServices)(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
function tryGetNameInType(name, typeNode) { | ||
@@ -66,6 +66,4 @@ if (typeNode.type === utils_1.AST_NODE_TYPES.TSTypeReference && | ||
function isThisSpecifiedInParameters(originalFunc) { | ||
const firstArg = originalFunc.params[0]; | ||
return (firstArg && | ||
firstArg.type === utils_1.AST_NODE_TYPES.Identifier && | ||
firstArg.name === 'this'); | ||
const firstArg = originalFunc.params.at(0); | ||
return !!(firstArg?.type === utils_1.AST_NODE_TYPES.Identifier && firstArg.name === 'this'); | ||
} | ||
@@ -76,7 +74,7 @@ function isFunctionReturningThis(originalFunc, originalClass) { | ||
} | ||
const func = parserServices.esTreeNodeToTSNodeMap.get(originalFunc); | ||
const func = services.esTreeNodeToTSNodeMap.get(originalFunc); | ||
if (!func.body) { | ||
return false; | ||
} | ||
const classType = checker.getTypeAtLocation(parserServices.esTreeNodeToTSNodeMap.get(originalClass)); | ||
const classType = services.getTypeAtLocation(originalClass); | ||
if (func.body.kind !== ts.SyntaxKind.Block) { | ||
@@ -112,4 +110,3 @@ const type = checker.getTypeAtLocation(func.body); | ||
function checkFunction(originalFunc, originalClass) { | ||
var _a; | ||
const className = (_a = originalClass.id) === null || _a === void 0 ? void 0 : _a.name; | ||
const className = originalClass.id?.name; | ||
if (!className || !originalFunc.returnType) { | ||
@@ -135,5 +132,4 @@ return; | ||
'ClassBody > PropertyDefinition'(node) { | ||
var _a, _b; | ||
if (!(((_a = node.value) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.FunctionExpression || | ||
((_b = node.value) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)) { | ||
if (!(node.value?.type === utils_1.AST_NODE_TYPES.FunctionExpression || | ||
node.value?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)) { | ||
return; | ||
@@ -140,0 +136,0 @@ } |
@@ -5,2 +5,3 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -16,3 +17,3 @@ const EQ_OPERATORS = /^[=!]=/; | ||
description: 'Enforce using `String#startsWith` and `String#endsWith` over other equivalent methods of checking substrings', | ||
recommended: 'strict', | ||
recommended: 'stylistic', | ||
requiresTypeChecking: true, | ||
@@ -28,6 +29,6 @@ }, | ||
create(context) { | ||
const globalScope = context.getScope(); | ||
const sourceCode = context.getSourceCode(); | ||
const service = (0, util_1.getParserServices)(context); | ||
const typeChecker = service.program.getTypeChecker(); | ||
const globalScope = (0, eslint_utils_1.getScope)(context); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
/** | ||
@@ -38,4 +39,4 @@ * Check if a given node is a string. | ||
function isStringType(node) { | ||
const objectType = typeChecker.getTypeAtLocation(service.esTreeNodeToTSNodeMap.get(node)); | ||
return (0, util_1.getTypeName)(typeChecker, objectType) === 'string'; | ||
const objectType = services.getTypeAtLocation(node); | ||
return (0, util_1.getTypeName)(checker, objectType) === 'string'; | ||
} | ||
@@ -124,15 +125,13 @@ /** | ||
/** | ||
* Check if a given node is a negative index expression | ||
* | ||
* E.g. `s.slice(- <expr>)`, `s.substring(s.length - <expr>)` | ||
* | ||
* @param node The node to check. | ||
* @param expectedIndexedNode The node which is expected as the receiver of index expression. | ||
* Returns true if `node` is `-substring.length` or | ||
* `parentString.length - substring.length` | ||
*/ | ||
function isNegativeIndexExpression(node, expectedIndexedNode) { | ||
function isLengthAheadOfEnd(node, substring, parentString) { | ||
return ((node.type === utils_1.AST_NODE_TYPES.UnaryExpression && | ||
node.operator === '-') || | ||
node.operator === '-' && | ||
isLengthExpression(node.argument, substring)) || | ||
(node.type === utils_1.AST_NODE_TYPES.BinaryExpression && | ||
node.operator === '-' && | ||
isLengthExpression(node.left, expectedIndexedNode))); | ||
isLengthExpression(node.left, parentString) && | ||
isLengthExpression(node.right, substring))); | ||
} | ||
@@ -169,7 +168,9 @@ /** | ||
* @param pattern The RegExp pattern text to parse. | ||
* @param uFlag The Unicode flag of the RegExp. | ||
* @param unicode Whether the RegExp is unicode. | ||
*/ | ||
function parseRegExpText(pattern, uFlag) { | ||
function parseRegExpText(pattern, unicode) { | ||
// Parse it. | ||
const ast = regexpp.parsePattern(pattern, undefined, undefined, uFlag); | ||
const ast = regexpp.parsePattern(pattern, undefined, undefined, { | ||
unicode, | ||
}); | ||
if (ast.alternatives.length !== 1) { | ||
@@ -267,4 +268,3 @@ return null; | ||
function getParent(node) { | ||
var _a; | ||
return (0, util_1.nullThrows)(((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ChainExpression | ||
return (0, util_1.nullThrows)(node.parent?.type === utils_1.AST_NODE_TYPES.ChainExpression | ||
? node.parent.parent | ||
@@ -286,3 +286,3 @@ : node.parent, util_1.NullThrowsReasons.MissingParent); | ||
let indexNode = null; | ||
if ((parentNode === null || parentNode === void 0 ? void 0 : parentNode.type) === utils_1.AST_NODE_TYPES.CallExpression) { | ||
if (parentNode.type === utils_1.AST_NODE_TYPES.CallExpression) { | ||
if (parentNode.arguments.length === 1) { | ||
@@ -415,10 +415,30 @@ indexNode = parentNode.arguments[0]; | ||
} | ||
const isEndsWith = (callNode.arguments.length === 1 || | ||
(callNode.arguments.length === 2 && | ||
isLengthExpression(callNode.arguments[1], node.object))) && | ||
isNegativeIndexExpression(callNode.arguments[0], node.object); | ||
const isStartsWith = !isEndsWith && | ||
callNode.arguments.length === 2 && | ||
let isEndsWith = false; | ||
let isStartsWith = false; | ||
if (callNode.arguments.length === 1) { | ||
if ( | ||
// foo.slice(-bar.length) === bar | ||
// foo.slice(foo.length - bar.length) === bar | ||
isLengthAheadOfEnd(callNode.arguments[0], parentNode.right, node.object)) { | ||
isEndsWith = true; | ||
} | ||
} | ||
else if (callNode.arguments.length === 2) { | ||
if ( | ||
// foo.slice(0, bar.length) === bar | ||
isNumber(callNode.arguments[0], 0) && | ||
!isNegativeIndexExpression(callNode.arguments[1], node.object); | ||
isLengthExpression(callNode.arguments[1], parentNode.right)) { | ||
isStartsWith = true; | ||
} | ||
else if ( | ||
// foo.slice(foo.length - bar.length, foo.length) === bar | ||
// foo.slice(foo.length - bar.length, 0) === bar | ||
// foo.slice(-bar.length, foo.length) === bar | ||
// foo.slice(-bar.length, 0) === bar | ||
(isLengthExpression(callNode.arguments[1], node.object) || | ||
isNumber(callNode.arguments[1], 0)) && | ||
isLengthAheadOfEnd(callNode.arguments[0], parentNode.right, node.object)) { | ||
isEndsWith = true; | ||
} | ||
} | ||
if (!isStartsWith && !isEndsWith) { | ||
@@ -425,0 +445,0 @@ return; |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'prefer-ts-expect-error', | ||
@@ -46,3 +24,3 @@ meta: { | ||
const tsIgnoreRegExpMultiLine = /^\s*(?:\/|\*)*\s*@ts-ignore/; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function isLineComment(comment) { | ||
@@ -49,0 +27,0 @@ return comment.type === utils_1.AST_TOKEN_TYPES.Line; |
@@ -27,5 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'promise-function-async', | ||
@@ -37,3 +38,2 @@ meta: { | ||
description: 'Require any function or method that returns a Promise to be marked async', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -91,11 +91,7 @@ }, | ||
]); | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function validateNode(node) { | ||
var _a; | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const signatures = checker | ||
.getTypeAtLocation(originalNode) | ||
.getCallSignatures(); | ||
const signatures = services.getTypeAtLocation(node).getCallSignatures(); | ||
if (!signatures.length) { | ||
@@ -105,3 +101,3 @@ return; | ||
const returnType = checker.getReturnTypeOfSignature(signatures[0]); | ||
if (!util.containsAllTypesByName(returnType, allowAny, allAllowedPromiseNames, | ||
if (!(0, util_1.containsAllTypesByName)(returnType, allowAny, allAllowedPromiseNames, | ||
// If no return type is explicitly set, we check if any parts of the return type match a Promise (instead of requiring all to match). | ||
@@ -112,9 +108,8 @@ node.returnType == null)) { | ||
} | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition) { | ||
// Abstract method can't be async | ||
return; | ||
} | ||
if (node.parent && | ||
(node.parent.type === utils_1.AST_NODE_TYPES.Property || | ||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) && | ||
if ((node.parent.type === utils_1.AST_NODE_TYPES.Property || | ||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) && | ||
(node.parent.kind === 'get' || node.parent.kind === 'set')) { | ||
@@ -124,3 +119,3 @@ // Getters and setters can't be async | ||
} | ||
if (util.isTypeFlagSet(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { | ||
if ((0, util_1.isTypeFlagSet)(returnType, ts.TypeFlags.Any | ts.TypeFlags.Unknown)) { | ||
// Report without auto fixer because the return type is unknown | ||
@@ -130,3 +125,3 @@ return context.report({ | ||
node, | ||
loc: util.getFunctionHeadLoc(node, sourceCode), | ||
loc: (0, util_1.getFunctionHeadLoc)(node, sourceCode), | ||
}); | ||
@@ -137,8 +132,6 @@ } | ||
node, | ||
loc: util.getFunctionHeadLoc(node, sourceCode), | ||
loc: (0, util_1.getFunctionHeadLoc)(node, sourceCode), | ||
fix: fixer => { | ||
if (node.parent && | ||
(node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition || | ||
(node.parent.type === utils_1.AST_NODE_TYPES.Property && | ||
node.parent.method))) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition || | ||
(node.parent.type === utils_1.AST_NODE_TYPES.Property && node.parent.method)) { | ||
// this function is a class method or object function property shorthand | ||
@@ -150,3 +143,3 @@ const method = node.parent; | ||
if (method.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
method.decorators) { | ||
method.decorators.length) { | ||
const lastDecorator = method.decorators[method.decorators.length - 1]; | ||
@@ -172,13 +165,15 @@ keyToken = sourceCode.getTokenAfter(lastDecorator); | ||
} | ||
return Object.assign(Object.assign(Object.assign({}, (checkArrowFunctions && { | ||
'ArrowFunctionExpression[async = false]'(node) { | ||
validateNode(node); | ||
}, | ||
})), (checkFunctionDeclarations && { | ||
'FunctionDeclaration[async = false]'(node) { | ||
validateNode(node); | ||
}, | ||
})), { 'FunctionExpression[async = false]'(node) { | ||
if (node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
return { | ||
...(checkArrowFunctions && { | ||
'ArrowFunctionExpression[async = false]'(node) { | ||
validateNode(node); | ||
}, | ||
}), | ||
...(checkFunctionDeclarations && { | ||
'FunctionDeclaration[async = false]'(node) { | ||
validateNode(node); | ||
}, | ||
}), | ||
'FunctionExpression[async = false]'(node) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition && | ||
node.parent.kind === 'method') { | ||
@@ -193,5 +188,6 @@ if (checkMethodDeclarations) { | ||
} | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=promise-function-async.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('quotes'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'quotes', | ||
@@ -37,3 +13,2 @@ meta: { | ||
description: 'Enforce the consistent use of either backticks, double, or single quotes', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -43,6 +18,3 @@ }, | ||
hasSuggestions: baseRule.meta.hasSuggestions, | ||
// TODO: this rule has only had messages since v7.0 - remove this when we remove support for v6 | ||
messages: (_a = baseRule.meta.messages) !== null && _a !== void 0 ? _a : { | ||
wrongQuotes: 'Strings must use {{description}}.', | ||
}, | ||
messages: baseRule.meta.messages, | ||
schema: baseRule.meta.schema, | ||
@@ -61,3 +33,3 @@ }, | ||
const parent = node.parent; | ||
switch (parent === null || parent === void 0 ? void 0 : parent.type) { | ||
switch (parent.type) { | ||
case utils_1.AST_NODE_TYPES.TSAbstractMethodDefinition: | ||
@@ -64,0 +36,0 @@ case utils_1.AST_NODE_TYPES.TSMethodSignature: |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'require-array-sort-compare', | ||
defaultOptions: [ | ||
{ | ||
ignoreStringArrays: false, | ||
ignoreStringArrays: true, | ||
}, | ||
@@ -37,4 +14,3 @@ ], | ||
docs: { | ||
description: 'Require `Array#sort` calls to always provide a `compareFunction`', | ||
recommended: false, | ||
description: 'Require `Array#sort` and `Array#toSorted` calls to always provide a `compareFunction`', | ||
requiresTypeChecking: true, | ||
@@ -48,2 +24,3 @@ }, | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
@@ -59,4 +36,4 @@ ignoreStringArrays: { | ||
create(context, [options]) { | ||
const service = util.getParserServices(context); | ||
const checker = service.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
/** | ||
@@ -67,20 +44,21 @@ * Check if a given node is an array which all elements are string. | ||
function isStringArrayNode(node) { | ||
const type = checker.getTypeAtLocation(service.esTreeNodeToTSNodeMap.get(node)); | ||
const type = services.getTypeAtLocation(node); | ||
if (checker.isArrayType(type) || checker.isTupleType(type)) { | ||
const typeArgs = util.getTypeArguments(type, checker); | ||
return typeArgs.every(arg => util.getTypeName(checker, arg) === 'string'); | ||
const typeArgs = checker.getTypeArguments(type); | ||
return typeArgs.every(arg => (0, util_1.getTypeName)(checker, arg) === 'string'); | ||
} | ||
return false; | ||
} | ||
function checkSortArgument(callee) { | ||
const calleeObjType = (0, util_1.getConstrainedTypeAtLocation)(services, callee.object); | ||
if (options.ignoreStringArrays && isStringArrayNode(callee.object)) { | ||
return; | ||
} | ||
if ((0, util_1.isTypeArrayTypeOrUnionOfArrayTypes)(calleeObjType, checker)) { | ||
context.report({ node: callee.parent, messageId: 'requireCompare' }); | ||
} | ||
} | ||
return { | ||
"CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]"(callee) { | ||
const tsNode = service.esTreeNodeToTSNodeMap.get(callee.object); | ||
const calleeObjType = util.getConstrainedTypeAtLocation(checker, tsNode); | ||
if (options.ignoreStringArrays && isStringArrayNode(callee.object)) { | ||
return; | ||
} | ||
if (util.isTypeArrayTypeOrUnionOfArrayTypes(calleeObjType, checker)) { | ||
context.report({ node: callee.parent, messageId: 'requireCompare' }); | ||
} | ||
}, | ||
"CallExpression[arguments.length=0] > MemberExpression[property.name='sort'][computed=false]": checkSortArgument, | ||
"CallExpression[arguments.length=0] > MemberExpression[property.name='toSorted'][computed=false]": checkSortArgument, | ||
}; | ||
@@ -87,0 +65,0 @@ }, |
@@ -27,5 +27,6 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'require-await', | ||
@@ -36,3 +37,3 @@ meta: { | ||
description: 'Disallow async functions which have no `await` expression', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -48,5 +49,5 @@ extendsBaseRule: true, | ||
create(context) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
let scopeInfo = null; | ||
@@ -83,3 +84,3 @@ /** | ||
data: { | ||
name: util.upperCaseFirst(util.getFunctionNameWithKind(node)), | ||
name: (0, util_1.upperCaseFirst)((0, util_1.getFunctionNameWithKind)(node)), | ||
}, | ||
@@ -107,17 +108,23 @@ }); | ||
/** | ||
* mark `scopeInfo.isAsyncYield` to `true` if its a generator | ||
* function and the delegate is `true` | ||
* Mark `scopeInfo.isAsyncYield` to `true` if it | ||
* 1) delegates async generator function | ||
* or | ||
* 2) yields thenable type | ||
*/ | ||
function markAsHasDelegateGen(node) { | ||
var _a; | ||
if (!(scopeInfo === null || scopeInfo === void 0 ? void 0 : scopeInfo.isGen) || !node.argument) { | ||
function visitYieldExpression(node) { | ||
if (!scopeInfo?.isGen || !node.argument) { | ||
return; | ||
} | ||
if (((_a = node === null || node === void 0 ? void 0 : node.argument) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.Literal) { | ||
// making this `false` as for literals we don't need to check the definition | ||
if (node.argument.type === utils_1.AST_NODE_TYPES.Literal) { | ||
// ignoring this as for literals we don't need to check the definition | ||
// eg : async function* run() { yield* 1 } | ||
scopeInfo.isAsyncYield || (scopeInfo.isAsyncYield = false); | ||
return; | ||
} | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node === null || node === void 0 ? void 0 : node.argument); | ||
const type = checker.getTypeAtLocation(tsNode); | ||
if (!node.delegate) { | ||
if (isThenableType(services.esTreeNodeToTSNodeMap.get(node.argument))) { | ||
scopeInfo.isAsyncYield = true; | ||
} | ||
return; | ||
} | ||
const type = services.getTypeAtLocation(node.argument); | ||
const typesToCheck = expandUnionOrIntersectionType(type); | ||
@@ -140,9 +147,10 @@ for (const type of typesToCheck) { | ||
AwaitExpression: markAsHasAwait, | ||
'VariableDeclaration[kind = "await using"]': markAsHasAwait, | ||
'ForOfStatement[await = true]': markAsHasAwait, | ||
'YieldExpression[delegate = true]': markAsHasDelegateGen, | ||
YieldExpression: visitYieldExpression, | ||
// check body-less async arrow function. | ||
// ignore `async () => await foo` because it's obviously correct | ||
'ArrowFunctionExpression[async = true] > :not(BlockStatement, AwaitExpression)'(node) { | ||
const expression = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
if (expression && isThenableType(expression)) { | ||
const expression = services.esTreeNodeToTSNodeMap.get(node); | ||
if (isThenableType(expression)) { | ||
markAsHasAwait(); | ||
@@ -156,3 +164,3 @@ } | ||
} | ||
const { expression } = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const { expression } = services.esTreeNodeToTSNodeMap.get(node); | ||
if (expression && isThenableType(expression)) { | ||
@@ -166,4 +174,3 @@ markAsHasAwait(); | ||
function isEmptyFunction(node) { | ||
var _a; | ||
return (((_a = node.body) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.BlockStatement && | ||
return (node.body.type === utils_1.AST_NODE_TYPES.BlockStatement && | ||
node.body.body.length === 0); | ||
@@ -176,5 +183,5 @@ } | ||
function getOpeningParenOfParams(node, sourceCode) { | ||
return util.nullThrows(node.id | ||
? sourceCode.getTokenAfter(node.id, util.isOpeningParenToken) | ||
: sourceCode.getFirstToken(node, util.isOpeningParenToken), util.NullThrowsReasons.MissingToken('(', node.type)); | ||
return (0, util_1.nullThrows)(node.id | ||
? sourceCode.getTokenAfter(node.id, util_1.isOpeningParenToken) | ||
: sourceCode.getFirstToken(node, util_1.isOpeningParenToken), util_1.NullThrowsReasons.MissingToken('(', node.type)); | ||
} | ||
@@ -186,7 +193,7 @@ // https://github.com/eslint/eslint/blob/03a69dbe86d5b5768a310105416ae726822e3c1c/lib/rules/utils/ast-utils.js#L1220-L1242 | ||
function getFunctionHeadLoc(node, sourceCode) { | ||
const parent = util.nullThrows(node.parent, util.NullThrowsReasons.MissingParent); | ||
const parent = (0, util_1.nullThrows)(node.parent, util_1.NullThrowsReasons.MissingParent); | ||
let start = null; | ||
let end = null; | ||
if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { | ||
const arrowToken = util.nullThrows(sourceCode.getTokenBefore(node.body, util.isArrowToken), util.NullThrowsReasons.MissingToken('=>', node.type)); | ||
const arrowToken = (0, util_1.nullThrows)(sourceCode.getTokenBefore(node.body, util_1.isArrowToken), util_1.NullThrowsReasons.MissingToken('=>', node.type)); | ||
start = arrowToken.loc.start; | ||
@@ -193,0 +200,0 @@ end = arrowToken.loc.end; |
@@ -26,5 +26,6 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'restrict-plus-operands', | ||
@@ -35,11 +36,9 @@ meta: { | ||
description: 'Require both operands of addition to be the same type and be `bigint`, `number`, or `string`', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
}, | ||
messages: { | ||
notNumbers: "Operands of '+' operation must either be both strings or both numbers.", | ||
notStrings: "Operands of '+' operation must either be both strings or both numbers. Consider using a template literal.", | ||
notBigInts: "Operands of '+' operation must be both bigints.", | ||
notValidAnys: "Operands of '+' operation with any is possible only with string, number, bigint or any", | ||
notValidTypes: "Operands of '+' operation must either be one of string, number, bigint or any (if allowed by option)", | ||
bigintAndNumber: "Numeric '+' operations must either be both bigints or both numbers. Got `{{left}}` + `{{right}}`.", | ||
invalid: "Invalid operand for a '+' operation. Operands must each be a number or {{stringLike}}. Got `{{type}}`.", | ||
mismatched: "Operands of '+' operations must be a number or {{stringLike}}. Got `{{left}}` + `{{right}}`.", | ||
}, | ||
@@ -51,6 +50,2 @@ schema: [ | ||
properties: { | ||
checkCompoundAssignments: { | ||
description: 'Whether to check compound assignments such as `+=`.', | ||
type: 'boolean', | ||
}, | ||
allowAny: { | ||
@@ -60,2 +55,22 @@ description: 'Whether to allow `any` typed values.', | ||
}, | ||
allowBoolean: { | ||
description: 'Whether to allow `boolean` typed values.', | ||
type: 'boolean', | ||
}, | ||
allowNullish: { | ||
description: 'Whether to allow potentially `null` or `undefined` typed values.', | ||
type: 'boolean', | ||
}, | ||
allowNumberAndString: { | ||
description: 'Whether to allow `bigint`/`number` typed values and `string` typed values to be added together.', | ||
type: 'boolean', | ||
}, | ||
allowRegExp: { | ||
description: 'Whether to allow `regexp` typed values.', | ||
type: 'boolean', | ||
}, | ||
skipCompoundAssignments: { | ||
description: 'Whether to skip compound assignments such as `+=`.', | ||
type: 'boolean', | ||
}, | ||
}, | ||
@@ -67,112 +82,135 @@ }, | ||
{ | ||
checkCompoundAssignments: false, | ||
allowAny: false, | ||
allowAny: true, | ||
allowBoolean: true, | ||
allowNullish: true, | ||
allowNumberAndString: true, | ||
allowRegExp: true, | ||
skipCompoundAssignments: false, | ||
}, | ||
], | ||
create(context, [{ checkCompoundAssignments, allowAny }]) { | ||
const service = util.getParserServices(context); | ||
const typeChecker = service.program.getTypeChecker(); | ||
/** | ||
* Helper function to get base type of node | ||
*/ | ||
function getBaseTypeOfLiteralType(type) { | ||
if (type.isNumberLiteral()) { | ||
return 'number'; | ||
create(context, [{ allowAny, allowBoolean, allowNullish, allowNumberAndString, allowRegExp, skipCompoundAssignments, },]) { | ||
const services = (0, util_1.getParserServices)(context); | ||
const typeChecker = services.program.getTypeChecker(); | ||
const stringLikes = [ | ||
allowAny && '`any`', | ||
allowBoolean && '`boolean`', | ||
allowNullish && '`null`', | ||
allowRegExp && '`RegExp`', | ||
allowNullish && '`undefined`', | ||
].filter((value) => typeof value === 'string'); | ||
const stringLike = stringLikes.length | ||
? stringLikes.length === 1 | ||
? `string, allowing a string + ${stringLikes[0]}` | ||
: `string, allowing a string + any of: ${stringLikes.join(', ')}` | ||
: 'string'; | ||
function getTypeConstrained(node) { | ||
return typeChecker.getBaseTypeOfLiteralType((0, util_1.getConstrainedTypeAtLocation)(services, node)); | ||
} | ||
function checkPlusOperands(node) { | ||
const leftType = getTypeConstrained(node.left); | ||
const rightType = getTypeConstrained(node.right); | ||
if (leftType === rightType && | ||
tsutils.isTypeFlagSet(leftType, ts.TypeFlags.BigIntLike | | ||
ts.TypeFlags.NumberLike | | ||
ts.TypeFlags.StringLike)) { | ||
return; | ||
} | ||
if (type.isStringLiteral() || | ||
util.isTypeFlagSet(type, ts.TypeFlags.TemplateLiteral)) { | ||
return 'string'; | ||
} | ||
// is BigIntLiteral | ||
if (type.flags & ts.TypeFlags.BigIntLiteral) { | ||
return 'bigint'; | ||
} | ||
if (type.isUnion()) { | ||
const types = type.types.map(getBaseTypeOfLiteralType); | ||
return types.every(value => value === types[0]) ? types[0] : 'invalid'; | ||
} | ||
if (type.isIntersection()) { | ||
const types = type.types.map(getBaseTypeOfLiteralType); | ||
if (types.some(value => value === 'string')) { | ||
return 'string'; | ||
let hadIndividualComplaint = false; | ||
for (const [baseNode, baseType, otherType] of [ | ||
[node.left, leftType, rightType], | ||
[node.right, rightType, leftType], | ||
]) { | ||
if (isTypeFlagSetInUnion(baseType, ts.TypeFlags.ESSymbolLike | | ||
ts.TypeFlags.Never | | ||
ts.TypeFlags.Unknown) || | ||
(!allowAny && isTypeFlagSetInUnion(baseType, ts.TypeFlags.Any)) || | ||
(!allowBoolean && | ||
isTypeFlagSetInUnion(baseType, ts.TypeFlags.BooleanLike)) || | ||
(!allowNullish && | ||
(0, util_1.isTypeFlagSet)(baseType, ts.TypeFlags.Null | ts.TypeFlags.Undefined))) { | ||
context.report({ | ||
data: { | ||
stringLike, | ||
type: typeChecker.typeToString(baseType), | ||
}, | ||
messageId: 'invalid', | ||
node: baseNode, | ||
}); | ||
hadIndividualComplaint = true; | ||
continue; | ||
} | ||
if (types.some(value => value === 'number')) { | ||
return 'number'; | ||
// RegExps also contain ts.TypeFlags.Any & ts.TypeFlags.Object | ||
for (const subBaseType of tsutils.unionTypeParts(baseType)) { | ||
const typeName = (0, util_1.getTypeName)(typeChecker, subBaseType); | ||
if (typeName === 'RegExp' | ||
? !allowRegExp || | ||
tsutils.isTypeFlagSet(otherType, ts.TypeFlags.NumberLike) | ||
: (!allowAny && (0, util_1.isTypeAnyType)(subBaseType)) || | ||
isDeeplyObjectType(subBaseType)) { | ||
context.report({ | ||
data: { | ||
stringLike, | ||
type: typeChecker.typeToString(subBaseType), | ||
}, | ||
messageId: 'invalid', | ||
node: baseNode, | ||
}); | ||
hadIndividualComplaint = true; | ||
continue; | ||
} | ||
} | ||
if (types.some(value => value === 'bigint')) { | ||
return 'bigint'; | ||
} | ||
return 'invalid'; | ||
} | ||
const stringType = typeChecker.typeToString(type); | ||
if (stringType === 'number' || | ||
stringType === 'string' || | ||
stringType === 'bigint' || | ||
stringType === 'any') { | ||
return stringType; | ||
if (hadIndividualComplaint) { | ||
return; | ||
} | ||
return 'invalid'; | ||
} | ||
/** | ||
* Helper function to get base type of node | ||
* @param node the node to be evaluated. | ||
*/ | ||
function getNodeType(node) { | ||
const tsNode = service.esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); | ||
return getBaseTypeOfLiteralType(type); | ||
} | ||
function checkPlusOperands(node) { | ||
const leftType = getNodeType(node.left); | ||
const rightType = getNodeType(node.right); | ||
if (leftType === rightType) { | ||
if (leftType === 'invalid') { | ||
context.report({ | ||
for (const [baseType, otherType] of [ | ||
[leftType, rightType], | ||
[rightType, leftType], | ||
]) { | ||
if (!allowNumberAndString && | ||
isTypeFlagSetInUnion(baseType, ts.TypeFlags.StringLike) && | ||
isTypeFlagSetInUnion(otherType, ts.TypeFlags.NumberLike)) { | ||
return context.report({ | ||
data: { | ||
stringLike, | ||
left: typeChecker.typeToString(leftType), | ||
right: typeChecker.typeToString(rightType), | ||
}, | ||
messageId: 'mismatched', | ||
node, | ||
messageId: 'notValidTypes', | ||
}); | ||
} | ||
if (!allowAny && leftType === 'any') { | ||
context.report({ | ||
if (isTypeFlagSetInUnion(baseType, ts.TypeFlags.NumberLike) && | ||
isTypeFlagSetInUnion(otherType, ts.TypeFlags.BigIntLike)) { | ||
return context.report({ | ||
data: { | ||
left: typeChecker.typeToString(leftType), | ||
right: typeChecker.typeToString(rightType), | ||
}, | ||
messageId: 'bigintAndNumber', | ||
node, | ||
messageId: 'notValidAnys', | ||
}); | ||
} | ||
return; | ||
} | ||
if (leftType === 'any' || rightType === 'any') { | ||
if (!allowAny || leftType === 'invalid' || rightType === 'invalid') { | ||
context.report({ | ||
node, | ||
messageId: 'notValidAnys', | ||
}); | ||
} | ||
return; | ||
} | ||
if (leftType === 'string' || rightType === 'string') { | ||
return context.report({ | ||
node, | ||
messageId: 'notStrings', | ||
}); | ||
} | ||
if (leftType === 'bigint' || rightType === 'bigint') { | ||
return context.report({ | ||
node, | ||
messageId: 'notBigInts', | ||
}); | ||
} | ||
if (leftType === 'number' || rightType === 'number') { | ||
return context.report({ | ||
node, | ||
messageId: 'notNumbers', | ||
}); | ||
} | ||
} | ||
return Object.assign({ "BinaryExpression[operator='+']": checkPlusOperands }, (checkCompoundAssignments && { | ||
"AssignmentExpression[operator='+=']"(node) { | ||
checkPlusOperands(node); | ||
}, | ||
})); | ||
return { | ||
"BinaryExpression[operator='+']": checkPlusOperands, | ||
...(!skipCompoundAssignments && { | ||
"AssignmentExpression[operator='+=']"(node) { | ||
checkPlusOperands(node); | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
function isDeeplyObjectType(type) { | ||
return type.isIntersection() | ||
? tsutils.intersectionTypeParts(type).every(tsutils.isObjectType) | ||
: tsutils.unionTypeParts(type).every(tsutils.isObjectType); | ||
} | ||
function isTypeFlagSetInUnion(type, flag) { | ||
return tsutils | ||
.unionTypeParts(type) | ||
.some(subType => tsutils.isTypeFlagSet(subType, flag)); | ||
} | ||
//# sourceMappingURL=restrict-plus-operands.js.map |
@@ -28,4 +28,4 @@ "use strict"; | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'restrict-template-expressions', | ||
@@ -36,3 +36,3 @@ meta: { | ||
description: 'Enforce template literal expressions to be of `string` type', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -46,5 +46,6 @@ }, | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
allowNumber: { | ||
description: 'Whether to allow `number` typed values in template expressions.', | ||
allowAny: { | ||
description: 'Whether to allow `any` typed values in template expressions.', | ||
type: 'boolean', | ||
@@ -56,6 +57,2 @@ }, | ||
}, | ||
allowAny: { | ||
description: 'Whether to allow `any` typed values in template expressions.', | ||
type: 'boolean', | ||
}, | ||
allowNullish: { | ||
@@ -65,2 +62,6 @@ description: 'Whether to allow `nullish` typed values in template expressions.', | ||
}, | ||
allowNumber: { | ||
description: 'Whether to allow `number` typed values in template expressions.', | ||
type: 'boolean', | ||
}, | ||
allowRegExp: { | ||
@@ -80,32 +81,35 @@ description: 'Whether to allow `regexp` typed values in template expressions.', | ||
{ | ||
allowAny: true, | ||
allowBoolean: true, | ||
allowNullish: true, | ||
allowNumber: true, | ||
allowRegExp: true, | ||
}, | ||
], | ||
create(context, [options]) { | ||
const service = util.getParserServices(context); | ||
const typeChecker = service.program.getTypeChecker(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
function isUnderlyingTypePrimitive(type) { | ||
if (util.isTypeFlagSet(type, ts.TypeFlags.StringLike)) { | ||
if ((0, util_1.isTypeFlagSet)(type, ts.TypeFlags.StringLike)) { | ||
return true; | ||
} | ||
if (options.allowNumber && | ||
util.isTypeFlagSet(type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike)) { | ||
(0, util_1.isTypeFlagSet)(type, ts.TypeFlags.NumberLike | ts.TypeFlags.BigIntLike)) { | ||
return true; | ||
} | ||
if (options.allowBoolean && | ||
util.isTypeFlagSet(type, ts.TypeFlags.BooleanLike)) { | ||
(0, util_1.isTypeFlagSet)(type, ts.TypeFlags.BooleanLike)) { | ||
return true; | ||
} | ||
if (options.allowAny && util.isTypeAnyType(type)) { | ||
if (options.allowAny && (0, util_1.isTypeAnyType)(type)) { | ||
return true; | ||
} | ||
if (options.allowRegExp && | ||
util.getTypeName(typeChecker, type) === 'RegExp') { | ||
if (options.allowRegExp && (0, util_1.getTypeName)(checker, type) === 'RegExp') { | ||
return true; | ||
} | ||
if (options.allowNullish && | ||
util.isTypeFlagSet(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined)) { | ||
(0, util_1.isTypeFlagSet)(type, ts.TypeFlags.Null | ts.TypeFlags.Undefined)) { | ||
return true; | ||
} | ||
if (options.allowNever && util.isTypeNeverType(type)) { | ||
if (options.allowNever && (0, util_1.isTypeNeverType)(type)) { | ||
return true; | ||
@@ -122,3 +126,3 @@ } | ||
for (const expression of node.expressions) { | ||
const expressionType = util.getConstrainedTypeAtLocation(typeChecker, service.esTreeNodeToTSNodeMap.get(expression)); | ||
const expressionType = (0, util_1.getConstrainedTypeAtLocation)(services, expression); | ||
if (!isInnerUnionOrIntersectionConformingTo(expressionType, isUnderlyingTypePrimitive)) { | ||
@@ -128,3 +132,3 @@ context.report({ | ||
messageId: 'invalidType', | ||
data: { type: typeChecker.typeToString(expressionType) }, | ||
data: { type: checker.typeToString(expressionType) }, | ||
}); | ||
@@ -131,0 +135,0 @@ } |
@@ -27,8 +27,8 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const tsutils_1 = require("tsutils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getOperatorPrecedence_1 = require("../util/getOperatorPrecedence"); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'return-await', | ||
@@ -38,3 +38,2 @@ meta: { | ||
description: 'Enforce consistent returning of awaited values', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -53,2 +52,3 @@ extendsBaseRule: 'no-return-await', | ||
{ | ||
type: 'string', | ||
enum: ['in-try-catch', 'always', 'never'], | ||
@@ -60,5 +60,5 @@ }, | ||
create(context, [option]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const scopeInfoStack = []; | ||
@@ -119,6 +119,6 @@ function enterFunction(node) { | ||
// Should always be an await node; but let's be safe. | ||
/* istanbul ignore if */ if (!util.isAwaitExpression(node)) { | ||
/* istanbul ignore if */ if (!(0, util_1.isAwaitExpression)(node)) { | ||
return null; | ||
} | ||
const awaitToken = sourceCode.getFirstToken(node, util.isAwaitKeyword); | ||
const awaitToken = sourceCode.getFirstToken(node, util_1.isAwaitKeyword); | ||
// Should always be the case; but let's be safe. | ||
@@ -143,11 +143,9 @@ /* istanbul ignore if */ if (!awaitToken) { | ||
} | ||
else { | ||
return [ | ||
fixer.insertTextBefore(node, 'await ('), | ||
fixer.insertTextAfter(node, ')'), | ||
]; | ||
} | ||
return [ | ||
fixer.insertTextBefore(node, 'await ('), | ||
fixer.insertTextAfter(node, ')'), | ||
]; | ||
} | ||
function isHigherPrecedenceThanAwait(node) { | ||
const operator = (0, tsutils_1.isBinaryExpression)(node) | ||
const operator = ts.isBinaryExpression(node) | ||
? node.operatorToken.kind | ||
@@ -175,14 +173,18 @@ : ts.SyntaxKind.Unknown; | ||
// any/unknown could be thenable; do not auto-fix | ||
const useAutoFix = !(util.isTypeAnyType(type) || util.isTypeUnknownType(type)); | ||
const useAutoFix = !((0, util_1.isTypeAnyType)(type) || (0, util_1.isTypeUnknownType)(type)); | ||
const fix = (fixer) => removeAwait(fixer, node); | ||
context.report(Object.assign({ messageId: 'nonPromiseAwait', node }, (useAutoFix | ||
? { fix } | ||
: { | ||
suggest: [ | ||
{ | ||
messageId: 'nonPromiseAwait', | ||
fix, | ||
}, | ||
], | ||
}))); | ||
context.report({ | ||
messageId: 'nonPromiseAwait', | ||
node, | ||
...(useAutoFix | ||
? { fix } | ||
: { | ||
suggest: [ | ||
{ | ||
messageId: 'nonPromiseAwait', | ||
fix, | ||
}, | ||
], | ||
}), | ||
}); | ||
return; | ||
@@ -255,3 +257,3 @@ } | ||
findPossiblyReturnedNodes(node.body).forEach(node => { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
test(node, tsNode); | ||
@@ -262,8 +264,8 @@ }); | ||
ReturnStatement(node) { | ||
const scopeInfo = scopeInfoStack[scopeInfoStack.length - 1]; | ||
if (!(scopeInfo === null || scopeInfo === void 0 ? void 0 : scopeInfo.hasAsync) || !node.argument) { | ||
const scopeInfo = scopeInfoStack.at(-1); | ||
if (!scopeInfo?.hasAsync || !node.argument) { | ||
return; | ||
} | ||
findPossiblyReturnedNodes(node.argument).forEach(node => { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const tsNode = services.esTreeNodeToTSNodeMap.get(node); | ||
test(node, tsNode); | ||
@@ -270,0 +272,0 @@ }); |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
var _a; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('semi'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'semi', | ||
@@ -38,3 +14,2 @@ meta: { | ||
// too opinionated to be recommended | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -45,7 +20,3 @@ }, | ||
schema: baseRule.meta.schema, | ||
// TODO: this rule has only had messages since v7.0 - remove this when we remove support for v6 | ||
messages: (_a = baseRule.meta.messages) !== null && _a !== void 0 ? _a : { | ||
missingSemi: 'Missing semicolon.', | ||
extraSemi: 'Extra semicolon.', | ||
}, | ||
messages: baseRule.meta.messages, | ||
}, | ||
@@ -82,9 +53,13 @@ defaultOptions: [ | ||
}, {}); | ||
return Object.assign(Object.assign(Object.assign({}, rules), nodesToCheck), { ExportDefaultDeclaration(node) { | ||
return { | ||
...rules, | ||
...nodesToCheck, | ||
ExportDefaultDeclaration(node) { | ||
if (node.declaration.type !== utils_1.AST_NODE_TYPES.TSInterfaceDeclaration) { | ||
rules.ExportDefaultDeclaration(node); | ||
} | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=semi.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
@@ -108,3 +85,3 @@ var Group; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'sort-type-constituents', | ||
@@ -115,3 +92,2 @@ meta: { | ||
description: 'Enforce constituents of a type union/intersection to be sorted alphabetically', | ||
recommended: false, | ||
}, | ||
@@ -128,2 +104,3 @@ fixable: 'code', | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
@@ -171,3 +148,3 @@ checkIntersections: { | ||
create(context, [{ checkIntersections, checkUnions, groupOrder }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const collator = new Intl.Collator('en', { | ||
@@ -178,6 +155,4 @@ sensitivity: 'base', | ||
function checkSorting(node) { | ||
var _a; | ||
const sourceOrder = node.types.map(type => { | ||
var _a; | ||
const group = (_a = groupOrder === null || groupOrder === void 0 ? void 0 : groupOrder.indexOf(getGroup(type))) !== null && _a !== void 0 ? _a : -1; | ||
const group = groupOrder?.indexOf(getGroup(type)) ?? -1; | ||
return { | ||
@@ -210,3 +185,3 @@ group: group === -1 ? Number.MAX_SAFE_INTEGER : group, | ||
}; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration) { | ||
messageId = 'notSortedNamed'; | ||
@@ -225,28 +200,36 @@ data.name = node.parent.id.name; | ||
}; | ||
return context.report(Object.assign({ node, | ||
return context.report({ | ||
node, | ||
messageId, | ||
data }, (hasComments | ||
? { | ||
suggest: [ | ||
{ | ||
messageId: 'suggestFix', | ||
fix, | ||
}, | ||
], | ||
} | ||
: { fix }))); | ||
data, | ||
// don't autofix if any of the types have leading/trailing comments | ||
// the logic for preserving them correctly is a pain - we may implement this later | ||
...(hasComments | ||
? { | ||
suggest: [ | ||
{ | ||
messageId: 'suggestFix', | ||
fix, | ||
}, | ||
], | ||
} | ||
: { fix }), | ||
}); | ||
} | ||
} | ||
} | ||
return Object.assign(Object.assign({}, (checkIntersections && { | ||
TSIntersectionType(node) { | ||
checkSorting(node); | ||
}, | ||
})), (checkUnions && { | ||
TSUnionType(node) { | ||
checkSorting(node); | ||
}, | ||
})); | ||
return { | ||
...(checkIntersections && { | ||
TSIntersectionType(node) { | ||
checkSorting(node); | ||
}, | ||
}), | ||
...(checkUnions && { | ||
TSUnionType(node) { | ||
checkSorting(node); | ||
}, | ||
}), | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=sort-type-constituents.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('space-before-blocks'); | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'space-before-blocks', | ||
@@ -35,3 +13,2 @@ meta: { | ||
description: 'Enforce consistent spacing before blocks', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -42,7 +19,9 @@ }, | ||
schema: baseRule.meta.schema, | ||
messages: Object.assign({ | ||
messages: { | ||
// @ts-expect-error -- we report on this messageId so we need to ensure it's there in case ESLint changes in future | ||
unexpectedSpace: 'Unexpected space before opening brace.', | ||
unexpectedSpace: 'Unexpected space before opening brace.', | ||
// @ts-expect-error -- we report on this messageId so we need to ensure it's there in case ESLint changes in future | ||
missingSpace: 'Missing space before opening brace.' }, baseRule.meta.messages), | ||
missingSpace: 'Missing space before opening brace.', | ||
...baseRule.meta.messages, | ||
}, | ||
}, | ||
@@ -52,3 +31,3 @@ defaultOptions: ['always'], | ||
const rules = baseRule.create(context); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
let requireSpace = true; | ||
@@ -63,3 +42,3 @@ if (typeof config === 'object') { | ||
const precedingToken = sourceCode.getTokenBefore(node); | ||
if (precedingToken && util.isTokenOnSameLine(precedingToken, node)) { | ||
if (precedingToken && (0, util_1.isTokenOnSameLine)(precedingToken, node)) { | ||
// eslint-disable-next-line deprecation/deprecation -- TODO - switch once our min ESLint version is 6.7.0 | ||
@@ -96,5 +75,9 @@ const hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node); | ||
} | ||
return Object.assign(Object.assign({}, rules), { TSEnumDeclaration: checkSpaceAfterEnum, TSInterfaceBody: checkPrecedingSpace }); | ||
return { | ||
...rules, | ||
TSEnumDeclaration: checkSpaceAfterEnum, | ||
TSInterfaceBody: checkPrecedingSpace, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=space-before-blocks.js.map |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'space-before-function-paren', | ||
@@ -34,3 +12,2 @@ meta: { | ||
description: 'Enforce consistent spacing before function parenthesis', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -43,2 +20,3 @@ }, | ||
{ | ||
type: 'string', | ||
enum: ['always', 'never'], | ||
@@ -50,8 +28,11 @@ }, | ||
anonymous: { | ||
type: 'string', | ||
enum: ['always', 'never', 'ignore'], | ||
}, | ||
named: { | ||
type: 'string', | ||
enum: ['always', 'never', 'ignore'], | ||
}, | ||
asyncArrow: { | ||
type: 'string', | ||
enum: ['always', 'never', 'ignore'], | ||
@@ -72,3 +53,3 @@ }, | ||
create(context, [firstOption]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const baseConfig = typeof firstOption === 'string' ? firstOption : 'always'; | ||
@@ -97,16 +78,15 @@ const overrideConfig = typeof firstOption === 'object' ? firstOption : {}; | ||
function getConfigForFunction(node) { | ||
var _a, _b, _c; | ||
if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { | ||
// Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar | ||
if (node.async && | ||
util.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) { | ||
return (_a = overrideConfig.asyncArrow) !== null && _a !== void 0 ? _a : baseConfig; | ||
(0, util_1.isOpeningParenToken)(sourceCode.getFirstToken(node, { skip: 1 }))) { | ||
return overrideConfig.asyncArrow ?? baseConfig; | ||
} | ||
} | ||
else if (isNamedFunction(node)) { | ||
return (_b = overrideConfig.named) !== null && _b !== void 0 ? _b : baseConfig; | ||
return overrideConfig.named ?? baseConfig; | ||
// `generator-star-spacing` should warn anonymous generators. E.g. `function* () {}` | ||
} | ||
else if (!node.generator) { | ||
return (_c = overrideConfig.anonymous) !== null && _c !== void 0 ? _c : baseConfig; | ||
return overrideConfig.anonymous ?? baseConfig; | ||
} | ||
@@ -132,3 +112,3 @@ return 'ignore'; | ||
else { | ||
rightToken = sourceCode.getFirstToken(node, util.isOpeningParenToken); | ||
rightToken = sourceCode.getFirstToken(node, util_1.isOpeningParenToken); | ||
leftToken = sourceCode.getTokenBefore(rightToken); | ||
@@ -135,0 +115,0 @@ } |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const getESLintCoreRule_1 = require("../util/getESLintCoreRule"); | ||
const baseRule = (0, getESLintCoreRule_1.getESLintCoreRule)('space-infix-ops'); | ||
const UNIONS = ['|', '&']; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'space-infix-ops', | ||
@@ -37,3 +15,2 @@ meta: { | ||
description: 'Require spacing around infix operators', | ||
recommended: false, | ||
extendsBaseRule: true, | ||
@@ -44,5 +21,7 @@ }, | ||
schema: baseRule.meta.schema, | ||
messages: Object.assign({ | ||
messages: { | ||
// @ts-expect-error -- we report on this messageId so we need to ensure it's there in case ESLint changes in future | ||
missingSpace: "Operator '{{operator}}' must be spaced." }, baseRule.meta.messages), | ||
missingSpace: "Operator '{{operator}}' must be spaced.", | ||
...baseRule.meta.messages, | ||
}, | ||
}, | ||
@@ -56,3 +35,3 @@ defaultOptions: [ | ||
const rules = baseRule.create(context); | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
function report(operator) { | ||
@@ -107,6 +86,5 @@ context.report({ | ||
function checkForPropertyDefinitionAssignmentSpace(node) { | ||
var _a; | ||
const leftNode = node.optional && !node.typeAnnotation | ||
? sourceCode.getTokenAfter(node.key) | ||
: (_a = node.typeAnnotation) !== null && _a !== void 0 ? _a : node.key; | ||
: node.typeAnnotation ?? node.key; | ||
checkAndReportAssignmentSpace(leftNode, node.value); | ||
@@ -122,3 +100,3 @@ } | ||
const skipFunctionParenthesis = type.type === utils_1.TSESTree.AST_NODE_TYPES.TSFunctionType | ||
? util.isNotOpeningParenToken | ||
? util_1.isNotOpeningParenToken | ||
: 0; | ||
@@ -141,4 +119,3 @@ const operator = sourceCode.getTokenBefore(type, skipFunctionParenthesis); | ||
function checkForTypeAliasAssignment(node) { | ||
var _a; | ||
checkAndReportAssignmentSpace((_a = node.typeParameters) !== null && _a !== void 0 ? _a : node.id, node.typeAnnotation); | ||
checkAndReportAssignmentSpace(node.typeParameters ?? node.id, node.typeAnnotation); | ||
} | ||
@@ -149,5 +126,13 @@ function checkForTypeConditional(node) { | ||
} | ||
return Object.assign(Object.assign({}, rules), { TSEnumMember: checkForEnumAssignmentSpace, PropertyDefinition: checkForPropertyDefinitionAssignmentSpace, TSTypeAliasDeclaration: checkForTypeAliasAssignment, TSUnionType: checkForTypeAnnotationSpace, TSIntersectionType: checkForTypeAnnotationSpace, TSConditionalType: checkForTypeConditional }); | ||
return { | ||
...rules, | ||
TSEnumMember: checkForEnumAssignmentSpace, | ||
PropertyDefinition: checkForPropertyDefinitionAssignmentSpace, | ||
TSTypeAliasDeclaration: checkForTypeAliasAssignment, | ||
TSUnionType: checkForTypeAnnotationSpace, | ||
TSIntersectionType: checkForTypeAnnotationSpace, | ||
TSConditionalType: checkForTypeConditional, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=space-infix-ops.js.map |
@@ -27,6 +27,7 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'strict-boolean-expressions', | ||
@@ -39,3 +40,2 @@ meta: { | ||
description: 'Disallow certain types in boolean expressions', | ||
recommended: false, | ||
requiresTypeChecking: true, | ||
@@ -107,3 +107,3 @@ }, | ||
allowNullableNumber: false, | ||
allowNullableEnum: true, | ||
allowNullableEnum: false, | ||
allowAny: false, | ||
@@ -114,6 +114,6 @@ allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing: false, | ||
create(context, [options]) { | ||
const parserServices = util.getParserServices(context); | ||
const typeChecker = parserServices.program.getTypeChecker(); | ||
const compilerOptions = parserServices.program.getCompilerOptions(); | ||
const sourceCode = context.getSourceCode(); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const isStrictNullChecks = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'strictNullChecks'); | ||
@@ -201,4 +201,3 @@ if (!isStrictNullChecks && | ||
function checkNode(node) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); | ||
const type = (0, util_1.getConstrainedTypeAtLocation)(services, node); | ||
const types = inspectVariantTypes(tsutils.unionTypeParts(type)); | ||
@@ -238,3 +237,3 @@ const is = (...wantedTypes) => types.size === wantedTypes.length && | ||
messageId: 'conditionFixDefaultFalse', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -247,3 +246,3 @@ node, | ||
messageId: 'conditionFixCompareFalse', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -266,3 +265,3 @@ node: node.parent, | ||
messageId: 'conditionFixDefaultFalse', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -275,3 +274,3 @@ node, | ||
messageId: 'conditionFixCompareTrue', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -304,3 +303,3 @@ node, | ||
messageId: 'conditionFixCompareStringLength', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -314,3 +313,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareEmptyString', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -324,3 +323,3 @@ node: node.parent, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -343,3 +342,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareStringLength', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -352,3 +351,3 @@ node, | ||
messageId: 'conditionFixCompareEmptyString', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -361,3 +360,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -385,3 +384,3 @@ node, | ||
messageId: 'conditionFixCompareNullish', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -395,3 +394,3 @@ node: node.parent, | ||
messageId: 'conditionFixDefaultEmptyString', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -404,3 +403,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -423,3 +422,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareNullish', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -432,3 +431,3 @@ node, | ||
messageId: 'conditionFixDefaultEmptyString', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -441,3 +440,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -457,3 +456,3 @@ node, | ||
if (!options.allowNumber) { | ||
if (isArrayLengthExpression(node, typeChecker, parserServices)) { | ||
if (isArrayLengthExpression(node, checker, services)) { | ||
if (isLogicalNegationExpression(node.parent)) { | ||
@@ -464,3 +463,3 @@ // if (!array.length) | ||
messageId: 'conditionErrorNumber', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -478,3 +477,3 @@ node: node.parent, | ||
messageId: 'conditionErrorNumber', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -495,3 +494,3 @@ node, | ||
messageId: 'conditionFixCompareZero', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -507,3 +506,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareNaN', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -517,3 +516,3 @@ node: node.parent, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -536,3 +535,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareZero', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -545,3 +544,3 @@ node, | ||
messageId: 'conditionFixCompareNaN', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -554,3 +553,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -578,3 +577,3 @@ node, | ||
messageId: 'conditionFixCompareNullish', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -588,3 +587,3 @@ node: node.parent, | ||
messageId: 'conditionFixDefaultZero', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -597,3 +596,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -616,3 +615,3 @@ node: node.parent, | ||
messageId: 'conditionFixCompareNullish', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -625,3 +624,3 @@ node, | ||
messageId: 'conditionFixDefaultZero', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -634,3 +633,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -661,8 +660,13 @@ node, | ||
messageId: 'conditionErrorNullableObject', | ||
fix: util.getWrappingFixer({ | ||
sourceCode, | ||
node: node.parent, | ||
innerNode: node, | ||
wrap: code => `${code} == null`, | ||
}), | ||
suggest: [ | ||
{ | ||
messageId: 'conditionFixCompareNullish', | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
node: node.parent, | ||
innerNode: node, | ||
wrap: code => `${code} == null`, | ||
}), | ||
}, | ||
], | ||
}); | ||
@@ -675,7 +679,12 @@ } | ||
messageId: 'conditionErrorNullableObject', | ||
fix: util.getWrappingFixer({ | ||
sourceCode, | ||
node, | ||
wrap: code => `${code} != null`, | ||
}), | ||
suggest: [ | ||
{ | ||
messageId: 'conditionFixCompareNullish', | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
node, | ||
wrap: code => `${code} != null`, | ||
}), | ||
}, | ||
], | ||
}); | ||
@@ -690,3 +699,8 @@ } | ||
is('nullish', 'truthy number', 'enum') || | ||
is('nullish', 'truthy string', 'enum')) { | ||
is('nullish', 'truthy string', 'enum') || | ||
// mixed enums | ||
is('nullish', 'truthy number', 'truthy string', 'enum') || | ||
is('nullish', 'truthy number', 'string', 'enum') || | ||
is('nullish', 'truthy string', 'number', 'enum') || | ||
is('nullish', 'number', 'string', 'enum')) { | ||
if (!options.allowNullableEnum) { | ||
@@ -697,3 +711,3 @@ if (isLogicalNegationExpression(node.parent)) { | ||
messageId: 'conditionErrorNullableEnum', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -710,3 +724,3 @@ node: node.parent, | ||
messageId: 'conditionErrorNullableEnum', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -730,3 +744,3 @@ node, | ||
messageId: 'conditionFixCastBoolean', | ||
fix: util.getWrappingFixer({ | ||
fix: (0, util_1.getWrappingFixer)({ | ||
sourceCode, | ||
@@ -757,5 +771,5 @@ node, | ||
// If incoming type is boolean, there will be two type objects with | ||
// intrinsicName set "true" and "false" each because of tsutils.unionTypeParts() | ||
// intrinsicName set "true" and "false" each because of ts-api-utils.unionTypeParts() | ||
if (booleans.length === 1) { | ||
tsutils.isBooleanLiteralType(booleans[0], true) | ||
tsutils.isTrueLiteralType(booleans[0]) | ||
? variantTypes.add('truthy boolean') | ||
@@ -801,3 +815,3 @@ : variantTypes.add('boolean'); | ||
} | ||
if (types.some(type => util.isTypeFlagSet(type, ts.TypeFlags.TypeParameter | | ||
if (types.some(type => tsutils.isTypeFlagSet(type, ts.TypeFlags.TypeParameter | | ||
ts.TypeFlags.Any | | ||
@@ -817,3 +831,3 @@ ts.TypeFlags.Unknown))) { | ||
} | ||
function isArrayLengthExpression(node, typeChecker, parserServices) { | ||
function isArrayLengthExpression(node, typeChecker, services) { | ||
if (node.type !== utils_1.AST_NODE_TYPES.MemberExpression) { | ||
@@ -828,6 +842,5 @@ return false; | ||
} | ||
const objectTsNode = parserServices.esTreeNodeToTSNodeMap.get(node.object); | ||
const objectType = util.getConstrainedTypeAtLocation(typeChecker, objectTsNode); | ||
return util.isTypeArrayTypeOrUnionOfArrayTypes(objectType, typeChecker); | ||
const objectType = (0, util_1.getConstrainedTypeAtLocation)(services, node.object); | ||
return (0, util_1.isTypeArrayTypeOrUnionOfArrayTypes)(objectType, typeChecker); | ||
} | ||
//# sourceMappingURL=strict-boolean-expressions.js.map |
@@ -26,3 +26,4 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const tsutils_1 = require("tsutils"); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
@@ -35,8 +36,18 @@ const util_1 = require("../util"); | ||
docs: { | ||
description: 'Require switch-case statements to be exhaustive with union type', | ||
recommended: false, | ||
description: 'Require switch-case statements to be exhaustive', | ||
requiresTypeChecking: true, | ||
}, | ||
hasSuggestions: true, | ||
schema: [], | ||
schema: [ | ||
{ | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
requireDefaultForNonUnion: { | ||
description: `If 'true', require a 'default' clause for switches on non-union types.`, | ||
type: 'boolean', | ||
}, | ||
}, | ||
}, | ||
], | ||
messages: { | ||
@@ -47,14 +58,10 @@ switchIsNotExhaustive: 'Switch is not exhaustive. Cases not matched: {{missingBranches}}', | ||
}, | ||
defaultOptions: [], | ||
create(context) { | ||
const sourceCode = context.getSourceCode(); | ||
const service = (0, util_1.getParserServices)(context); | ||
const checker = service.program.getTypeChecker(); | ||
const compilerOptions = service.program.getCompilerOptions(); | ||
function getNodeType(node) { | ||
const tsNode = service.esTreeNodeToTSNodeMap.get(node); | ||
return (0, util_1.getConstrainedTypeAtLocation)(checker, tsNode); | ||
} | ||
function fixSwitch(fixer, node, missingBranchTypes, symbolName) { | ||
var _a; | ||
defaultOptions: [{ requireDefaultForNonUnion: false }], | ||
create(context, [{ requireDefaultForNonUnion }]) { | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const services = (0, util_1.getParserServices)(context); | ||
const checker = services.program.getTypeChecker(); | ||
const compilerOptions = services.program.getCompilerOptions(); | ||
function fixSwitch(fixer, node, missingBranchTypes, // null means default branch | ||
symbolName) { | ||
const lastCase = node.cases.length > 0 ? node.cases[node.cases.length - 1] : null; | ||
@@ -68,2 +75,6 @@ const caseIndent = lastCase | ||
for (const missingBranchType of missingBranchTypes) { | ||
if (missingBranchType == null) { | ||
missingCases.push(`default: { throw new Error('default case') }`); | ||
continue; | ||
} | ||
// While running this rule on checker.ts of TypeScript project | ||
@@ -82,3 +93,3 @@ // the fix introduced a compiler error due to: | ||
} | ||
const missingBranchName = (_a = missingBranchType.getSymbol()) === null || _a === void 0 ? void 0 : _a.escapedName; | ||
const missingBranchName = missingBranchType.getSymbol()?.escapedName; | ||
let caseTest = checker.typeToString(missingBranchType); | ||
@@ -88,6 +99,11 @@ if (symbolName && | ||
(0, util_1.requiresQuoting)(missingBranchName.toString(), compilerOptions.target)) { | ||
caseTest = `${symbolName}['${missingBranchName}']`; | ||
const escapedBranchName = missingBranchName | ||
.replace(/'/g, "\\'") | ||
.replace(/\n/g, '\\n') | ||
.replace(/\r/g, '\\r'); | ||
caseTest = `${symbolName}['${escapedBranchName}']`; | ||
} | ||
const errorMessage = `Not implemented yet: ${caseTest} case`; | ||
missingCases.push(`case ${caseTest}: { throw new Error('${errorMessage}') }`); | ||
const escapedErrorMessage = errorMessage.replace(/'/g, "\\'"); | ||
missingCases.push(`case ${caseTest}: { throw new Error('${escapedErrorMessage}') }`); | ||
} | ||
@@ -106,7 +122,6 @@ const fixString = missingCases | ||
function checkSwitchExhaustive(node) { | ||
var _a; | ||
const discriminantType = getNodeType(node.discriminant); | ||
const symbolName = (_a = discriminantType.getSymbol()) === null || _a === void 0 ? void 0 : _a.escapedName; | ||
const discriminantType = (0, util_1.getConstrainedTypeAtLocation)(services, node.discriminant); | ||
const symbolName = discriminantType.getSymbol()?.escapedName; | ||
if (discriminantType.isUnion()) { | ||
const unionTypes = (0, tsutils_1.unionTypeParts)(discriminantType); | ||
const unionTypes = tsutils.unionTypeParts(discriminantType); | ||
const caseTypes = new Set(); | ||
@@ -118,3 +133,3 @@ for (const switchCase of node.cases) { | ||
} | ||
caseTypes.add(getNodeType(switchCase.test)); | ||
caseTypes.add((0, util_1.getConstrainedTypeAtLocation)(services, switchCase.test)); | ||
} | ||
@@ -131,8 +146,5 @@ const missingBranchTypes = unionTypes.filter(unionType => !caseTypes.has(unionType)); | ||
missingBranches: missingBranchTypes | ||
.map(missingType => { | ||
var _a; | ||
return (0, tsutils_1.isTypeFlagSet)(missingType, ts.TypeFlags.ESSymbolLike) | ||
? `typeof ${(_a = missingType.getSymbol()) === null || _a === void 0 ? void 0 : _a.escapedName}` | ||
: checker.typeToString(missingType); | ||
}) | ||
.map(missingType => tsutils.isTypeFlagSet(missingType, ts.TypeFlags.ESSymbolLike) | ||
? `typeof ${missingType.getSymbol()?.escapedName}` | ||
: checker.typeToString(missingType)) | ||
.join(' | '), | ||
@@ -144,3 +156,3 @@ }, | ||
fix(fixer) { | ||
return fixSwitch(fixer, node, missingBranchTypes, symbolName === null || symbolName === void 0 ? void 0 : symbolName.toString()); | ||
return fixSwitch(fixer, node, missingBranchTypes, symbolName?.toString()); | ||
}, | ||
@@ -151,2 +163,22 @@ }, | ||
} | ||
else if (requireDefaultForNonUnion) { | ||
const hasDefault = node.cases.some(switchCase => switchCase.test == null); | ||
if (!hasDefault) { | ||
context.report({ | ||
node: node.discriminant, | ||
messageId: 'switchIsNotExhaustive', | ||
data: { | ||
missingBranches: 'default', | ||
}, | ||
suggest: [ | ||
{ | ||
messageId: 'addMissingCases', | ||
fix(fixer) { | ||
return fixSwitch(fixer, node, [null]); | ||
}, | ||
}, | ||
], | ||
}); | ||
} | ||
} | ||
} | ||
@@ -153,0 +185,0 @@ return { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'triple-slash-reference', | ||
@@ -34,3 +12,3 @@ meta: { | ||
description: 'Disallow certain triple slash directives in favor of ES6-style import declarations', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
}, | ||
@@ -45,8 +23,11 @@ messages: { | ||
lib: { | ||
type: 'string', | ||
enum: ['always', 'never'], | ||
}, | ||
path: { | ||
type: 'string', | ||
enum: ['always', 'never'], | ||
}, | ||
types: { | ||
type: 'string', | ||
enum: ['always', 'never', 'prefer-import'], | ||
@@ -68,3 +49,3 @@ }, | ||
let programNode; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const references = []; | ||
@@ -71,0 +52,0 @@ function hasMatchingReference(source) { |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const util = __importStar(require("../util")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
const definition = { | ||
type: 'object', | ||
properties: { | ||
before: { type: 'boolean' }, | ||
after: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}; | ||
function createRules(options) { | ||
var _a; | ||
const globals = Object.assign(Object.assign({}, ((options === null || options === void 0 ? void 0 : options.before) !== undefined ? { before: options.before } : {})), ((options === null || options === void 0 ? void 0 : options.after) !== undefined ? { after: options.after } : {})); | ||
const override = (_a = options === null || options === void 0 ? void 0 : options.overrides) !== null && _a !== void 0 ? _a : {}; | ||
const colon = Object.assign(Object.assign({ before: false, after: true }, globals), override === null || override === void 0 ? void 0 : override.colon); | ||
const arrow = Object.assign(Object.assign({ before: true, after: true }, globals), override === null || override === void 0 ? void 0 : override.arrow); | ||
const globals = { | ||
...(options?.before !== undefined ? { before: options.before } : {}), | ||
...(options?.after !== undefined ? { after: options.after } : {}), | ||
}; | ||
const override = options?.overrides ?? {}; | ||
const colon = { | ||
...{ before: false, after: true }, | ||
...globals, | ||
...override.colon, | ||
}; | ||
const arrow = { | ||
...{ before: true, after: true }, | ||
...globals, | ||
...override.arrow, | ||
}; | ||
return { | ||
colon: colon, | ||
arrow: arrow, | ||
variable: Object.assign(Object.assign({}, colon), override === null || override === void 0 ? void 0 : override.variable), | ||
property: Object.assign(Object.assign({}, colon), override === null || override === void 0 ? void 0 : override.property), | ||
parameter: Object.assign(Object.assign({}, colon), override === null || override === void 0 ? void 0 : override.parameter), | ||
returnType: Object.assign(Object.assign({}, colon), override === null || override === void 0 ? void 0 : override.returnType), | ||
variable: { ...colon, ...override.variable }, | ||
property: { ...colon, ...override.property }, | ||
parameter: { ...colon, ...override.parameter }, | ||
returnType: { ...colon, ...override.returnType }, | ||
}; | ||
} | ||
function getIdentifierRules(rules, node) { | ||
const scope = node === null || node === void 0 ? void 0 : node.parent; | ||
const scope = node?.parent; | ||
if ((0, util_1.isVariableDeclarator)(scope)) { | ||
@@ -59,9 +38,6 @@ return rules.variable; | ||
} | ||
else { | ||
return rules.colon; | ||
} | ||
return rules.colon; | ||
} | ||
function getRules(rules, node) { | ||
var _a; | ||
const scope = (_a = node === null || node === void 0 ? void 0 : node.parent) === null || _a === void 0 ? void 0 : _a.parent; | ||
const scope = node.parent.parent; | ||
if ((0, util_1.isTSFunctionType)(scope) || (0, util_1.isTSConstructorType)(scope)) { | ||
@@ -79,7 +55,5 @@ return rules.arrow; | ||
} | ||
else { | ||
return rules.colon; | ||
} | ||
return rules.colon; | ||
} | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'type-annotation-spacing', | ||
@@ -90,3 +64,2 @@ meta: { | ||
description: 'Require consistent spacing around type annotations', | ||
recommended: false, | ||
}, | ||
@@ -103,2 +76,12 @@ fixable: 'whitespace', | ||
{ | ||
$defs: { | ||
spacingConfig: { | ||
type: 'object', | ||
properties: { | ||
before: { type: 'boolean' }, | ||
after: { type: 'boolean' }, | ||
}, | ||
additionalProperties: false, | ||
}, | ||
}, | ||
type: 'object', | ||
@@ -111,8 +94,8 @@ properties: { | ||
properties: { | ||
colon: definition, | ||
arrow: definition, | ||
variable: definition, | ||
parameter: definition, | ||
property: definition, | ||
returnType: definition, | ||
colon: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
arrow: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
variable: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
parameter: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
property: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
returnType: { $ref: '#/items/0/$defs/spacingConfig' }, | ||
}, | ||
@@ -133,3 +116,3 @@ additionalProperties: false, | ||
const punctuators = [':', '=>']; | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
const ruleSet = createRules(options); | ||
@@ -136,0 +119,0 @@ /** |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'typedef', | ||
@@ -33,3 +10,2 @@ meta: { | ||
description: 'Require type annotations in certain places', | ||
recommended: false, | ||
}, | ||
@@ -43,2 +19,3 @@ messages: { | ||
type: 'object', | ||
additionalProperties: false, | ||
properties: { | ||
@@ -110,4 +87,3 @@ ["arrayDestructuring" /* OptionKeys.ArrayDestructuring */]: { type: 'boolean' }, | ||
// Check TS parameter property with default value like `constructor(private param: string = 'something') {}` | ||
if (annotationNode && | ||
annotationNode.type === utils_1.AST_NODE_TYPES.AssignmentPattern) { | ||
if (annotationNode.type === utils_1.AST_NODE_TYPES.AssignmentPattern) { | ||
annotationNode = annotationNode.left; | ||
@@ -120,3 +96,3 @@ } | ||
} | ||
if (annotationNode !== undefined && !annotationNode.typeAnnotation) { | ||
if (!annotationNode.typeAnnotation) { | ||
report(param, getNodeName(param)); | ||
@@ -143,50 +119,56 @@ } | ||
} | ||
return Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign(Object.assign({}, (arrayDestructuring && { | ||
ArrayPattern(node) { | ||
var _a, _b; | ||
if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.RestElement && | ||
node.parent.typeAnnotation) { | ||
return; | ||
} | ||
if (!node.typeAnnotation && | ||
!isForOfStatementContext(node) && | ||
!isAncestorHasTypeAnnotation(node) && | ||
((_b = node.parent) === null || _b === void 0 ? void 0 : _b.type) !== utils_1.AST_NODE_TYPES.AssignmentExpression) { | ||
report(node); | ||
} | ||
}, | ||
})), (arrowParameter && { | ||
ArrowFunctionExpression(node) { | ||
checkParameters(node.params); | ||
}, | ||
})), (memberVariableDeclaration && { | ||
PropertyDefinition(node) { | ||
if (!(node.value && isVariableDeclarationIgnoreFunction(node.value)) && | ||
!node.typeAnnotation) { | ||
report(node, node.key.type === utils_1.AST_NODE_TYPES.Identifier | ||
? node.key.name | ||
: undefined); | ||
} | ||
}, | ||
})), (parameter && { | ||
'FunctionDeclaration, FunctionExpression'(node) { | ||
checkParameters(node.params); | ||
}, | ||
})), (objectDestructuring && { | ||
ObjectPattern(node) { | ||
if (!node.typeAnnotation && | ||
!isForOfStatementContext(node) && | ||
!isAncestorHasTypeAnnotation(node)) { | ||
report(node); | ||
} | ||
}, | ||
})), (propertyDeclaration && { | ||
'TSIndexSignature, TSPropertySignature'(node) { | ||
if (!node.typeAnnotation) { | ||
report(node, node.type === utils_1.AST_NODE_TYPES.TSPropertySignature | ||
? getNodeName(node.key) | ||
: undefined); | ||
} | ||
}, | ||
})), { VariableDeclarator(node) { | ||
return { | ||
...(arrayDestructuring && { | ||
ArrayPattern(node) { | ||
if (node.parent.type === utils_1.AST_NODE_TYPES.RestElement && | ||
node.parent.typeAnnotation) { | ||
return; | ||
} | ||
if (!node.typeAnnotation && | ||
!isForOfStatementContext(node) && | ||
!isAncestorHasTypeAnnotation(node) && | ||
node.parent.type !== utils_1.AST_NODE_TYPES.AssignmentExpression) { | ||
report(node); | ||
} | ||
}, | ||
}), | ||
...(arrowParameter && { | ||
ArrowFunctionExpression(node) { | ||
checkParameters(node.params); | ||
}, | ||
}), | ||
...(memberVariableDeclaration && { | ||
PropertyDefinition(node) { | ||
if (!(node.value && isVariableDeclarationIgnoreFunction(node.value)) && | ||
!node.typeAnnotation) { | ||
report(node, node.key.type === utils_1.AST_NODE_TYPES.Identifier | ||
? node.key.name | ||
: undefined); | ||
} | ||
}, | ||
}), | ||
...(parameter && { | ||
'FunctionDeclaration, FunctionExpression'(node) { | ||
checkParameters(node.params); | ||
}, | ||
}), | ||
...(objectDestructuring && { | ||
ObjectPattern(node) { | ||
if (!node.typeAnnotation && | ||
!isForOfStatementContext(node) && | ||
!isAncestorHasTypeAnnotation(node)) { | ||
report(node); | ||
} | ||
}, | ||
}), | ||
...(propertyDeclaration && { | ||
'TSIndexSignature, TSPropertySignature'(node) { | ||
if (!node.typeAnnotation) { | ||
report(node, node.type === utils_1.AST_NODE_TYPES.TSPropertySignature | ||
? getNodeName(node.key) | ||
: undefined); | ||
} | ||
}, | ||
}), | ||
VariableDeclarator(node) { | ||
if (!variableDeclaration || | ||
@@ -219,5 +201,6 @@ node.id.typeAnnotation || | ||
report(node, getNodeName(node.id)); | ||
} }); | ||
}, | ||
}; | ||
}, | ||
}); | ||
//# sourceMappingURL=typedef.js.map |
@@ -27,5 +27,5 @@ "use strict"; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const tsutils = __importStar(require("tsutils")); | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const tsutils = __importStar(require("ts-api-utils")); | ||
const ts = __importStar(require("typescript")); | ||
const util = __importStar(require("../util")); | ||
const util_1 = require("../util"); | ||
@@ -81,3 +81,3 @@ /** | ||
'Object', | ||
'String', | ||
'String', // eslint-disable-line @typescript-eslint/internal/prefer-ast-types-enum | ||
'RegExp', | ||
@@ -122,3 +122,3 @@ 'Symbol', | ||
const BASE_MESSAGE = 'Avoid referencing unbound methods which may cause unintentional scoping of `this`.'; | ||
exports.default = util.createRule({ | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'unbound-method', | ||
@@ -128,3 +128,3 @@ meta: { | ||
description: 'Enforce unbound methods are called with their expected scope', | ||
recommended: 'error', | ||
recommended: 'recommended', | ||
requiresTypeChecking: true, | ||
@@ -158,5 +158,4 @@ }, | ||
create(context, [{ ignoreStatic }]) { | ||
const parserServices = util.getParserServices(context); | ||
const checker = parserServices.program.getTypeChecker(); | ||
const currentSourceFile = parserServices.program.getSourceFile(context.getFilename()); | ||
const services = (0, util_1.getParserServices)(context); | ||
const currentSourceFile = services.program.getSourceFile((0, eslint_utils_1.getFilename)(context)); | ||
function checkMethodAndReport(node, symbol) { | ||
@@ -181,3 +180,3 @@ if (!symbol) { | ||
} | ||
const objectSymbol = checker.getSymbolAtLocation(parserServices.esTreeNodeToTSNodeMap.get(node.object)); | ||
const objectSymbol = services.getSymbolAtLocation(node.object); | ||
if (objectSymbol && | ||
@@ -188,4 +187,3 @@ nativelyBoundMembers.includes(getMemberFullName(node)) && | ||
} | ||
const originalNode = parserServices.esTreeNodeToTSNodeMap.get(node); | ||
checkMethodAndReport(node, checker.getSymbolAtLocation(originalNode)); | ||
checkMethodAndReport(node, services.getSymbolAtLocation(node)); | ||
}, | ||
@@ -197,5 +195,4 @@ 'VariableDeclarator, AssignmentExpression'(node) { | ||
if (initNode && idNode.type === utils_1.AST_NODE_TYPES.ObjectPattern) { | ||
const tsNode = parserServices.esTreeNodeToTSNodeMap.get(initNode); | ||
const rightSymbol = checker.getSymbolAtLocation(tsNode); | ||
const initTypes = checker.getTypeAtLocation(tsNode); | ||
const rightSymbol = services.getSymbolAtLocation(initNode); | ||
const initTypes = services.getTypeAtLocation(initNode); | ||
const notImported = rightSymbol && isNotImported(rightSymbol, currentSourceFile); | ||
@@ -206,3 +203,3 @@ idNode.properties.forEach(property => { | ||
if (notImported && | ||
util.isIdentifier(initNode) && | ||
(0, util_1.isIdentifier)(initNode) && | ||
nativelyBoundMembers.includes(`${initNode.name}.${property.key.name}`)) { | ||
@@ -220,3 +217,2 @@ return; | ||
function checkMethod(symbol, ignoreStatic) { | ||
var _a, _b; | ||
const { valueDeclaration } = symbol; | ||
@@ -230,3 +226,3 @@ if (!valueDeclaration) { | ||
return { | ||
dangerous: ((_a = valueDeclaration.initializer) === null || _a === void 0 ? void 0 : _a.kind) === | ||
dangerous: valueDeclaration.initializer?.kind === | ||
ts.SyntaxKind.FunctionExpression, | ||
@@ -237,11 +233,11 @@ }; | ||
const decl = valueDeclaration; | ||
const firstParam = decl.parameters[0]; | ||
const firstParamIsThis = (firstParam === null || firstParam === void 0 ? void 0 : firstParam.name.kind) === ts.SyntaxKind.Identifier && | ||
(firstParam === null || firstParam === void 0 ? void 0 : firstParam.name.escapedText) === 'this'; | ||
const thisArgIsVoid = firstParamIsThis && | ||
((_b = firstParam === null || firstParam === void 0 ? void 0 : firstParam.type) === null || _b === void 0 ? void 0 : _b.kind) === ts.SyntaxKind.VoidKeyword; | ||
const firstParam = decl.parameters.at(0); | ||
const firstParamIsThis = firstParam?.name.kind === ts.SyntaxKind.Identifier && | ||
// eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison | ||
firstParam.name.escapedText === 'this'; | ||
const thisArgIsVoid = firstParamIsThis && firstParam.type?.kind === ts.SyntaxKind.VoidKeyword; | ||
return { | ||
dangerous: !thisArgIsVoid && | ||
!(ignoreStatic && | ||
tsutils.hasModifier((0, util_1.getModifiers)(valueDeclaration), ts.SyntaxKind.StaticKeyword)), | ||
tsutils.includesModifier((0, util_1.getModifiers)(valueDeclaration), ts.SyntaxKind.StaticKeyword)), | ||
firstParamIsThis, | ||
@@ -255,3 +251,3 @@ }; | ||
const parent = node.parent; | ||
switch (parent === null || parent === void 0 ? void 0 : parent.type) { | ||
switch (parent?.type) { | ||
case utils_1.AST_NODE_TYPES.IfStatement: | ||
@@ -258,0 +254,0 @@ case utils_1.AST_NODE_TYPES.ForStatement: |
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const util = __importStar(require("../util")); | ||
exports.default = util.createRule({ | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
const util_1 = require("../util"); | ||
exports.default = (0, util_1.createRule)({ | ||
name: 'unified-signatures', | ||
@@ -61,3 +39,3 @@ meta: { | ||
create(context, [{ ignoreDifferentlyNamedParameters }]) { | ||
const sourceCode = context.getSourceCode(); | ||
const sourceCode = (0, eslint_utils_1.getSourceCode)(context); | ||
//---------------------------------------------------------------------- | ||
@@ -91,4 +69,4 @@ // Helpers | ||
failureStringStart: failureStringStart(lineOfOtherOverload), | ||
type1: sourceCode.getText(typeAnnotation0 === null || typeAnnotation0 === void 0 ? void 0 : typeAnnotation0.typeAnnotation), | ||
type2: sourceCode.getText(typeAnnotation1 === null || typeAnnotation1 === void 0 ? void 0 : typeAnnotation1.typeAnnotation), | ||
type1: sourceCode.getText(typeAnnotation0?.typeAnnotation), | ||
type2: sourceCode.getText(typeAnnotation1?.typeAnnotation), | ||
}, | ||
@@ -123,5 +101,4 @@ node: p1, | ||
forEachPair(overloads, (a, b) => { | ||
var _a, _b; | ||
const signature0 = (_a = a.value) !== null && _a !== void 0 ? _a : a; | ||
const signature1 = (_b = b.value) !== null && _b !== void 0 ? _b : b; | ||
const signature0 = a.value ?? a; | ||
const signature1 = b.value ?? b; | ||
const unify = compareSignatures(signature0, signature1, isTypeParameter); | ||
@@ -147,5 +124,5 @@ if (unify !== undefined) { | ||
const bTypeParams = b.typeParameters !== undefined ? b.typeParameters.params : undefined; | ||
if (ignoreDifferentlyNamedParameters && | ||
a.params.length === b.params.length) { | ||
for (let i = 0; i < a.params.length; i += 1) { | ||
if (ignoreDifferentlyNamedParameters) { | ||
const commonParamsLength = Math.min(a.params.length, b.params.length); | ||
for (let i = 0; i < commonParamsLength; i += 1) { | ||
if (a.params[i].type === b.params[i].type && | ||
@@ -161,3 +138,3 @@ getStaticParameterName(a.params[i]) !== | ||
// If one uses a type parameter (from outside) and the other doesn't, they shouldn't be joined. | ||
util.arraysAreEqual(aTypeParams, bTypeParams, typeParametersAreEqual) && | ||
(0, util_1.arraysAreEqual)(aTypeParams, bTypeParams, typeParametersAreEqual) && | ||
signatureUsesTypeParameter(a, isTypeParameter) === | ||
@@ -173,3 +150,3 @@ signatureUsesTypeParameter(b, isTypeParameter)); | ||
// If remaining arrays are equal, the signatures differ by just one parameter type | ||
if (!util.arraysAreEqual(types1.slice(index + 1), types2.slice(index + 1), parametersAreEqual)) { | ||
if (!(0, util_1.arraysAreEqual)(types1.slice(index + 1), types2.slice(index + 1), parametersAreEqual)) { | ||
return undefined; | ||
@@ -259,4 +236,3 @@ } | ||
function isTSParameterProperty(node) { | ||
return (node.type === | ||
utils_1.AST_NODE_TYPES.TSParameterProperty); | ||
return node.type === utils_1.AST_NODE_TYPES.TSParameterProperty; | ||
} | ||
@@ -289,4 +265,3 @@ function parametersAreEqual(a, b) { | ||
return ((a.type === utils_1.AST_NODE_TYPES.RestElement) === | ||
(b.type === utils_1.AST_NODE_TYPES.RestElement) && | ||
(optionalA !== undefined) === (optionalB !== undefined)); | ||
(b.type === utils_1.AST_NODE_TYPES.RestElement) && optionalA === optionalB); | ||
} | ||
@@ -342,3 +317,3 @@ function typeParametersAreEqual(a, b) { | ||
function addOverload(signature, key, containingNode) { | ||
key = key !== null && key !== void 0 ? key : getOverloadKey(signature); | ||
key ??= getOverloadKey(signature); | ||
if (currentScope && | ||
@@ -370,5 +345,4 @@ (containingNode || signature).parent === currentScope.parent) { | ||
TSDeclareFunction(node) { | ||
var _a, _b; | ||
const exportingNode = getExportingNode(node); | ||
addOverload(node, (_b = (_a = node.id) === null || _a === void 0 ? void 0 : _a.name) !== null && _b !== void 0 ? _b : exportingNode === null || exportingNode === void 0 ? void 0 : exportingNode.type, exportingNode); | ||
addOverload(node, node.id?.name ?? exportingNode?.type, exportingNode); | ||
}, | ||
@@ -398,5 +372,4 @@ TSCallSignatureDeclaration: addOverload, | ||
function getExportingNode(node) { | ||
return node.parent && | ||
(node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration || | ||
node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) | ||
return node.parent.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration || | ||
node.parent.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration | ||
? node.parent | ||
@@ -403,0 +376,0 @@ : undefined; |
@@ -33,3 +33,3 @@ "use strict"; | ||
// deeply re-export, for convenience | ||
__exportStar(require("@typescript-eslint/utils/dist/ast-utils"), exports); | ||
__exportStar(require("@typescript-eslint/utils/ast-utils"), exports); | ||
// The following is copied from `eslint`'s source code since it doesn't exist in eslint@5. | ||
@@ -36,0 +36,0 @@ // https://github.com/eslint/eslint/blob/145aec1ab9052fbca96a44d04927c595951b1536/lib/rules/utils/ast-utils.js#L1751-L1779 |
@@ -17,5 +17,5 @@ "use strict"; | ||
const scope_manager_1 = require("@typescript-eslint/scope-manager"); | ||
const Visitor_1 = require("@typescript-eslint/scope-manager/dist/referencer/Visitor"); | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
class UnusedVarsVisitor extends Visitor_1.Visitor { | ||
const eslint_utils_1 = require("@typescript-eslint/utils/eslint-utils"); | ||
class UnusedVarsVisitor extends scope_manager_1.Visitor { | ||
// readonly #unusedVariables = new Set<TSESLint.Scope.Variable>(); | ||
@@ -43,6 +43,6 @@ constructor(context) { | ||
this.TSMethodSignature = this.visitFunctionTypeSignature; | ||
__classPrivateFieldSet(this, _UnusedVarsVisitor_scopeManager, utils_1.ESLintUtils.nullThrows(context.getSourceCode().scopeManager, 'Missing required scope manager'), "f"); | ||
__classPrivateFieldSet(this, _UnusedVarsVisitor_scopeManager, utils_1.ESLintUtils.nullThrows((0, eslint_utils_1.getSourceCode)(context).scopeManager, 'Missing required scope manager'), "f"); | ||
} | ||
static collectUnusedVariables(context) { | ||
const program = context.getSourceCode().ast; | ||
const program = (0, eslint_utils_1.getSourceCode)(context).ast; | ||
const cached = this.RESULTS_CACHE.get(program); | ||
@@ -90,3 +90,3 @@ if (cached) { | ||
if (scope) { | ||
if (scope.type === 'function-expression-name') { | ||
if (scope.type === scope_manager_1.ScopeType.functionExpressionName) { | ||
return scope.childScopes[0]; | ||
@@ -140,3 +140,3 @@ } | ||
const variable = scope.set.get('arguments'); | ||
if ((variable === null || variable === void 0 ? void 0 : variable.defs.length) === 0) { | ||
if (variable?.defs.length === 0) { | ||
this.markVariableAsUsed(variable); | ||
@@ -183,3 +183,3 @@ } | ||
if (node.left.type === utils_1.AST_NODE_TYPES.VariableDeclaration) { | ||
const variable = __classPrivateFieldGet(this, _UnusedVarsVisitor_scopeManager, "f").getDeclaredVariables(node.left)[0]; | ||
const variable = __classPrivateFieldGet(this, _UnusedVarsVisitor_scopeManager, "f").getDeclaredVariables(node.left).at(0); | ||
if (!variable) { | ||
@@ -233,3 +233,3 @@ return; | ||
// -- global augmentation can be in any file, and they do not need exports | ||
if (node.global === true) { | ||
if (node.global) { | ||
this.markVariableAsUsed('global', node.parent); | ||
@@ -297,3 +297,2 @@ } | ||
function isMergableExported(variable) { | ||
var _a, _b; | ||
// If all of the merged things are of the same type, TS will error if not all of them are exported - so we only need to find one | ||
@@ -308,4 +307,4 @@ for (const def of variable.defs) { | ||
if ((MERGABLE_TYPES.has(def.node.type) && | ||
((_a = def.node.parent) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) || | ||
((_b = def.node.parent) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
def.node.parent?.type === utils_1.AST_NODE_TYPES.ExportNamedDeclaration) || | ||
def.node.parent?.type === utils_1.AST_NODE_TYPES.ExportDefaultDeclaration) { | ||
return true; | ||
@@ -322,4 +321,3 @@ } | ||
function isExported(variable) { | ||
const definition = variable.defs[0]; | ||
if (definition) { | ||
return variable.defs.some(definition => { | ||
let node = definition.node; | ||
@@ -333,5 +331,5 @@ if (node.type === utils_1.AST_NODE_TYPES.VariableDeclarator) { | ||
return node.parent.type.indexOf('Export') === 0; | ||
} | ||
return false; | ||
}); | ||
} | ||
const LOGICAL_ASSIGNMENT_OPERATORS = new Set(['&&=', '||=', '??=']); | ||
/** | ||
@@ -351,3 +349,2 @@ * Determines if the variable is used. | ||
variable.defs.forEach(def => { | ||
var _a, _b; | ||
// FunctionDeclarations | ||
@@ -359,4 +356,4 @@ if (def.type === utils_1.TSESLint.Scope.DefinitionType.FunctionName) { | ||
if (def.type === utils_1.TSESLint.Scope.DefinitionType.Variable && | ||
(((_a = def.node.init) === null || _a === void 0 ? void 0 : _a.type) === utils_1.AST_NODE_TYPES.FunctionExpression || | ||
((_b = def.node.init) === null || _b === void 0 ? void 0 : _b.type) === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)) { | ||
(def.node.init?.type === utils_1.AST_NODE_TYPES.FunctionExpression || | ||
def.node.init?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression)) { | ||
functionDefinitions.add(def.node.init); | ||
@@ -540,2 +537,3 @@ } | ||
((parent.type === utils_1.AST_NODE_TYPES.AssignmentExpression && | ||
!LOGICAL_ASSIGNMENT_OPERATORS.has(parent.operator) && | ||
grandparent.type === utils_1.AST_NODE_TYPES.ExpressionStatement && | ||
@@ -542,0 +540,0 @@ parent.left === id) || |
@@ -28,2 +28,32 @@ "use strict"; | ||
* ``` | ||
* foo(() => 1) | ||
* ``` | ||
*/ | ||
function isFunctionArgument(parent, callee) { | ||
return (parent.type === utils_1.AST_NODE_TYPES.CallExpression && | ||
// make sure this isn't an IIFE | ||
parent.callee !== callee); | ||
} | ||
/** | ||
* Checks if a node is type-constrained in JSX | ||
* ``` | ||
* <Foo x={() => {}} /> | ||
* <Bar>{() => {}}</Bar> | ||
* <Baz {...props} /> | ||
* ``` | ||
*/ | ||
function isTypedJSX(node) { | ||
return (node.type === utils_1.AST_NODE_TYPES.JSXExpressionContainer || | ||
node.type === utils_1.AST_NODE_TYPES.JSXSpreadAttribute); | ||
} | ||
function isTypedParent(parent, callee) { | ||
return ((0, astUtils_1.isTypeAssertion)(parent) || | ||
isVariableDeclaratorWithTypeAnnotation(parent) || | ||
isPropertyDefinitionWithTypeAnnotation(parent) || | ||
isFunctionArgument(parent, callee) || | ||
isTypedJSX(parent)); | ||
} | ||
/** | ||
* Checks if a node belongs to: | ||
* ``` | ||
* new Foo(() => {}) | ||
@@ -49,16 +79,8 @@ * ^^^^^^^^ | ||
} | ||
const objectExpr = property.parent; // this shouldn't happen, checking just in case | ||
/* istanbul ignore if */ if (!objectExpr || | ||
objectExpr.type !== utils_1.AST_NODE_TYPES.ObjectExpression) { | ||
const objectExpr = property.parent; | ||
if (objectExpr.type !== utils_1.AST_NODE_TYPES.ObjectExpression) { | ||
return false; | ||
} | ||
const parent = objectExpr.parent; // this shouldn't happen, checking just in case | ||
/* istanbul ignore if */ if (!parent) { | ||
return false; | ||
} | ||
return ((0, astUtils_1.isTypeAssertion)(parent) || | ||
isPropertyDefinitionWithTypeAnnotation(parent) || | ||
isVariableDeclaratorWithTypeAnnotation(parent) || | ||
isFunctionArgument(parent) || | ||
isPropertyOfObjectWithType(parent)); | ||
const parent = objectExpr.parent; | ||
return isTypedParent(parent) || isPropertyOfObjectWithType(parent); | ||
} | ||
@@ -77,6 +99,2 @@ /** | ||
function doesImmediatelyReturnFunctionExpression({ body, }) { | ||
// Should always have a body; really checking just in case | ||
/* istanbul ignore if */ if (!body) { | ||
return false; | ||
} | ||
// Check if body is a block with a single statement | ||
@@ -98,13 +116,2 @@ if (body.type === utils_1.AST_NODE_TYPES.BlockStatement && body.body.length === 1) { | ||
/** | ||
* Checks if a node belongs to: | ||
* ``` | ||
* foo(() => 1) | ||
* ``` | ||
*/ | ||
function isFunctionArgument(parent, callee) { | ||
return (parent.type === utils_1.AST_NODE_TYPES.CallExpression && | ||
// make sure this isn't an IIFE | ||
parent.callee !== callee); | ||
} | ||
/** | ||
* Checks if a function belongs to: | ||
@@ -137,7 +144,4 @@ * ``` | ||
} | ||
return ((0, astUtils_1.isTypeAssertion)(parent) || | ||
isVariableDeclaratorWithTypeAnnotation(parent) || | ||
isPropertyDefinitionWithTypeAnnotation(parent) || | ||
return (isTypedParent(parent, node) || | ||
isPropertyOfObjectWithType(parent) || | ||
isFunctionArgument(parent, node) || | ||
isConstructorArgument(parent)); | ||
@@ -205,8 +209,8 @@ } | ||
let ancestor = node.parent; | ||
if ((ancestor === null || ancestor === void 0 ? void 0 : ancestor.type) === utils_1.AST_NODE_TYPES.Property) { | ||
if (ancestor.type === utils_1.AST_NODE_TYPES.Property) { | ||
ancestor = ancestor.value; | ||
} | ||
// if the ancestor is not a return, then this function was not returned at all, so we can exit early | ||
const isReturnStatement = (ancestor === null || ancestor === void 0 ? void 0 : ancestor.type) === utils_1.AST_NODE_TYPES.ReturnStatement; | ||
const isBodylessArrow = (ancestor === null || ancestor === void 0 ? void 0 : ancestor.type) === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && | ||
const isReturnStatement = ancestor.type === utils_1.AST_NODE_TYPES.ReturnStatement; | ||
const isBodylessArrow = ancestor.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && | ||
ancestor.body.type !== utils_1.AST_NODE_TYPES.BlockStatement; | ||
@@ -232,2 +236,7 @@ if (!isReturnStatement && !isBodylessArrow) { | ||
break; | ||
case utils_1.AST_NODE_TYPES.PropertyDefinition: | ||
if (ancestor.typeAnnotation) { | ||
return true; | ||
} | ||
break; | ||
} | ||
@@ -234,0 +243,0 @@ ancestor = ancestor.parent; |
@@ -40,3 +40,3 @@ "use strict"; | ||
} | ||
catch (_a) { | ||
catch { | ||
return null; | ||
@@ -43,0 +43,0 @@ } |
"use strict"; | ||
// adapted from https://github.com/eslint/eslint/blob/5bdaae205c3a0089ea338b382df59e21d5b06436/lib/rules/utils/ast-utils.js#L1668-L1787 | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getFunctionHeadLoc = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const astUtils_1 = require("./astUtils"); | ||
/** | ||
* Creates a report location for the given function. | ||
* The location only encompasses the "start" of the function, and not the body | ||
* Gets the `(` token of the given function node. | ||
* @param node The function node to get. | ||
* @param sourceCode The source code object to get tokens. | ||
* @returns `(` token. | ||
*/ | ||
function getOpeningParenOfParams(node, sourceCode) { | ||
// If the node is an arrow function and doesn't have parens, this returns the identifier of the first param. | ||
if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && | ||
node.params.length === 1) { | ||
const argToken = utils_1.ESLintUtils.nullThrows(sourceCode.getFirstToken(node.params[0]), utils_1.ESLintUtils.NullThrowsReasons.MissingToken('parameter', 'arrow function')); | ||
const maybeParenToken = sourceCode.getTokenBefore(argToken); | ||
return maybeParenToken && (0, astUtils_1.isOpeningParenToken)(maybeParenToken) | ||
? maybeParenToken | ||
: argToken; | ||
} | ||
// Otherwise, returns paren. | ||
return node.id != null | ||
? utils_1.ESLintUtils.nullThrows(sourceCode.getTokenAfter(node.id, astUtils_1.isOpeningParenToken), utils_1.ESLintUtils.NullThrowsReasons.MissingToken('id', 'function')) | ||
: utils_1.ESLintUtils.nullThrows(sourceCode.getFirstToken(node, astUtils_1.isOpeningParenToken), utils_1.ESLintUtils.NullThrowsReasons.MissingToken('opening parenthesis', 'function')); | ||
} | ||
/** | ||
* Gets the location of the given function node for reporting. | ||
* | ||
* eg. | ||
* | ||
* ``` | ||
* function foo(args) {} | ||
* ^^^^^^^^^^^^^^^^^^ | ||
* | ||
* get y(args) {} | ||
* ^^^^^^^^^^^ | ||
* | ||
* const x = (args) => {} | ||
* ^^^^^^^^^ | ||
* ``` | ||
* - `function foo() {}` | ||
* ^^^^^^^^^^^^ | ||
* - `(function foo() {})` | ||
* ^^^^^^^^^^^^ | ||
* - `(function() {})` | ||
* ^^^^^^^^ | ||
* - `function* foo() {}` | ||
* ^^^^^^^^^^^^^ | ||
* - `(function* foo() {})` | ||
* ^^^^^^^^^^^^^ | ||
* - `(function*() {})` | ||
* ^^^^^^^^^ | ||
* - `() => {}` | ||
* ^^ | ||
* - `async () => {}` | ||
* ^^ | ||
* - `({ foo: function foo() {} })` | ||
* ^^^^^^^^^^^^^^^^^ | ||
* - `({ foo: function() {} })` | ||
* ^^^^^^^^^^^^^ | ||
* - `({ ['foo']: function() {} })` | ||
* ^^^^^^^^^^^^^^^^^ | ||
* - `({ [foo]: function() {} })` | ||
* ^^^^^^^^^^^^^^^ | ||
* - `({ foo() {} })` | ||
* ^^^ | ||
* - `({ foo: function* foo() {} })` | ||
* ^^^^^^^^^^^^^^^^^^ | ||
* - `({ foo: function*() {} })` | ||
* ^^^^^^^^^^^^^^ | ||
* - `({ ['foo']: function*() {} })` | ||
* ^^^^^^^^^^^^^^^^^^ | ||
* - `({ [foo]: function*() {} })` | ||
* ^^^^^^^^^^^^^^^^ | ||
* - `({ *foo() {} })` | ||
* ^^^^ | ||
* - `({ foo: async function foo() {} })` | ||
* ^^^^^^^^^^^^^^^^^^^^^^^ | ||
* - `({ foo: async function() {} })` | ||
* ^^^^^^^^^^^^^^^^^^^ | ||
* - `({ ['foo']: async function() {} })` | ||
* ^^^^^^^^^^^^^^^^^^^^^^^ | ||
* - `({ [foo]: async function() {} })` | ||
* ^^^^^^^^^^^^^^^^^^^^^ | ||
* - `({ async foo() {} })` | ||
* ^^^^^^^^^ | ||
* - `({ get foo() {} })` | ||
* ^^^^^^^ | ||
* - `({ set foo(a) {} })` | ||
* ^^^^^^^ | ||
* - `class A { constructor() {} }` | ||
* ^^^^^^^^^^^ | ||
* - `class A { foo() {} }` | ||
* ^^^ | ||
* - `class A { *foo() {} }` | ||
* ^^^^ | ||
* - `class A { async foo() {} }` | ||
* ^^^^^^^^^ | ||
* - `class A { ['foo']() {} }` | ||
* ^^^^^^^ | ||
* - `class A { *['foo']() {} }` | ||
* ^^^^^^^^ | ||
* - `class A { async ['foo']() {} }` | ||
* ^^^^^^^^^^^^^ | ||
* - `class A { [foo]() {} }` | ||
* ^^^^^ | ||
* - `class A { *[foo]() {} }` | ||
* ^^^^^^ | ||
* - `class A { async [foo]() {} }` | ||
* ^^^^^^^^^^^ | ||
* - `class A { get foo() {} }` | ||
* ^^^^^^^ | ||
* - `class A { set foo(a) {} }` | ||
* ^^^^^^^ | ||
* - `class A { static foo() {} }` | ||
* ^^^^^^^^^^ | ||
* - `class A { static *foo() {} }` | ||
* ^^^^^^^^^^^ | ||
* - `class A { static async foo() {} }` | ||
* ^^^^^^^^^^^^^^^^ | ||
* - `class A { static get foo() {} }` | ||
* ^^^^^^^^^^^^^^ | ||
* - `class A { static set foo(a) {} }` | ||
* ^^^^^^^^^^^^^^ | ||
* - `class A { foo = function() {} }` | ||
* ^^^^^^^^^^^^^^ | ||
* - `class A { static foo = function() {} }` | ||
* ^^^^^^^^^^^^^^^^^^^^^ | ||
* - `class A { foo = (a, b) => {} }` | ||
* ^^^^^^ | ||
* @param node The function node to get. | ||
* @param sourceCode The source code object to get tokens. | ||
* @returns The location of the function node for reporting. | ||
*/ | ||
function getFunctionHeadLoc(node, sourceCode) { | ||
function getLocStart() { | ||
if (node.parent && node.parent.type === utils_1.AST_NODE_TYPES.MethodDefinition) { | ||
// return the start location for class method | ||
if (node.parent.decorators && node.parent.decorators.length > 0) { | ||
// exclude decorators | ||
return sourceCode.getTokenAfter(node.parent.decorators[node.parent.decorators.length - 1]).loc.start; | ||
} | ||
return node.parent.loc.start; | ||
const parent = node.parent; | ||
let start = null; | ||
let end = null; | ||
if (parent.type === utils_1.AST_NODE_TYPES.MethodDefinition || | ||
parent.type === utils_1.AST_NODE_TYPES.PropertyDefinition) { | ||
// the decorator's range is included within the member | ||
// however it's usually irrelevant to the member itself - so we don't want | ||
// to highlight it ever. | ||
if (parent.decorators.length > 0) { | ||
const lastDecorator = parent.decorators[parent.decorators.length - 1]; | ||
const firstTokenAfterDecorator = utils_1.ESLintUtils.nullThrows(sourceCode.getTokenAfter(lastDecorator), utils_1.ESLintUtils.NullThrowsReasons.MissingToken('modifier or member name', 'class member')); | ||
start = firstTokenAfterDecorator.loc.start; | ||
} | ||
if (node.parent && | ||
node.parent.type === utils_1.AST_NODE_TYPES.Property && | ||
node.parent.method) { | ||
// return the start location for object method shorthand | ||
return node.parent.loc.start; | ||
else { | ||
start = parent.loc.start; | ||
} | ||
// return the start location for a regular function | ||
return node.loc.start; | ||
end = getOpeningParenOfParams(node, sourceCode).loc.start; | ||
} | ||
function getLocEnd() { | ||
if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { | ||
// find the end location for arrow function expression | ||
return sourceCode.getTokenBefore(node.body, token => token.type === utils_1.AST_TOKEN_TYPES.Punctuator && token.value === '=>').loc.end; | ||
} | ||
// return the end location for a regular function | ||
return sourceCode.getTokenBefore(node.body).loc.end; | ||
else if (parent.type === utils_1.AST_NODE_TYPES.Property) { | ||
start = parent.loc.start; | ||
end = getOpeningParenOfParams(node, sourceCode).loc.start; | ||
} | ||
else if (node.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression) { | ||
const arrowToken = utils_1.ESLintUtils.nullThrows(sourceCode.getTokenBefore(node.body, astUtils_1.isArrowToken), utils_1.ESLintUtils.NullThrowsReasons.MissingToken('arrow token', 'arrow function')); | ||
start = arrowToken.loc.start; | ||
end = arrowToken.loc.end; | ||
} | ||
else { | ||
start = node.loc.start; | ||
end = getOpeningParenOfParams(node, sourceCode).loc.start; | ||
} | ||
return { | ||
start: getLocStart(), | ||
end: getLocEnd(), | ||
start: Object.assign({}, start), | ||
end: Object.assign({}, end), | ||
}; | ||
@@ -53,0 +161,0 @@ } |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getBinaryOperatorPrecedence = exports.getOperatorPrecedence = exports.OperatorPrecedence = void 0; | ||
exports.getBinaryOperatorPrecedence = exports.getOperatorPrecedence = exports.getOperatorPrecedenceForNode = exports.OperatorPrecedence = void 0; | ||
const utils_1 = require("@typescript-eslint/utils"); | ||
const typescript_1 = require("typescript"); | ||
@@ -173,5 +174,88 @@ var OperatorPrecedence; | ||
OperatorPrecedence[OperatorPrecedence["Invalid"] = -1] = "Invalid"; | ||
})(OperatorPrecedence = exports.OperatorPrecedence || (exports.OperatorPrecedence = {})); | ||
})(OperatorPrecedence || (exports.OperatorPrecedence = OperatorPrecedence = {})); | ||
function getOperatorPrecedenceForNode(node) { | ||
switch (node.type) { | ||
case utils_1.AST_NODE_TYPES.SpreadElement: | ||
case utils_1.AST_NODE_TYPES.RestElement: | ||
return OperatorPrecedence.Spread; | ||
case utils_1.AST_NODE_TYPES.YieldExpression: | ||
return OperatorPrecedence.Yield; | ||
case utils_1.AST_NODE_TYPES.ConditionalExpression: | ||
return OperatorPrecedence.Conditional; | ||
case utils_1.AST_NODE_TYPES.SequenceExpression: | ||
return OperatorPrecedence.Comma; | ||
case utils_1.AST_NODE_TYPES.AssignmentExpression: | ||
case utils_1.AST_NODE_TYPES.BinaryExpression: | ||
case utils_1.AST_NODE_TYPES.LogicalExpression: | ||
switch (node.operator) { | ||
case '==': | ||
case '+=': | ||
case '-=': | ||
case '**=': | ||
case '*=': | ||
case '/=': | ||
case '%=': | ||
case '<<=': | ||
case '>>=': | ||
case '>>>=': | ||
case '&=': | ||
case '^=': | ||
case '|=': | ||
case '||=': | ||
case '&&=': | ||
case '??=': | ||
return OperatorPrecedence.Assignment; | ||
default: | ||
return getBinaryOperatorPrecedence(node.operator); | ||
} | ||
case utils_1.AST_NODE_TYPES.TSTypeAssertion: | ||
case utils_1.AST_NODE_TYPES.TSNonNullExpression: | ||
case utils_1.AST_NODE_TYPES.UnaryExpression: | ||
case utils_1.AST_NODE_TYPES.AwaitExpression: | ||
return OperatorPrecedence.Unary; | ||
case utils_1.AST_NODE_TYPES.UpdateExpression: | ||
// TODO: Should prefix `++` and `--` be moved to the `Update` precedence? | ||
if (node.prefix) { | ||
return OperatorPrecedence.Unary; | ||
} | ||
return OperatorPrecedence.Update; | ||
case utils_1.AST_NODE_TYPES.ChainExpression: | ||
return getOperatorPrecedenceForNode(node.expression); | ||
case utils_1.AST_NODE_TYPES.CallExpression: | ||
return OperatorPrecedence.LeftHandSide; | ||
case utils_1.AST_NODE_TYPES.NewExpression: | ||
return node.arguments.length > 0 | ||
? OperatorPrecedence.Member | ||
: OperatorPrecedence.LeftHandSide; | ||
case utils_1.AST_NODE_TYPES.TaggedTemplateExpression: | ||
case utils_1.AST_NODE_TYPES.MemberExpression: | ||
case utils_1.AST_NODE_TYPES.MetaProperty: | ||
return OperatorPrecedence.Member; | ||
case utils_1.AST_NODE_TYPES.TSAsExpression: | ||
return OperatorPrecedence.Relational; | ||
case utils_1.AST_NODE_TYPES.ThisExpression: | ||
case utils_1.AST_NODE_TYPES.Super: | ||
case utils_1.AST_NODE_TYPES.Identifier: | ||
case utils_1.AST_NODE_TYPES.PrivateIdentifier: | ||
case utils_1.AST_NODE_TYPES.Literal: | ||
case utils_1.AST_NODE_TYPES.ArrayExpression: | ||
case utils_1.AST_NODE_TYPES.ObjectExpression: | ||
case utils_1.AST_NODE_TYPES.FunctionExpression: | ||
case utils_1.AST_NODE_TYPES.ArrowFunctionExpression: | ||
case utils_1.AST_NODE_TYPES.ClassExpression: | ||
case utils_1.AST_NODE_TYPES.TemplateLiteral: | ||
case utils_1.AST_NODE_TYPES.JSXElement: | ||
case utils_1.AST_NODE_TYPES.JSXFragment: | ||
// we don't have nodes for these cases | ||
// case SyntaxKind.ParenthesizedExpression: | ||
// case SyntaxKind.OmittedExpression: | ||
return OperatorPrecedence.Primary; | ||
default: | ||
return OperatorPrecedence.Invalid; | ||
} | ||
} | ||
exports.getOperatorPrecedenceForNode = getOperatorPrecedenceForNode; | ||
function getOperatorPrecedence(nodeKind, operatorKind, hasArguments) { | ||
switch (nodeKind) { | ||
// A list of comma-separated expressions. This node is only created by transformations. | ||
case typescript_1.SyntaxKind.CommaListExpression: | ||
@@ -232,2 +316,3 @@ return OperatorPrecedence.Comma; | ||
case typescript_1.SyntaxKind.AsExpression: | ||
case typescript_1.SyntaxKind.SatisfiesExpression: | ||
return OperatorPrecedence.Relational; | ||
@@ -266,38 +351,64 @@ case typescript_1.SyntaxKind.ThisKeyword: | ||
case typescript_1.SyntaxKind.QuestionQuestionToken: | ||
case '??': | ||
return OperatorPrecedence.Coalesce; | ||
case typescript_1.SyntaxKind.BarBarToken: | ||
case '||': | ||
return OperatorPrecedence.LogicalOR; | ||
case typescript_1.SyntaxKind.AmpersandAmpersandToken: | ||
case '&&': | ||
return OperatorPrecedence.LogicalAND; | ||
case typescript_1.SyntaxKind.BarToken: | ||
case '|': | ||
return OperatorPrecedence.BitwiseOR; | ||
case typescript_1.SyntaxKind.CaretToken: | ||
case '^': | ||
return OperatorPrecedence.BitwiseXOR; | ||
case typescript_1.SyntaxKind.AmpersandToken: | ||
case '&': | ||
return OperatorPrecedence.BitwiseAND; | ||
case typescript_1.SyntaxKind.EqualsEqualsToken: | ||
case '==': | ||
case typescript_1.SyntaxKind.ExclamationEqualsToken: | ||
case '!=': | ||
case typescript_1.SyntaxKind.EqualsEqualsEqualsToken: | ||
case '===': | ||
case typescript_1.SyntaxKind.ExclamationEqualsEqualsToken: | ||
case '!==': | ||
return OperatorPrecedence.Equality; | ||
case typescript_1.SyntaxKind.LessThanToken: | ||
case '<': | ||
case typescript_1.SyntaxKind.GreaterThanToken: | ||
case '>': | ||
case typescript_1.SyntaxKind.LessThanEqualsToken: | ||
case '<=': | ||
case typescript_1.SyntaxKind.GreaterThanEqualsToken: | ||
case '>=': | ||
case typescript_1.SyntaxKind.InstanceOfKeyword: | ||
case 'instanceof': | ||
case typescript_1.SyntaxKind.InKeyword: | ||
case 'in': | ||
case typescript_1.SyntaxKind.AsKeyword: | ||
// case 'as': -- we don't have a token for this | ||
return OperatorPrecedence.Relational; | ||
case typescript_1.SyntaxKind.LessThanLessThanToken: | ||
case '<<': | ||
case typescript_1.SyntaxKind.GreaterThanGreaterThanToken: | ||
case '>>': | ||
case typescript_1.SyntaxKind.GreaterThanGreaterThanGreaterThanToken: | ||
case '>>>': | ||
return OperatorPrecedence.Shift; | ||
case typescript_1.SyntaxKind.PlusToken: | ||
case '+': | ||
case typescript_1.SyntaxKind.MinusToken: | ||
case '-': | ||
return OperatorPrecedence.Additive; | ||
case typescript_1.SyntaxKind.AsteriskToken: | ||
case '*': | ||
case typescript_1.SyntaxKind.SlashToken: | ||
case '/': | ||
case typescript_1.SyntaxKind.PercentToken: | ||
case '%': | ||
return OperatorPrecedence.Multiplicative; | ||
case typescript_1.SyntaxKind.AsteriskAsteriskToken: | ||
case '**': | ||
return OperatorPrecedence.Exponentiation; | ||
@@ -304,0 +415,0 @@ } |
@@ -7,3 +7,3 @@ "use strict"; | ||
exports.getStringLength = void 0; | ||
const grapheme_splitter_1 = __importDefault(require("grapheme-splitter")); | ||
const graphemer_1 = __importDefault(require("graphemer")); | ||
let splitter; | ||
@@ -17,3 +17,3 @@ function isASCII(value) { | ||
} | ||
splitter !== null && splitter !== void 0 ? splitter : (splitter = new grapheme_splitter_1.default()); | ||
splitter ??= new graphemer_1.default(); | ||
return splitter.countGraphemes(value); | ||
@@ -20,0 +20,0 @@ } |
@@ -6,3 +6,3 @@ "use strict"; | ||
function getThisExpression(node) { | ||
while (node) { | ||
while (true) { | ||
if (node.type === utils_1.AST_NODE_TYPES.CallExpression) { | ||
@@ -9,0 +9,0 @@ node = node.callee; |
@@ -15,6 +15,9 @@ "use strict"; | ||
let code = sourceCode.getText(innerNode); | ||
// check the inner expression's precedence | ||
if (!isStrongPrecedenceNode(innerNode)) { | ||
// the code we are adding might have stronger precedence than our wrapped node | ||
// let's wrap our node in parens in case it has a weaker precedence than the code we are wrapping it in | ||
/** | ||
* Wrap our node in parens to prevent the following cases: | ||
* - It has a weaker precedence than the code we are wrapping it in | ||
* - It's gotten mistaken as block statement instead of object expression | ||
*/ | ||
if (!isStrongPrecedenceNode(innerNode) || | ||
isObjectExpressionInOneLineReturn(node, innerNode)) { | ||
code = `(${code})`; | ||
@@ -48,2 +51,4 @@ } | ||
innerNode.type === utils_1.AST_NODE_TYPES.Identifier || | ||
innerNode.type === utils_1.AST_NODE_TYPES.TSTypeReference || | ||
innerNode.type === utils_1.AST_NODE_TYPES.TSTypeOperator || | ||
innerNode.type === utils_1.AST_NODE_TYPES.ArrayExpression || | ||
@@ -54,3 +59,4 @@ innerNode.type === utils_1.AST_NODE_TYPES.ObjectExpression || | ||
innerNode.type === utils_1.AST_NODE_TYPES.NewExpression || | ||
innerNode.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression); | ||
innerNode.type === utils_1.AST_NODE_TYPES.TaggedTemplateExpression || | ||
innerNode.type === utils_1.AST_NODE_TYPES.TSInstantiationExpression); | ||
} | ||
@@ -144,2 +150,10 @@ exports.isStrongPrecedenceNode = isStrongPrecedenceNode; | ||
} | ||
/** | ||
* Checks if a node's parent is arrow function expression and a inner node is object expression | ||
*/ | ||
function isObjectExpressionInOneLineReturn(node, innerNode) { | ||
return (node.parent?.type === utils_1.AST_NODE_TYPES.ArrowFunctionExpression && | ||
node.parent.body === node && | ||
innerNode.type === utils_1.AST_NODE_TYPES.ObjectExpression); | ||
} | ||
//# sourceMappingURL=getWrappingFixer.js.map |
@@ -24,2 +24,3 @@ "use strict"; | ||
__exportStar(require("./getOperatorPrecedence"), exports); | ||
__exportStar(require("./getStaticStringValue"), exports); | ||
__exportStar(require("./getStringLength"), exports); | ||
@@ -26,0 +27,0 @@ __exportStar(require("./getThisExpression"), exports); |
@@ -106,4 +106,3 @@ "use strict"; | ||
MemberNameType[MemberNameType["Expression"] = 4] = "Expression"; | ||
})(MemberNameType || (MemberNameType = {})); | ||
exports.MemberNameType = MemberNameType; | ||
})(MemberNameType || (exports.MemberNameType = MemberNameType = {})); | ||
/** | ||
@@ -134,8 +133,6 @@ * Gets a string name representation of the name of the given MethodDefinition | ||
} | ||
else { | ||
return { | ||
type: MemberNameType.Normal, | ||
name, | ||
}; | ||
} | ||
return { | ||
type: MemberNameType.Normal, | ||
name, | ||
}; | ||
} | ||
@@ -159,3 +156,3 @@ return { | ||
function formatWordList(words) { | ||
if (!(words === null || words === void 0 ? void 0 : words.length)) { | ||
if (!words.length) { | ||
return ''; | ||
@@ -162,0 +159,0 @@ } |
@@ -93,2 +93,8 @@ --- | ||
If you don't care about the general structure of the code, then you will not need this rule. | ||
It can sometimes be useful to place overload signatures alongside other meaningful parts of a type. | ||
For example, if each of a function's overloads corresponds to a different property, you might wish to put each overloads next to its corresponding property. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`unified-signatures`](./unified-signatures.md) |
@@ -25,3 +25,3 @@ --- | ||
```ts | ||
```ts option='{ "default": "array" }' | ||
const x: Array<string> = ['a', 'b']; | ||
@@ -33,3 +33,3 @@ const y: ReadonlyArray<string> = ['a', 'b']; | ||
```ts | ||
```ts option='{ "default": "array" }' | ||
const x: string[] = ['a', 'b']; | ||
@@ -47,3 +47,3 @@ const y: readonly string[] = ['a', 'b']; | ||
```ts | ||
```ts option='{ "default": "generic" }' | ||
const x: string[] = ['a', 'b']; | ||
@@ -55,3 +55,3 @@ const y: readonly string[] = ['a', 'b']; | ||
```ts | ||
```ts option='{ "default": "generic" }' | ||
const x: Array<string> = ['a', 'b']; | ||
@@ -70,3 +70,3 @@ const y: ReadonlyArray<string> = ['a', 'b']; | ||
```ts | ||
```ts option='{ "default": "array-simple" }' | ||
const a: (string | number)[] = ['a', 'b']; | ||
@@ -82,3 +82,3 @@ const b: { prop: string }[] = [{ prop: 'a' }]; | ||
```ts | ||
```ts option='{ "default": "array-simple" }' | ||
const a: Array<string | number> = ['a', 'b']; | ||
@@ -110,1 +110,9 @@ const b: Array<{ prop: string }> = [{ prop: 'a' }]; | ||
| `generic` | `generic` | `Array<number>` | `Array<Foo & Bar>` | `ReadonlyArray<number>` | `ReadonlyArray<Foo & Bar>` | | ||
## When Not To Use It | ||
This rule is purely a stylistic rule for maintaining consistency in your project. | ||
You can turn it off if you don't want to keep a consistent style for array types. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -40,2 +40,4 @@ --- | ||
If you want to allow code to `await` non-Promise values. | ||
This is generally not preferred, but can sometimes be useful for visual consistency. | ||
For example, if your framework is in transition from one style of asynchronous code to another, it may be useful to include `await`s unnecessarily. | ||
This is generally not preferred but can sometimes be useful for visual consistency. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -36,3 +36,3 @@ --- | ||
```ts | ||
```ts option='{ "ts-ignore": true }' | ||
if (false) { | ||
@@ -52,3 +52,3 @@ // @ts-ignore: Unreachable code error | ||
```ts | ||
```ts option='{ "ts-ignore": true }' | ||
if (false) { | ||
@@ -70,3 +70,3 @@ // Compiler warns about unreachable code error | ||
```ts | ||
```ts option='{ "ts-expect-error": "allow-with-description" }' | ||
if (false) { | ||
@@ -84,3 +84,3 @@ // @ts-expect-error | ||
```ts | ||
```ts option='{ "ts-expect-error": "allow-with-description" }' | ||
if (false) { | ||
@@ -108,3 +108,4 @@ // @ts-expect-error: Unreachable code error | ||
```ts | ||
<!-- prettier-ignore --> | ||
```ts option='{ "ts-expect-error": { "descriptionFormat": "^: TS\\\\d+ because .+$" } }' | ||
// @ts-expect-error: the library definition is wrong | ||
@@ -116,3 +117,4 @@ const a = doSomething('hello'); | ||
```ts | ||
<!-- prettier-ignore --> | ||
```ts option='{ "ts-expect-error": { "descriptionFormat": "^: TS\\\\d+ because .+$" } }' | ||
// @ts-expect-error: TS1234 because the library definition is wrong | ||
@@ -132,3 +134,3 @@ const a = doSomething('hello'); | ||
```ts | ||
```ts option='{ "ts-expect-error": "allow-with-description", "minimumDescriptionLength": 10 }' | ||
if (false) { | ||
@@ -142,3 +144,3 @@ // @ts-expect-error: TODO | ||
```ts | ||
```ts option='{ "ts-expect-error": "allow-with-description", "minimumDescriptionLength": 10 }' | ||
if (false) { | ||
@@ -152,3 +154,4 @@ // @ts-expect-error The rationale for this override is described in issue #1337 on GitLab | ||
If you want to use all of the TypeScript directives. | ||
If your project or its dependencies were not architected with strong type safety in mind, it can be difficult to always adhere to proper TypeScript semantics. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -155,0 +158,0 @@ ## Further Reading |
@@ -39,2 +39,2 @@ --- | ||
If you are still using TSLint. | ||
If you are still using TSLint alongside ESLint. |
@@ -78,50 +78,3 @@ --- | ||
```ts | ||
const defaultTypes = { | ||
String: { | ||
message: 'Use string instead', | ||
fixWith: 'string', | ||
}, | ||
Boolean: { | ||
message: 'Use boolean instead', | ||
fixWith: 'boolean', | ||
}, | ||
Number: { | ||
message: 'Use number instead', | ||
fixWith: 'number', | ||
}, | ||
Symbol: { | ||
message: 'Use symbol instead', | ||
fixWith: 'symbol', | ||
}, | ||
BigInt: { | ||
message: 'Use bigint instead', | ||
fixWith: 'bigint', | ||
}, | ||
Function: { | ||
message: [ | ||
'The `Function` type accepts any function-like value.', | ||
'It provides no type safety when calling the function, which can be a common source of bugs.', | ||
'It also accepts things like class declarations, which will throw at runtime as they will not be called with `new`.', | ||
'If you are expecting the function to accept certain arguments, you should explicitly define the function shape.', | ||
].join('\n'), | ||
}, | ||
// object typing | ||
Object: { | ||
message: [ | ||
'The `Object` type actually means "any non-nullish value", so it is marginally better than `unknown`.', | ||
'- If you want a type meaning "any object", you probably want `object` instead.', | ||
'- If you want a type meaning "any value", you probably want `unknown` instead.', | ||
].join('\n'), | ||
}, | ||
'{}': { | ||
message: [ | ||
'`{}` actually means "any non-nullish value".', | ||
'- If you want a type meaning "any object", you probably want `object` instead.', | ||
'- If you want a type meaning "any value", you probably want `unknown` instead.', | ||
'- If you want a type meaning "empty object", you probably want `Record<string, never>` instead.', | ||
].join('\n'), | ||
}, | ||
}; | ||
``` | ||
<!-- Inject default options --> | ||
@@ -143,2 +96,3 @@ </details> | ||
- `fixWith?: string` - a string to replace the banned type with when the fixer is run. If this is omitted, no fix will be done. | ||
- `suggest?: string[]` - a list of suggested replacements for the banned type. | ||
@@ -176,1 +130,6 @@ ### `extendDefaults` | ||
``` | ||
## When Not To Use It | ||
If your project is a rare one that intentionally deals with the class equivalents of primitives, it might not be worthwhile to enable the default `ban-types` options. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/block-spacing`](https://eslint.org/docs/rules/block-spacing) rule. | ||
This version adds support for TypeScript related blocks (interfaces, object type literals and enums). |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/brace-style`](https://eslint.org/docs/rules/brace-style) rule. | ||
It adds support for `enum`, `interface`, `namespace` and `module` declarations. |
@@ -8,4 +8,7 @@ :::danger Deprecated | ||
<!-- | ||
This doc file has been left on purpose because `camelcase` is a core eslint rule. | ||
This exists to help direct people to the replacement rule. | ||
This doc file has been left on purpose because `camelcase` is a core ESLint | ||
rule. This exists to help direct people to the replacement rule. | ||
Note that there is no actual way to get to this page in the normal navigation, | ||
so end-users will only be able to get to this page from the search bar. | ||
--> |
@@ -34,5 +34,3 @@ --- | ||
```ts | ||
/* eslint @typescript-eslint/class-literal-property-style: ["error", "fields"] */ | ||
```ts option='"fields"' | ||
class Mx { | ||
@@ -51,5 +49,3 @@ public static get myField1() { | ||
```ts | ||
/* eslint @typescript-eslint/class-literal-property-style: ["error", "fields"] */ | ||
```ts option='"fields"' | ||
class Mx { | ||
@@ -81,5 +77,3 @@ public readonly myField1 = 1; | ||
```ts | ||
/* eslint @typescript-eslint/class-literal-property-style: ["error", "getters"] */ | ||
```ts option='"getters"' | ||
class Mx { | ||
@@ -94,5 +88,3 @@ readonly myField1 = 1; | ||
```ts | ||
/* eslint @typescript-eslint/class-literal-property-style: ["error", "getters"] */ | ||
```ts option='"getters"' | ||
class Mx { | ||
@@ -117,3 +109,2 @@ // no readonly modifier | ||
When you have no strong preference, or do not wish to enforce a particular style | ||
for how literal values are exposed by your classes. | ||
When you have no strong preference, or do not wish to enforce a particular style for how literal values are exposed by your classes. |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/comma-dangle`](https://eslint.org/docs/rules/comma-dangle) rule. | ||
@@ -17,3 +15,3 @@ It adds support for TypeScript syntax. | ||
## How to Use | ||
## Options | ||
@@ -20,0 +18,0 @@ In addition to the options supported by the `comma-dangle` rule in ESLint core, the rule adds the following options: |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/comma-spacing`](https://eslint.org/docs/rules/comma-spacing) rule. | ||
It adds support for trailing comma in a types parameters list. |
@@ -36,3 +36,3 @@ --- | ||
```ts | ||
```ts option='"constructor"' | ||
const map: Map<string, number> = new Map(); | ||
@@ -44,3 +44,3 @@ const set: Set<string> = new Set(); | ||
```ts | ||
```ts option='"constructor"' | ||
const map = new Map<string, number>(); | ||
@@ -59,3 +59,3 @@ const map: Map<string, number> = new MyMap(); | ||
```ts | ||
```ts option='"type-annotation"' | ||
const map = new Map<string, number>(); | ||
@@ -67,3 +67,3 @@ const set = new Set<string>(); | ||
```ts | ||
```ts option='"type-annotation"' | ||
const map: Map<string, number> = new Map(); | ||
@@ -78,1 +78,4 @@ const set: Set<string> = new Set(); | ||
You can turn this rule off if you don't want to enforce one kind of generic constructor style over the other. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -36,5 +36,3 @@ --- | ||
```ts | ||
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */ | ||
```ts option='"record"' | ||
interface Foo { | ||
@@ -51,5 +49,3 @@ [key: string]: unknown; | ||
```ts | ||
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "record"] */ | ||
```ts option='"record"' | ||
type Foo = Record<string, unknown>; | ||
@@ -64,5 +60,3 @@ ``` | ||
```ts | ||
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "index-signature"] */ | ||
```ts option='"index-signature"' | ||
type Foo = Record<string, unknown>; | ||
@@ -73,5 +67,3 @@ ``` | ||
```ts | ||
/* eslint @typescript-eslint/consistent-indexed-object-style: ["error", "index-signature"] */ | ||
```ts option='"index-signature"' | ||
interface Foo { | ||
@@ -85,1 +77,9 @@ [key: string]: unknown; | ||
``` | ||
## When Not To Use It | ||
This rule is purely a stylistic rule for maintaining consistency in your project. | ||
You can turn it off if you don't want to keep a consistent style for indexed object types. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -56,3 +56,3 @@ --- | ||
```ts | ||
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "never" }' | ||
const x = { ... } as T; | ||
@@ -67,3 +67,3 @@ | ||
```ts | ||
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "never" }' | ||
const x: T = { ... }; | ||
@@ -86,3 +86,3 @@ const y = { ... } as any; | ||
```ts | ||
```ts option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" }' | ||
const x = { ... } as T; | ||
@@ -97,3 +97,3 @@ | ||
```tsx | ||
```tsx option='{ "assertionStyle": "as", "objectLiteralTypeAssertions": "allow-as-parameter" }' | ||
const x: T = { ... }; | ||
@@ -113,1 +113,4 @@ const y = { ... } as any; | ||
If you do not want to enforce consistent type assertions. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -39,5 +39,3 @@ --- | ||
```ts | ||
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "interface"] */ | ||
```ts option='"interface"' | ||
type T = { x: number }; | ||
@@ -48,5 +46,3 @@ ``` | ||
```ts | ||
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "interface"] */ | ||
```ts option='"interface"' | ||
type T = string; | ||
@@ -66,5 +62,3 @@ type Foo = string | {}; | ||
```ts | ||
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "type"] */ | ||
```ts option='"type"' | ||
interface T { | ||
@@ -77,5 +71,3 @@ x: number; | ||
```ts | ||
/* eslint @typescript-eslint/consistent-type-definitions: ["error", "type"] */ | ||
```ts option='"type"' | ||
type T = { x: number }; | ||
@@ -86,2 +78,9 @@ ``` | ||
If you specifically want to use an interface or type literal for stylistic reasons, you can disable this rule. | ||
If you specifically want to use an interface or type literal for stylistic reasons, you can avoid this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. | ||
There are also subtle differences between `Record` and `interface` that can be difficult to catch statically. | ||
For example, if your project is a dependency of another project that relies on a specific type definition style, this rule may be counterproductive. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -86,3 +86,3 @@ --- | ||
```ts | ||
```ts option='{ "fixMixedExportsWithInlineTypeSpecifier": true }' | ||
export { Button } from 'some-library'; | ||
@@ -94,3 +94,3 @@ export type { ButtonProps } from 'some-library'; | ||
```ts | ||
```ts option='{ "fixMixedExportsWithInlineTypeSpecifier": true }' | ||
export { Button, type ButtonProps } from 'some-library'; | ||
@@ -101,3 +101,8 @@ ``` | ||
- If you specifically want to use both export kinds for stylistic reasons, you can disable this rule. | ||
- If you use `--isolatedModules` the compiler would error if a type is not re-exported using `export type`. If you also don't wish to enforce one style over the other, you can disable this rule. | ||
If you use `--isolatedModules` the compiler would error if a type is not re-exported using `export type`. | ||
This rule may be less useful in those cases. | ||
If you specifically want to use both export kinds for stylistic reasons, or don't wish to enforce one style over the other, you can avoid this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -25,3 +25,3 @@ --- | ||
```ts | ||
```ts option='{ "prefer": "type-imports" }' showPlaygroundButton | ||
import type { Foo } from 'Foo'; | ||
@@ -35,3 +35,3 @@ import type Bar from 'Bar'; | ||
```ts | ||
```ts option='{ "prefer": "type-imports" }' showPlaygroundButton | ||
import { Foo } from 'Foo'; | ||
@@ -63,3 +63,3 @@ import Bar from 'Bar'; | ||
```ts | ||
```ts option='{ "fixStyle": "separate-type-imports" }' | ||
import type { Foo } from 'Foo'; | ||
@@ -73,3 +73,3 @@ import type Bar from 'Bar'; | ||
```ts | ||
```ts option='{ "fixStyle": "inline-type-imports" }' | ||
import { type Foo } from 'Foo'; | ||
@@ -90,3 +90,3 @@ import type Bar from 'Bar'; | ||
```ts | ||
```ts option='{ "disallowTypeAnnotations": true }' showPlaygroundButton | ||
type T = import('Foo').Foo; | ||
@@ -104,4 +104,7 @@ const x: import('Bar') = 1; | ||
- If you specifically want to use both import kinds for stylistic reasons, you can disable this rule. | ||
If you specifically want to use both import kinds for stylistic reasons, or don't wish to enforce one style over the other, you can avoid this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. | ||
## Related To | ||
@@ -108,0 +111,0 @@ |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/default-param-last`](https://eslint.org/docs/rules/default-param-last) rule. | ||
@@ -26,6 +24,12 @@ It adds support for optional parameters. | ||
class Foo { | ||
constructor(public a = 10, private b: number) {} | ||
constructor( | ||
public a = 10, | ||
private b: number, | ||
) {} | ||
} | ||
class Foo { | ||
constructor(public a?: number, private b: number) {} | ||
constructor( | ||
public a?: number, | ||
private b: number, | ||
) {} | ||
} | ||
@@ -45,7 +49,13 @@ ``` | ||
class Foo { | ||
constructor(public a, private b = 0) {} | ||
constructor( | ||
public a, | ||
private b = 0, | ||
) {} | ||
} | ||
class Foo { | ||
constructor(public a, private b?: number) {} | ||
constructor( | ||
public a, | ||
private b?: number, | ||
) {} | ||
} | ||
``` |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/dot-notation`](https://eslint.org/docs/rules/dot-notation) rule. | ||
@@ -43,3 +41,3 @@ It adds: | ||
```ts | ||
```ts option='{ "allowPrivateClassPropertyAccess": true }' showPlaygroundButton | ||
class X { | ||
@@ -57,3 +55,3 @@ private priv_prop = 123; | ||
```ts | ||
```ts option='{ "allowProtectedClassPropertyAccess": true }' showPlaygroundButton | ||
class X { | ||
@@ -71,3 +69,3 @@ protected protected_prop = 123; | ||
```ts | ||
```ts option='{ "allowIndexSignaturePropertyAccess": true }' showPlaygroundButton | ||
class X { | ||
@@ -82,1 +80,8 @@ [key: string]: number; | ||
If the TypeScript compiler option `noPropertyAccessFromIndexSignature` is set to `true`, then the above code is always allowed, even if `allowIndexSignaturePropertyAccess` is `false`. | ||
## When Not To Use It | ||
If you specifically want to use both member access kinds for stylistic reasons, or don't wish to enforce one style over the other, you can avoid this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -101,3 +101,3 @@ --- | ||
```ts | ||
```ts option='{ "allowExpressions": true }' | ||
function test() {} | ||
@@ -112,3 +112,3 @@ | ||
```ts | ||
```ts option='{ "allowExpressions": true }' | ||
node.addEventListener('click', () => {}); | ||
@@ -129,3 +129,3 @@ | ||
```ts | ||
```ts option='{ "allowTypedFunctionExpressions": true }' | ||
let arrowFn = () => 'test'; | ||
@@ -144,3 +144,3 @@ | ||
```ts | ||
```ts option='{ "allowTypedFunctionExpressions": true }' | ||
type FuncType = () => string; | ||
@@ -179,2 +179,6 @@ | ||
}); | ||
const Comp: FC = () => { | ||
return <button onClick={() => {}} />; | ||
}; | ||
``` | ||
@@ -190,3 +194,3 @@ | ||
```ts | ||
```ts option='{ "allowHigherOrderFunctions": true }' | ||
var arrowFn = () => () => {}; | ||
@@ -201,3 +205,3 @@ | ||
```ts | ||
```ts option='{ "allowHigherOrderFunctions": true }' | ||
var arrowFn = () => (): void => {}; | ||
@@ -218,5 +222,5 @@ | ||
```ts | ||
const func = (value: number) => ({ type: 'X', value } as any); | ||
const func = (value: number) => ({ type: 'X', value } as Action); | ||
```ts option='{ "allowDirectConstAssertionInArrowFunctions": true }' | ||
const func = (value: number) => ({ type: 'X', value }) as any; | ||
const func = (value: number) => ({ type: 'X', value }) as Action; | ||
``` | ||
@@ -226,4 +230,4 @@ | ||
```ts | ||
const func = (value: number) => ({ foo: 'bar', value } as const); | ||
```ts option='{ "allowDirectConstAssertionInArrowFunctions": true }' | ||
const func = (value: number) => ({ foo: 'bar', value }) as const; | ||
const func = () => x as const; | ||
@@ -240,3 +244,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowConciseArrowFunctionExpressionsStartingWithVoid": true }' | ||
var join = (a: string, b: string) => `${a}${b}`; | ||
@@ -251,3 +255,3 @@ | ||
```ts | ||
```ts option='{ "allowConciseArrowFunctionExpressionsStartingWithVoid": true }' | ||
var log = (message: string) => void console.log(message); | ||
@@ -264,3 +268,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowFunctionsWithoutTypeParameters": true }' | ||
function foo<T>(t: T) { | ||
@@ -275,3 +279,3 @@ return t; | ||
```ts | ||
```ts option='{ "allowFunctionsWithoutTypeParameters": true }' | ||
function foo<T>(t: T): T { | ||
@@ -305,9 +309,11 @@ return t; | ||
### `allowIIFE` | ||
### `allowIIFEs` | ||
Examples of code for this rule with `{ allowIIFE: true }`: | ||
Examples of code for this rule with `{ allowIIFEs: true }`: | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts | ||
```ts option='{ "allowIIFEs": true }' | ||
var func = () => 'foo'; | ||
@@ -318,3 +324,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowIIFEs": true }' | ||
var foo = (() => 'foo')(); | ||
@@ -329,4 +335,3 @@ | ||
If you don't wish to prevent calling code from using function return values in unexpected ways, then | ||
you will not need this rule. | ||
If you don't find the added cost of explicitly writing function return types to be worth the visual clarity, or your project is not large enough for it to be a factor in type checking performance, then you will not need this rule. | ||
@@ -333,0 +338,0 @@ ## Further Reading |
@@ -10,3 +10,3 @@ --- | ||
TypeScript allows placing explicit `public`, `protected`, and `private` accessibility modifiers in front of class members. | ||
The modifiers exist solely in the type system and just server to describe who is allowed to access those members. | ||
The modifiers exist solely in the type system and just serve to describe who is allowed to access those members. | ||
@@ -69,3 +69,3 @@ Leaving off accessibility modifiers makes for less code to read and write. | ||
```ts | ||
```ts showPlaygroundButton | ||
class Animal { | ||
@@ -93,5 +93,8 @@ constructor(name) { | ||
```ts | ||
```ts option='{ "accessibility": "explicit" }' showPlaygroundButton | ||
class Animal { | ||
public constructor(public breed, name) { | ||
public constructor( | ||
public breed, | ||
name, | ||
) { | ||
// Parameter property and constructor | ||
@@ -117,5 +120,8 @@ this.animalName = name; | ||
```ts | ||
```ts option='{ "accessibility": "no-public" }' showPlaygroundButton | ||
class Animal { | ||
public constructor(public breed, name) { | ||
public constructor( | ||
public breed, | ||
name, | ||
) { | ||
// Parameter property and constructor | ||
@@ -141,5 +147,8 @@ this.animalName = name; | ||
```ts | ||
```ts option='{ "accessibility": "no-public" }' showPlaygroundButton | ||
class Animal { | ||
constructor(protected breed, name) { | ||
constructor( | ||
protected breed, | ||
name, | ||
) { | ||
// Parameter property and constructor | ||
@@ -177,3 +186,3 @@ this.name = name; | ||
```ts | ||
```ts option='{ "overrides": { "constructors": "no-public" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -189,3 +198,3 @@ public constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "overrides": { "constructors": "no-public" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -205,3 +214,3 @@ constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "accessibility": "no-public", "overrides": { "properties": "explicit" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -222,3 +231,3 @@ constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "accessibility": "no-public", "overrides": { "properties": "explicit" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -241,3 +250,3 @@ constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "accessibility": "off", "overrides": { "parameterProperties": "explicit" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -250,3 +259,3 @@ constructor(readonly animalName: string) {} | ||
```ts | ||
```ts option='{ "accessibility": "off", "overrides": { "parameterProperties": "explicit" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -269,3 +278,3 @@ constructor(public readonly animalName: string) {} | ||
```ts | ||
```ts option='{ "accessibility": "off", "overrides": { "parameterProperties": "no-public" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -278,3 +287,3 @@ constructor(public readonly animalName: string) {} | ||
```ts | ||
```ts option='{ "accessibility": "off", "overrides": { "parameterProperties": "no-public" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -293,3 +302,3 @@ constructor(public animalName: string) {} | ||
```ts | ||
```ts option='{ "overrides": { "accessors" : "off" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -308,3 +317,3 @@ constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "overrides": { "accessors" : "off" } }' showPlaygroundButton | ||
class Animal { | ||
@@ -326,3 +335,3 @@ public constructor(protected animalName) {} | ||
```ts | ||
```ts option='{ "ignoredMethodNames": ["specificMethod", "whateverMethod"] }' showPlaygroundButton | ||
class Animal { | ||
@@ -343,6 +352,10 @@ get specificMethod() { | ||
If you think defaulting to public is a good default, then you should consider using the `no-public` setting. If you want to mix implicit and explicit public members then disable this rule. | ||
If you think defaulting to public is a good default, then you should consider using the `no-public` setting. | ||
If you want to mix implicit and explicit public members then you can disable this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. | ||
## Further Reading | ||
- TypeScript [Accessibility Modifiers Handbook Docs](https://www.typescriptlang.org/docs/handbook/2/classes.html#member-visibility) |
@@ -59,3 +59,3 @@ --- | ||
// A return value of type string | ||
export var arrowFn = (arg: string): string => `test ${arg}`; | ||
export var arrowFn = (): string => 'test'; | ||
@@ -106,3 +106,3 @@ // All arguments should be typed | ||
```ts | ||
```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' | ||
export const func = (value: any): number => value + 1; | ||
@@ -113,3 +113,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' | ||
export const func = (value: number): number => value + 1; | ||
@@ -126,3 +126,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' | ||
export const func = (value: number) => ({ type: 'X', value }); | ||
@@ -137,8 +137,8 @@ export const foo = () => ({ | ||
```ts | ||
export const func = (value: number) => ({ type: 'X', value } as const); | ||
```ts option='{ "allowArgumentsExplicitlyTypedAsAny": false }' | ||
export const func = (value: number) => ({ type: 'X', value }) as const; | ||
export const foo = () => | ||
({ | ||
bar: true, | ||
} as const); | ||
}) as const; | ||
export const bar = () => 1 as const; | ||
@@ -170,3 +170,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowHigherOrderFunctions": false }' | ||
export const arrowFn = () => () => {}; | ||
@@ -185,3 +185,3 @@ | ||
```ts | ||
```ts option='{ "allowHigherOrderFunctions": false }' | ||
export const arrowFn = () => (): void => {}; | ||
@@ -206,3 +206,3 @@ | ||
```ts | ||
```ts option='{ "allowTypedFunctionExpressions": false }' | ||
export let arrowFn = () => 'test'; | ||
@@ -223,3 +223,3 @@ | ||
```ts | ||
```ts option='{ "allowTypedFunctionExpressions": false }' | ||
type FuncType = () => string; | ||
@@ -255,3 +255,3 @@ | ||
If you wish to make sure all functions have explicit return types, as opposed to only the module boundaries, you can use [explicit-function-return-type](./explicit-function-return-type.md) | ||
If your project is not used by downstream consumers that are sensitive to API types, you can disable this rule. | ||
@@ -261,1 +261,5 @@ ## Further Reading | ||
- TypeScript [Functions](https://www.typescriptlang.org/docs/handbook/functions.html#function-types) | ||
## Related To | ||
- [explicit-function-return-type](./explicit-function-return-type.md) |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/func-call-spacing`](https://eslint.org/docs/rules/func-call-spacing) rule. | ||
It adds support for generic type parameters on function calls. |
@@ -17,5 +17,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/indent`](https://eslint.org/docs/rules/indent) rule. | ||
It adds support for TypeScript nodes. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/init-declarations`](https://eslint.org/docs/rules/init-declarations) rule. | ||
It adds support for TypeScript's `declare` variables. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/key-spacing`](https://eslint.org/docs/rules/key-spacing) rule. | ||
This version adds support for type annotations on interfaces, classes and type literals properties. | ||
It adds support for type annotations on interfaces, classes and type literals properties. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/keyword-spacing`](https://eslint.org/docs/rules/keyword-spacing) rule. | ||
This version adds support for generic type parameters on function calls. | ||
It adds support for generic type parameters on function calls. |
@@ -9,19 +9,7 @@ --- | ||
## Rule Details | ||
This rule extends the base [`eslint/lines-around-comment`](https://eslint.org/docs/rules/lines-around-comment) rule. | ||
It adds support for TypeScript syntax. | ||
See the [ESLint documentation](https://eslint.org/docs/rules/lines-around-comment) for more details on the `comma-dangle` rule. | ||
See the [ESLint documentation](https://eslint.org/docs/rules/lines-around-comment) for more details on the `lines-around-comment` rule. | ||
## Rule Changes | ||
```jsonc | ||
{ | ||
// note you must disable the base rule as it can report incorrect errors | ||
"lines-around-comment": "off", | ||
"@typescript-eslint/lines-around-comment": ["error"] | ||
} | ||
``` | ||
## Options | ||
@@ -28,0 +16,0 @@ |
@@ -9,6 +9,2 @@ --- | ||
This rule improves readability by enforcing lines between class members. It will not check empty lines before the first member and after the last member. This rule will require or disallow an empty line between class members. | ||
## Examples | ||
This rule extends the base [`eslint/lines-between-class-members`](https://eslint.org/docs/rules/lines-between-class-members) rule. | ||
@@ -32,5 +28,3 @@ It adds support for ignoring overload methods in a class. | ||
```ts | ||
/*eslint @typescript-eslint/lines-between-class-members: ["error", "always", { "exceptAfterOverload": true }]*/ | ||
```ts option='"always", { "exceptAfterOverload": true }' showPlaygroundButton | ||
class foo { | ||
@@ -51,5 +45,3 @@ bar(a: string): void; | ||
```ts | ||
/*eslint @typescript-eslint/lines-between-class-members: ["error", "always", { "exceptAfterOverload": false }]*/ | ||
```ts option='"always", { "exceptAfterOverload": false }' showPlaygroundButton | ||
class foo { | ||
@@ -56,0 +48,0 @@ bar(a: string): void; |
@@ -161,2 +161,5 @@ --- | ||
If you don't care about enforcing a consistent member delimiter in interfaces and type literals, then you will not need this rule. | ||
If you specifically want to use both member delimiter kinds for stylistic reasons, or don't wish to enforce one style over the other, you can avoid this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -129,2 +129,33 @@ --- | ||
// Accessors | ||
"public-static-accessor", | ||
"protected-static-accessor", | ||
"private-static-accessor", | ||
"#private-static-accessor", | ||
"public-decorated-accessor", | ||
"protected-decorated-accessor", | ||
"private-decorated-accessor", | ||
"public-instance-accessor", | ||
"protected-instance-accessor", | ||
"private-instance-accessor", | ||
"#private-instance-accessor", | ||
"public-abstract-accessor", | ||
"protected-abstract-accessor", | ||
"public-accessor", | ||
"protected-accessor", | ||
"private-accessor", | ||
"#private-accessor", | ||
"static-accessor", | ||
"instance-accessor", | ||
"abstract-accessor", | ||
"decorated-accessor", | ||
"accessor", | ||
// Getters | ||
@@ -260,3 +291,3 @@ "public-static-get", | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
interface Foo { | ||
@@ -273,3 +304,3 @@ B: string; // -> field | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
type Foo = { | ||
@@ -286,3 +317,3 @@ B: string; // -> field | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
class Foo { | ||
@@ -302,3 +333,3 @@ private C: string; // -> field | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
const Foo = class { | ||
@@ -321,3 +352,3 @@ private C: string; // -> field | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
interface Foo { | ||
@@ -334,3 +365,3 @@ [Z: string]: any; // -> signature | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
type Foo = { | ||
@@ -347,3 +378,3 @@ // no signature | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
class Foo { | ||
@@ -363,3 +394,3 @@ [Z: string]: any; // -> signature | ||
```ts | ||
```ts option='{ "default": ["signature", "method", "constructor", "field"] }' | ||
const Foo = class { | ||
@@ -403,3 +434,3 @@ [Z: string]: any; // -> signature | ||
```ts | ||
```ts option='{ "default": ["public-instance-method", "public-static-field"] }' | ||
class Foo { | ||
@@ -422,3 +453,3 @@ private C: string; // (irrelevant) | ||
```ts | ||
```ts option='{ "default": ["public-instance-method", "public-static-field"] }' | ||
const Foo = class { | ||
@@ -443,3 +474,3 @@ private C: string; // (irrelevant) | ||
```ts | ||
```ts option='{ "default": ["public-instance-method", "public-static-field"] }' | ||
class Foo { | ||
@@ -462,3 +493,3 @@ public B(): void {} // -> public instance method | ||
```ts | ||
```ts option='{ "default": ["public-instance-method", "public-static-field"] }' | ||
const Foo = class { | ||
@@ -501,3 +532,3 @@ public B(): void {} // -> public instance method | ||
```ts | ||
```ts option='{ "default": ["public-static-field", "static-field", "instance-field"] }' | ||
class Foo { | ||
@@ -516,3 +547,3 @@ private E: string; // -> instance field | ||
```ts | ||
```ts option='{ "default": ["public-static-field", "static-field", "instance-field"] }' | ||
const foo = class { | ||
@@ -538,3 +569,3 @@ public T(): void {} // method (irrelevant) | ||
```ts | ||
```ts option='{ "default": ["public-static-field", "static-field", "instance-field"] }' | ||
class Foo { | ||
@@ -553,3 +584,3 @@ public static A: string; // -> public static field | ||
```ts | ||
```ts option='{ "default": ["public-static-field", "static-field", "instance-field"] }' | ||
const foo = class { | ||
@@ -594,3 +625,3 @@ [Z: string]: any; // -> signature (irrelevant) | ||
```ts | ||
```ts option='{ "classes": ["method", "constructor", "field"] }' | ||
class Foo { | ||
@@ -610,3 +641,3 @@ private C: string; // -> field | ||
```ts | ||
```ts option='{ "classes": ["method", "constructor", "field"] }' | ||
class Foo { | ||
@@ -646,3 +677,3 @@ public static A(): void {} // -> method | ||
```ts | ||
```ts option='{ "classExpressions": ["method", "constructor", "field"] }' | ||
const foo = class { | ||
@@ -662,3 +693,3 @@ private C: string; // -> field | ||
```ts | ||
```ts option='{ "classExpressions": ["method", "constructor", "field"] }' | ||
const foo = class { | ||
@@ -702,3 +733,3 @@ public static A(): void {} // -> method | ||
```ts | ||
```ts option='{ "interfaces": ["signature", "method", "constructor", "field"] }' | ||
interface Foo { | ||
@@ -717,3 +748,3 @@ B: string; // -> field | ||
```ts | ||
```ts option='{ "interfaces": ["signature", "method", "constructor", "field"] }' | ||
interface Foo { | ||
@@ -756,3 +787,3 @@ [Z: string]: any; // -> signature | ||
```ts | ||
```ts option='{ "typeLiterals": ["signature", "method", "constructor", "field"] }' | ||
type Foo = { | ||
@@ -771,3 +802,3 @@ B: string; // -> field | ||
```ts | ||
```ts option='{ "typeLiterals": ["signature", "method", "constructor", "field"] }' | ||
type Foo = { | ||
@@ -814,3 +845,3 @@ [Z: string]: any; // -> signature | ||
```ts | ||
```ts option='{"default":{"memberTypes":["signature","call-signature","public-static-field","protected-static-field","private-static-field","#private-static-field","public-decorated-field","protected-decorated-field","private-decorated-field","public-instance-field","protected-instance-field","private-instance-field","#private-instance-field","public-abstract-field","protected-abstract-field","public-field","protected-field","private-field","#private-field","static-field","instance-field","abstract-field","decorated-field","field","static-initialization","public-constructor","protected-constructor","private-constructor","constructor","public-static-get","protected-static-get","private-static-get","#private-static-get","public-decorated-get","protected-decorated-get","private-decorated-get","public-instance-get","protected-instance-get","private-instance-get","#private-instance-get","public-abstract-get","protected-abstract-get","public-get","protected-get","private-get","#private-get","static-get","instance-get","abstract-get","decorated-get","get","public-static-set","protected-static-set","private-static-set","#private-static-set","public-decorated-set","protected-decorated-set","private-decorated-set","public-instance-set","protected-instance-set","private-instance-set","#private-instance-set","public-abstract-set","protected-abstract-set","public-set","protected-set","private-set","#private-set","static-set","instance-set","abstract-set","decorated-set","set","public-static-method","protected-static-method","private-static-method","#private-static-method","public-decorated-method","protected-decorated-method","private-decorated-method","public-instance-method","protected-instance-method","private-instance-method","#private-instance-method","public-abstract-method","protected-abstract-method","public-method","protected-method","private-method","#private-method","static-method","instance-method","abstract-method","decorated-method","method"],"order":"alphabetically"}}' | ||
interface Foo { | ||
@@ -829,3 +860,3 @@ a: x; | ||
```ts | ||
```ts option='{"default":{"memberTypes":["signature","call-signature","public-static-field","protected-static-field","private-static-field","#private-static-field","public-decorated-field","protected-decorated-field","private-decorated-field","public-instance-field","protected-instance-field","private-instance-field","#private-instance-field","public-abstract-field","protected-abstract-field","public-field","protected-field","private-field","#private-field","static-field","instance-field","abstract-field","decorated-field","field","static-initialization","public-constructor","protected-constructor","private-constructor","constructor","public-static-get","protected-static-get","private-static-get","#private-static-get","public-decorated-get","protected-decorated-get","private-decorated-get","public-instance-get","protected-instance-get","private-instance-get","#private-instance-get","public-abstract-get","protected-abstract-get","public-get","protected-get","private-get","#private-get","static-get","instance-get","abstract-get","decorated-get","get","public-static-set","protected-static-set","private-static-set","#private-static-set","public-decorated-set","protected-decorated-set","private-decorated-set","public-instance-set","protected-instance-set","private-instance-set","#private-instance-set","public-abstract-set","protected-abstract-set","public-set","protected-set","private-set","#private-set","static-set","instance-set","abstract-set","decorated-set","set","public-static-method","protected-static-method","private-static-method","#private-static-method","public-decorated-method","protected-decorated-method","private-decorated-method","public-instance-method","protected-instance-method","private-instance-method","#private-instance-method","public-abstract-method","protected-abstract-method","public-method","protected-method","private-method","#private-method","static-method","instance-method","abstract-method","decorated-method","method"],"order":"alphabetically"}}' | ||
interface Foo { | ||
@@ -844,3 +875,3 @@ B: x; | ||
This config specifies that within each `memberTypes` group, members are in an alphabetic case-sensitive order. | ||
This config specifies that within each `memberTypes` group, members are in an alphabetic case-insensitive order. | ||
You can copy and paste the default order from [Default Configuration](#default-configuration). | ||
@@ -871,3 +902,3 @@ | ||
```ts | ||
```ts option='{"default":{"memberTypes":["signature","call-signature","public-static-field","protected-static-field","private-static-field","#private-static-field","public-decorated-field","protected-decorated-field","private-decorated-field","public-instance-field","protected-instance-field","private-instance-field","#private-instance-field","public-abstract-field","protected-abstract-field","public-field","protected-field","private-field","#private-field","static-field","instance-field","abstract-field","decorated-field","field","static-initialization","public-constructor","protected-constructor","private-constructor","constructor","public-static-get","protected-static-get","private-static-get","#private-static-get","public-decorated-get","protected-decorated-get","private-decorated-get","public-instance-get","protected-instance-get","private-instance-get","#private-instance-get","public-abstract-get","protected-abstract-get","public-get","protected-get","private-get","#private-get","static-get","instance-get","abstract-get","decorated-get","get","public-static-set","protected-static-set","private-static-set","#private-static-set","public-decorated-set","protected-decorated-set","private-decorated-set","public-instance-set","protected-instance-set","private-instance-set","#private-instance-set","public-abstract-set","protected-abstract-set","public-set","protected-set","private-set","#private-set","static-set","instance-set","abstract-set","decorated-set","set","public-static-method","protected-static-method","private-static-method","#private-static-method","public-decorated-method","protected-decorated-method","private-decorated-method","public-instance-method","protected-instance-method","private-instance-method","#private-instance-method","public-abstract-method","protected-abstract-method","public-method","protected-method","private-method","#private-method","static-method","instance-method","abstract-method","decorated-method","method"],"order":"alphabetically-case-insensitive"}}' | ||
interface Foo { | ||
@@ -886,3 +917,3 @@ B: x; | ||
```ts | ||
```ts option='{"default":{"memberTypes":["signature","call-signature","public-static-field","protected-static-field","private-static-field","#private-static-field","public-decorated-field","protected-decorated-field","private-decorated-field","public-instance-field","protected-instance-field","private-instance-field","#private-instance-field","public-abstract-field","protected-abstract-field","public-field","protected-field","private-field","#private-field","static-field","instance-field","abstract-field","decorated-field","field","static-initialization","public-constructor","protected-constructor","private-constructor","constructor","public-static-get","protected-static-get","private-static-get","#private-static-get","public-decorated-get","protected-decorated-get","private-decorated-get","public-instance-get","protected-instance-get","private-instance-get","#private-instance-get","public-abstract-get","protected-abstract-get","public-get","protected-get","private-get","#private-get","static-get","instance-get","abstract-get","decorated-get","get","public-static-set","protected-static-set","private-static-set","#private-static-set","public-decorated-set","protected-decorated-set","private-decorated-set","public-instance-set","protected-instance-set","private-instance-set","#private-instance-set","public-abstract-set","protected-abstract-set","public-set","protected-set","private-set","#private-set","static-set","instance-set","abstract-set","decorated-set","set","public-static-method","protected-static-method","private-static-method","#private-static-method","public-decorated-method","protected-decorated-method","private-decorated-method","public-instance-method","protected-instance-method","private-instance-method","#private-instance-method","public-abstract-method","protected-abstract-method","public-method","protected-method","private-method","#private-method","static-method","instance-method","abstract-method","decorated-method","method"],"order":"alphabetically-case-insensitive"}}' | ||
interface Foo { | ||
@@ -920,3 +951,3 @@ a: x; | ||
```ts | ||
```ts option='{ "default": { "memberTypes": "never", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -935,3 +966,3 @@ static c = 0; | ||
```ts | ||
```ts option='{ "default": { "memberTypes": "never", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -975,3 +1006,3 @@ a: boolean; | ||
```ts | ||
```ts option='{ "default": { "optionalityOrder": "optional-first", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -986,3 +1017,3 @@ a: boolean; | ||
```ts | ||
```ts option='{ "default": { "optionalityOrder": "optional-first", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -1020,3 +1051,3 @@ b?: number; | ||
```ts | ||
```ts option='{ "default": { "optionalityOrder": "required-first", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -1031,3 +1062,3 @@ a: boolean; | ||
```ts | ||
```ts option='{ "default": { "optionalityOrder": "required-first", "order": "alphabetically" } }' | ||
interface Foo { | ||
@@ -1034,0 +1065,0 @@ a: boolean; |
@@ -49,3 +49,3 @@ --- | ||
```ts | ||
```ts option='"property"' | ||
interface T1 { | ||
@@ -66,3 +66,3 @@ func(arg: string): number; | ||
```ts | ||
```ts option='"property"' | ||
interface T1 { | ||
@@ -90,3 +90,3 @@ func: (arg: string) => number; | ||
```ts | ||
```ts option='"method"' | ||
interface T1 { | ||
@@ -102,3 +102,3 @@ func: (arg: string) => number; | ||
```ts | ||
```ts option='"method"' | ||
interface T1 { | ||
@@ -115,1 +115,4 @@ func(arg: string): number; | ||
If you don't want to enforce a particular style for object/interface function types, and/or if you don't use `strictFunctionTypes`, then you don't need this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -84,2 +84,7 @@ --- | ||
{ | ||
selector: 'import', | ||
format: ['camelCase', 'PascalCase'], | ||
}, | ||
{ | ||
selector: 'variable', | ||
@@ -108,6 +113,6 @@ format: ['camelCase', 'UPPER_CASE'], | ||
- `camelCase` - standard camelCase format - no underscores are allowed between characters, and consecutive capitals are allowed (i.e. both `myID` and `myId` are valid). | ||
- `PascalCase` - same as `camelCase`, except the first character must be upper-case. | ||
- `snake_case` - standard snake_case format - all characters must be lower-case, and underscores are allowed. | ||
- `strictCamelCase` - same as `camelCase`, but consecutive capitals are not allowed (i.e. `myId` is valid, but `myID` is not). | ||
- `PascalCase` - same as `camelCase`, except the first character must be upper-case. | ||
- `StrictPascalCase` - same as `strictCamelCase`, except the first character must be upper-case. | ||
- `snake_case` - standard snake_case format - all characters must be lower-case, and underscores are allowed. | ||
- `UPPER_CASE` - same as `snake_case`, except all characters must be upper-case. | ||
@@ -123,4 +128,4 @@ | ||
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`. | ||
- `regex` - a string that is then passed into RegExp to create a new regular expression: `new RegExp(regex)` | ||
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`. | ||
@@ -135,4 +140,4 @@ #### `filter` | ||
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`. | ||
- `regex` - a string that is then passed into RegExp to create a new regular expression: `new RegExp(regex)` | ||
- `match` - true if the identifier _must_ match the `regex`, false if the identifier _must not_ match the `regex`. | ||
@@ -145,8 +150,8 @@ Alternatively, `filter` accepts a regular expression (anything accepted into `new RegExp(filter)`). In this case, it's treated as if you had passed an object with the regex and `match: true`. | ||
- `allow` - existence of a single leading/trailing underscore is not explicitly enforced. | ||
- `allowDouble` - existence of a double leading/trailing underscore is not explicitly enforced. | ||
- `allowSingleOrDouble` - existence of a single or a double leading/trailing underscore is not explicitly enforced. | ||
- `forbid` - a leading/trailing underscore is not allowed at all. | ||
- `require` - a single leading/trailing underscore must be included. | ||
- `requireDouble` - two leading/trailing underscores must be included. | ||
- `allow` - existence of a single leading/trailing underscore is not explicitly enforced. | ||
- `allowDouble` - existence of a double leading/trailing underscore is not explicitly enforced. | ||
- `allowSingleOrDouble` - existence of a single or a double leading/trailing underscore is not explicitly enforced. | ||
@@ -171,13 +176,13 @@ #### `prefix` / `suffix` | ||
- The following `modifiers` are allowed: | ||
- `abstract`,`override`,`private`,`protected`,`readonly`,`static` - matches any member explicitly declared with the given modifier. | ||
- `async` - matches any method, function, or function variable which is async via the `async` keyword (e.g. does not match functions that return promises without using `async` keyword) | ||
- `const` - matches a variable declared as being `const` (`const x = 1`). | ||
- `destructured` - matches a variable declared via an object destructuring pattern (`const {x, z = 2}`). | ||
- Note that this does not match renamed destructured properties (`const {x: y, a: b = 2}`). | ||
- `exported` - matches anything that is exported from the module. | ||
- `global` - matches a variable/function declared in the top-level scope. | ||
- `exported` - matches anything that is exported from the module. | ||
- `#private` - matches any member with a private identifier (an identifier that starts with `#`) | ||
- `public` - matches any member that is either explicitly declared as `public`, or has no visibility modifier (i.e. implicitly public). | ||
- `requiresQuotes` - matches any name that requires quotes as it is not a valid identifier (i.e. has a space, a dash, etc in it). | ||
- `unused` - matches anything that is not used. | ||
- `requiresQuotes` - matches any name that requires quotes as it is not a valid identifier (i.e. has a space, a dash, etc in it). | ||
- `public` - matches any member that is either explicitly declared as `public`, or has no visibility modifier (i.e. implicitly public). | ||
- `abstract`,`override`,`private`,`protected`,`readonly`,`static` - matches any member explicitly declared with the given modifier. | ||
- `#private` - matches any member with a private identifier (an identifier that starts with `#`) | ||
- `async` - matches any method, function, or function variable which is async via the `async` keyword (e.g. does not match functions that return promises without using `async` keyword) | ||
- `types` allows you to specify which types to match. This option supports simple, primitive types only (`array`,`boolean`,`function`,`number`,`string`). | ||
@@ -188,7 +193,7 @@ - The name must match _one_ of the types. | ||
- The following `types` are allowed: | ||
- `array` matches any type assignable to `Array<unknown> | null | undefined` | ||
- `boolean` matches any type assignable to `boolean | null | undefined` | ||
- `function` matches any type assignable to `Function | null | undefined` | ||
- `number` matches any type assignable to `number | null | undefined` | ||
- `string` matches any type assignable to `string | null | undefined` | ||
- `number` matches any type assignable to `number | null | undefined` | ||
- `array` matches any type assignable to `Array<unknown> | null | undefined` | ||
- `function` matches any type assignable to `Function | null | undefined` | ||
@@ -205,49 +210,46 @@ The ordering of selectors does not matter. The implementation will automatically sort the selectors to ensure they match from most-specific to least specific. It will keep checking selectors in that order until it finds one that matches the name. See ["How does the rule automatically order selectors?"](#how-does-the-rule-automatically-order-selectors) | ||
- `variable` - matches any `let` / `const` / `var` variable name. | ||
- Allowed `modifiers`: `async`, `const`, `destructured`, `exported`, `global`, `unused`. | ||
- `accessor` - matches any accessor. | ||
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `function` - matches any named function declaration or named function expression. | ||
- Allowed `modifiers`: `async`, `exported`, `global`, `unused`. | ||
- `class` - matches any class declaration. | ||
- Allowed `modifiers`: `abstract`, `exported`, `unused`. | ||
- Allowed `types`: none. | ||
- `parameter` - matches any function parameter. Does not match parameter properties. | ||
- Allowed `modifiers`: `destructured`, `unused`. | ||
- Allowed `types`: `boolean`, `string`, `number`, `function`, `array`. | ||
- `classMethod` - matches any class method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `requiresQuotes`, `static`. | ||
- Allowed `types`: none. | ||
- `classProperty` - matches any class property. Does not match properties that have direct function expression or arrow function expression values. | ||
- Allowed `modifiers`: `abstract`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `objectLiteralProperty` - matches any object literal property. Does not match properties that have direct function expression or arrow function expression values. | ||
- Allowed `modifiers`: `public`, `requiresQuotes`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `typeProperty` - matches any object type property. Does not match properties that have direct function expression or arrow function expression values. | ||
- Allowed `modifiers`: `public`, `readonly`, `requiresQuotes`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `parameterProperty` - matches any parameter property. | ||
- Allowed `modifiers`: `private`, `protected`, `public`, `readonly`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `classMethod` - matches any class method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `requiresQuotes`, `static`. | ||
- `enum` - matches any enum declaration. | ||
- Allowed `modifiers`: `exported`, `unused`. | ||
- Allowed `types`: none. | ||
- `objectLiteralMethod` - matches any object literal method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `async`, `public`, `requiresQuotes`. | ||
- Allowed `types`: none. | ||
- `typeMethod` - matches any object type method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `public`, `requiresQuotes`. | ||
- Allowed `types`: none. | ||
- `accessor` - matches any accessor. | ||
- Allowed `modifiers`: `abstract`, `override`, `private`, `protected`, `public`, `requiresQuotes`, `static`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `enumMember` - matches any enum member. | ||
- Allowed `modifiers`: `requiresQuotes`. | ||
- Allowed `types`: none. | ||
- `class` - matches any class declaration. | ||
- Allowed `modifiers`: `abstract`, `exported`, `unused`. | ||
- `function` - matches any named function declaration or named function expression. | ||
- Allowed `modifiers`: `async`, `exported`, `global`, `unused`. | ||
- Allowed `types`: none. | ||
- `import` - matches namespace imports and default imports (i.e. does not match named imports). | ||
- Allowed `modifiers`: `default`, `namespace`. | ||
- Allowed `types`: none. | ||
- `interface` - matches any interface declaration. | ||
- Allowed `modifiers`: `exported`, `unused`. | ||
- Allowed `types`: none. | ||
- `objectLiteralMethod` - matches any object literal method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `async`, `public`, `requiresQuotes`. | ||
- Allowed `types`: none. | ||
- `objectLiteralProperty` - matches any object literal property. Does not match properties that have direct function expression or arrow function expression values. | ||
- Allowed `modifiers`: `public`, `requiresQuotes`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `parameter` - matches any function parameter. Does not match parameter properties. | ||
- Allowed `modifiers`: `destructured`, `unused`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `parameterProperty` - matches any parameter property. | ||
- Allowed `modifiers`: `private`, `protected`, `public`, `readonly`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `typeAlias` - matches any type alias declaration. | ||
- Allowed `modifiers`: `exported`, `unused`. | ||
- Allowed `types`: none. | ||
- `enum` - matches any enum declaration. | ||
- Allowed `modifiers`: `exported`, `unused`. | ||
- `typeMethod` - matches any object type method. Also matches properties that have direct function expression or arrow function expression values. Does not match accessors. | ||
- Allowed `modifiers`: `public`, `requiresQuotes`. | ||
- Allowed `types`: none. | ||
@@ -257,2 +259,8 @@ - `typeParameter` - matches any generic type parameter declaration. | ||
- Allowed `types`: none. | ||
- `typeProperty` - matches any object type property. Does not match properties that have direct function expression or arrow function expression values. | ||
- Allowed `modifiers`: `public`, `readonly`, `requiresQuotes`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `variable` - matches any `const` / `let` / `var` variable name. | ||
- Allowed `modifiers`: `async`, `const`, `destructured`, `exported`, `global`, `unused`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
@@ -266,10 +274,7 @@ ##### Group Selectors | ||
- Allowed `types`: none. | ||
- `variableLike` - matches the same as `function`, `parameter` and `variable`. | ||
- Allowed `modifiers`: `async`, `unused`. | ||
- Allowed `types`: none. | ||
- `memberLike` - matches the same as `accessor`, `enumMember`, `method`, `parameterProperty`, `property`. | ||
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`. | ||
- Allowed `types`: none. | ||
- `typeLike` - matches the same as `class`, `enum`, `interface`, `typeAlias`, `typeParameter`. | ||
- Allowed `modifiers`: `abstract`, `unused`. | ||
- `method` - matches the same as `classMethod`, `objectLiteralMethod`, `typeMethod`. | ||
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`. | ||
- Allowed `types`: none. | ||
@@ -279,5 +284,8 @@ - `property` - matches the same as `classProperty`, `objectLiteralProperty`, `typeProperty`. | ||
- Allowed `types`: `array`, `boolean`, `function`, `number`, `string`. | ||
- `method` - matches the same as `classMethod`, `objectLiteralMethod`, `typeMethod`. | ||
- Allowed `modifiers`: `abstract`, `async`, `override`, `#private`, `private`, `protected`, `public`, `readonly`, `requiresQuotes`, `static`. | ||
- `typeLike` - matches the same as `class`, `enum`, `interface`, `typeAlias`, `typeParameter`. | ||
- Allowed `modifiers`: `abstract`, `unused`. | ||
- Allowed `types`: none. | ||
- `variableLike` - matches the same as `function`, `parameter` and `variable`. | ||
- Allowed `modifiers`: `async`, `unused`. | ||
- Allowed `types`: none. | ||
@@ -292,14 +300,14 @@ ## FAQ | ||
1. check the `selector` | ||
1. if `selector` is one individual selector → the name's type must be of that type. | ||
1. if `selector` is a group selector → the name's type must be one of the grouped types. | ||
1. if `selector` is an array of selectors → apply the above for each selector in the array. | ||
1. check the `filter` | ||
1. if `filter` is omitted → skip this step. | ||
1. if the name matches the `filter` → continue evaluating this selector. | ||
1. if the name does not match the `filter` → skip this selector and continue to the next selector. | ||
1. check the `types` | ||
2. if the name matches the `filter` → continue evaluating this selector. | ||
3. if the name does not match the `filter` → skip this selector and continue to the next selector. | ||
2. check the `selector` | ||
1. if `selector` is one individual selector → the name's type must be of that type. | ||
2. if `selector` is a group selector → the name's type must be one of the grouped types. | ||
3. if `selector` is an array of selectors → apply the above for each selector in the array. | ||
3. check the `types` | ||
1. if `types` is omitted → skip this step. | ||
1. if the name has a type in `types` → continue evaluating this selector. | ||
1. if the name does not have a type in `types` → skip this selector and continue to the next selector. | ||
2. if the name has a type in `types` → continue evaluating this selector. | ||
3. if the name does not have a type in `types` → skip this selector and continue to the next selector. | ||
@@ -718,2 +726,9 @@ A name is considered to pass the config if it: | ||
If you do not want to enforce naming conventions for anything. | ||
This rule can be very strict. | ||
If you don't have strong needs for enforcing naming conventions, we recommend using it only to flag very egregious violations of your naming standards. | ||
Consider documenting your naming conventions and enforcing them in code review if you have processes like that. | ||
If you do not want to enforce naming conventions for anything, you can disable this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend that if you care about naming conventions, pick a single option for this rule that works best for your project. |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-array-constructor`](https://eslint.org/docs/rules/no-array-constructor) rule. | ||
@@ -20,4 +18,2 @@ It adds support for the generically typed `Array` constructor (`new Array<Foo>()`). | ||
```ts | ||
/*eslint no-array-constructor: "error"*/ | ||
Array(0, 1, 2); | ||
@@ -30,4 +26,2 @@ new Array(0, 1, 2); | ||
```ts | ||
/*eslint no-array-constructor: "error"*/ | ||
Array<number>(0, 1, 2); | ||
@@ -34,0 +28,0 @@ new Array<Foo>(x, y, z); |
@@ -32,3 +32,3 @@ --- | ||
`Value: ${value}`; | ||
({}.toString()); | ||
({}).toString(); | ||
``` | ||
@@ -69,3 +69,3 @@ | ||
```ts | ||
```ts option='{ "ignoredTypeNames": ["RegExp"] }' showPlaygroundButton | ||
`${/regex/}`; | ||
@@ -81,3 +81,3 @@ '' + /regex/; | ||
If you don't mind `"[object Object]"` in your strings, then you will not need this rule. | ||
If you don't mind a risk of `"[object Object]"` or incorrect type coercions in your values, then you will not need this rule. | ||
@@ -84,0 +84,0 @@ ## Related To |
@@ -79,3 +79,3 @@ --- | ||
```ts | ||
```ts option='{ "ignoreArrowShorthand": true }' showPlaygroundButton | ||
promise.then(value => window.postMessage(value)); | ||
@@ -96,3 +96,3 @@ ``` | ||
```ts | ||
```ts option='{ "ignoreVoidOperator": true }' showPlaygroundButton | ||
// now it's obvious that we don't expect any response | ||
@@ -118,2 +118,2 @@ promise.then(value => void window.postMessage(value)); | ||
If you don't care about being explicit about the void type in actual code then don't use this rule. | ||
Also, if you prefer concise coding style then also don't use it. | ||
Also, if you strongly prefer a concise coding style more strongly than any fear of `void`-related bugs then you can avoid this rule. |
@@ -9,5 +9,7 @@ --- | ||
## Examples | ||
import TypeScriptOverlap from "@site/src/components/TypeScriptOverlap"; | ||
<TypeScriptOverlap /> | ||
This rule extends the base [`eslint/no-dupe-class-members`](https://eslint.org/docs/rules/no-dupe-class-members) rule. | ||
It adds support for TypeScript's method overload definitions. |
@@ -51,1 +51,9 @@ --- | ||
``` | ||
## When Not To Use It | ||
It can sometimes be useful to include duplicate enum members for very specific use cases. | ||
For example, when renaming an enum member, it can sometimes be useful to keep the old name until a scheduled major breaking change. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
In general, if your project intentionally duplicates enum member values, you can avoid this rule. |
@@ -1,12 +0,13 @@ | ||
--- | ||
description: 'Disallow duplicate imports.' | ||
--- | ||
> 🛑 This file is source code, not the primary documentation location! 🛑 | ||
> | ||
> See **https://typescript-eslint.io/rules/no-duplicate-imports** for documentation. | ||
:::danger Deprecated | ||
This rule has been deprecated in favour of the [`import/no-duplicates`](https://github.com/import-js/eslint-plugin-import/blob/HEAD/docs/rules/no-duplicates.md) rule. | ||
::: | ||
<!-- | ||
This doc file has been left on purpose because `import/no-duplicates` is | ||
commonly requested. This exists to help direct people to the replacement rule. | ||
Note that there is no actual way to get to this page in the normal navigation, | ||
so end-users will only be able to get to this page from the search bar. | ||
--> |
@@ -13,4 +13,2 @@ --- | ||
## Rule Details | ||
This rule disallows duplicate union or intersection constituents. | ||
@@ -63,1 +61,8 @@ We consider types to be duplicate if they evaluate to the same result in the type system. | ||
When set to true, duplicate checks on union type constituents are ignored. | ||
## When Not To Use It | ||
It can sometimes be useful for the sake of documentation to include aliases for the same type. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
> In some of those cases, [branded types](https://basarat.gitbook.io/typescript/main-1/nominaltyping#using-interfaces) might be a type-safe way to represent the underlying data types. |
@@ -50,5 +50,5 @@ --- | ||
When you know your keys are safe to delete, this rule can be unnecessary. | ||
Some environments such as older browsers might not support `Map` and `Set`. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
Do not consider this rule as performance advice before profiling your code's bottlenecks. | ||
Even repeated minor performance slowdowns likely do not significantly affect your application's general perceived speed. |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-empty-function`](https://eslint.org/docs/rules/no-empty-function) rule. | ||
@@ -45,3 +43,3 @@ It adds support for handling TypeScript specific code that would otherwise trigger the rule. | ||
```ts | ||
```ts option='{ "allow": ["private-constructors"] }' showPlaygroundButton | ||
class Foo { | ||
@@ -56,3 +54,3 @@ private constructor() {} | ||
```ts | ||
```ts option='{ "allow": ["protected-constructors"] }' showPlaygroundButton | ||
class Foo { | ||
@@ -67,3 +65,3 @@ protected constructor() {} | ||
```ts | ||
```ts option='{ "allow": ["decoratedFunctions"] }' showPlaygroundButton | ||
@decorator() | ||
@@ -82,3 +80,3 @@ function foo() {} | ||
```ts | ||
```ts option='{ "allow": ["overrideMethods"] }' showPlaygroundButton | ||
abstract class Base { | ||
@@ -94,1 +92,10 @@ protected greet(): void { | ||
``` | ||
## When Not To Use It | ||
If you are working with external APIs that require functions even if they do nothing, then you may want to avoid this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
Test code often violates this rule as well. | ||
If your testing setup doesn't support "mock" or "spy" functions such as [`jest.fn()`](https://jestjs.io/docs/mock-functions), [`sinon.spy()`](https://sinonjs.org/releases/latest/spies), or [`vi.fn()`](https://vitest.dev/guide/mocking.html), you may wish to disable this rule in test files. | ||
Again, if those cases aren't extremely common, you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule in test files. |
@@ -101,7 +101,5 @@ --- | ||
Examples of **incorrect** code for the `{ "ignoreRestArgs": false }` option: | ||
The examples below are **incorrect** when `{ignoreRestArgs: false}`, but **correct** when `{ignoreRestArgs: true}`. | ||
```ts | ||
/*eslint @typescript-eslint/no-explicit-any: ["error", { "ignoreRestArgs": false }]*/ | ||
```ts option='{ "ignoreRestArgs": false }' showPlaygroundButton | ||
function foo1(...args: any[]): void {} | ||
@@ -131,36 +129,17 @@ function foo2(...args: readonly any[]): void {} | ||
Examples of **correct** code for the `{ "ignoreRestArgs": true }` option: | ||
## When Not To Use It | ||
```ts | ||
/*eslint @typescript-eslint/no-explicit-any: ["error", { "ignoreRestArgs": true }]*/ | ||
`any` is always a dangerous escape hatch. | ||
Whenever possible, it is always safer to avoid it. | ||
TypeScript's `unknown` is almost always preferable to `any`. | ||
function foo1(...args: any[]): void {} | ||
function foo2(...args: readonly any[]): void {} | ||
function foo3(...args: Array<any>): void {} | ||
function foo4(...args: ReadonlyArray<any>): void {} | ||
However, there are occasional situations where it can be necessary to use `any`. | ||
Most commonly: | ||
declare function bar(...args: any[]): void; | ||
- If your project isn't fully onboarded to TypeScript yet, `any` can be temporarily used in places where types aren't yet known or representable | ||
- If an external package doesn't yet have typings and you want to use `any` pending adding a `.d.ts` for it | ||
- You're working with particularly complex or nuanced code that can't yet be represented in the TypeScript type system | ||
const baz = (...args: any[]) => {}; | ||
const qux = function (...args: any[]) {}; | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
type Quux = (...args: any[]) => void; | ||
type Quuz = new (...args: any[]) => void; | ||
interface Grault { | ||
(...args: any[]): void; | ||
} | ||
interface Corge { | ||
new (...args: any[]): void; | ||
} | ||
interface Garply { | ||
f(...args: any[]): void; | ||
} | ||
``` | ||
## When Not To Use It | ||
If an unknown type or a library without typings is used | ||
and you want to be able to specify `any`. | ||
## Related To | ||
@@ -176,2 +155,5 @@ | ||
- TypeScript [any type](https://www.typescriptlang.org/docs/handbook/basic-types.html#any) | ||
- TypeScript [`any` type](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any) | ||
- TypeScript's [`unknown` type](https://www.typescriptlang.org/docs/handbook/2/functions.html#unknown) | ||
- TypeScript [`any` type documentation](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#any) | ||
- TypeScript [`unknown` type release notes](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-3-0.html#new-unknown-top-type) |
@@ -53,1 +53,3 @@ --- | ||
``` | ||
<!-- Intentionally Omitted: When Not To Use It --> |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-extra-parens`](https://eslint.org/docs/rules/no-extra-parens) rule. | ||
It adds support for TypeScript type assertions. |
@@ -9,5 +9,5 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-extra-semi`](https://eslint.org/docs/rules/no-extra-semi) rule. | ||
It adds support for class properties. | ||
Note that this rule is classified as a "Suggestion" rule instead of a "Layout & Formatting" rule because [adding extra semi-colons actually changes the AST of the program](https://typescript-eslint.io/play/#ts=5.1.6&showAST=es&fileType=.ts&code=MYewdgzgLgBAHjAvDAjAbg0A&eslintrc=N4KABGBEBOCuA2BTAzpAXGUEKQHYHsBaRADwBdoBDQ5RAWwEt0p8AzVyAGnG0gAEyATwAOKAMbQGwssWTwGuMgHoCxclRr0mGSImjR80SDwC%2BIE0A&tsconfig=&tokens=false). With that said, modern TypeScript formatters will remove extra semi-colons automatically during the formatting process. Thus, if you [use a formatter](/linting/troubleshooting/formatting), then enabling this rule is probably unnecessary. |
@@ -208,3 +208,3 @@ --- | ||
```ts | ||
```ts option='{ "allowConstructorOnly": true }' | ||
class NoFields {} | ||
@@ -215,3 +215,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowConstructorOnly": true }' | ||
class NoFields { | ||
@@ -232,3 +232,3 @@ constructor() { | ||
```ts | ||
```ts option='{ "allowEmpty": true }' | ||
class NoFields { | ||
@@ -243,3 +243,3 @@ constructor() { | ||
```ts | ||
```ts option='{ "allowEmpty": true }' | ||
class NoFields {} | ||
@@ -261,3 +261,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowStaticOnly": true }' | ||
class EmptyClass {} | ||
@@ -268,3 +268,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowStaticOnly": true }' | ||
class NotEmptyClass { | ||
@@ -283,3 +283,3 @@ static version = 42; | ||
```ts | ||
```ts option='{ "allowWithDecorator": true }' | ||
class Constants { | ||
@@ -292,3 +292,3 @@ static readonly version = 42; | ||
```ts | ||
```ts option='{ "allowWithDecorator": true }' | ||
class Constants { | ||
@@ -302,2 +302,3 @@ @logOnRead() | ||
You can disable this rule if you are unable -or unwilling- to switch off using classes as namespaces. | ||
If your project was set up before modern class and namespace practices, and you don't have the time to switch over, you might not be practically able to use this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -61,3 +61,3 @@ --- | ||
Promise.reject('value').finally(() => {}); | ||
await Promise.reject('value').finally(() => {}); | ||
``` | ||
@@ -74,3 +74,3 @@ | ||
```ts | ||
```ts option='{ "ignoreVoid": true }' showPlaygroundButton | ||
async function returnsPromise() { | ||
@@ -88,7 +88,7 @@ return 'value'; | ||
This allows you to skip checking of async IIFEs (Immediately Invocated function Expressions). | ||
This allows you to skip checking of async IIFEs (Immediately Invoked function Expressions). | ||
Examples of **correct** code for this rule with `{ ignoreIIFE: true }`: | ||
```ts | ||
```ts option='{ "ignoreIIFE": true }' showPlaygroundButton | ||
await(async function () { | ||
@@ -105,3 +105,5 @@ await res(1); | ||
If you do not use Promise-like values in your codebase, or want to allow them to remain unhandled. | ||
This rule can be difficult to enable on large existing projects that set up many floating Promises. | ||
Alternately, if you're not worried about crashes from floating or misused Promises -such as if you have global unhandled Promise handlers registered- then in some cases it may be safe to not use this rule. | ||
You might consider using `void`s and/or [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -108,0 +110,0 @@ ## Related To |
@@ -56,2 +56,3 @@ --- | ||
If you want to iterate through a loop using the indices in an array as strings, you can turn off this rule. | ||
If your project is a rare one that intentionally loops over string indices of arrays, you can turn off this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -101,2 +101,3 @@ --- | ||
If you want to allow `new Function()` or `setTimeout()`, `setInterval()`, `setImmediate()` and `execScript()` with string arguments, then you can safely disable this rule. | ||
If your project is a rare one that needs to allow `new Function()` or `setTimeout()`, `setInterval()`, `setImmediate()` and `execScript()` with string arguments, then you can disable this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -68,4 +68,3 @@ --- | ||
- If you want to leave behind side effect imports, then you shouldn't use this rule. | ||
- If you're not using TypeScript 5.0's `verbatimModuleSyntax` option, then you don't need this rule. | ||
If you're not using TypeScript 5.0's `verbatimModuleSyntax` option and your project is built with a bundler that manages import side effects for you, this rule may not be as useful for you. | ||
@@ -72,0 +71,0 @@ ## Related To |
@@ -81,3 +81,3 @@ --- | ||
```ts | ||
```ts option='{ "ignoreParameters": true }' showPlaygroundButton | ||
function foo(a: number = 5, b: boolean = true) { | ||
@@ -92,3 +92,3 @@ // ... | ||
```ts | ||
```ts option='{ "ignoreProperties": true }' showPlaygroundButton | ||
class Foo { | ||
@@ -101,6 +101,6 @@ prop: number = 5; | ||
If you do not want to enforce inferred types. | ||
If you strongly prefer to have explicit types regardless of whether they can be inferred, this rule may not be for you. | ||
## Further Reading | ||
TypeScript [Inference](https://www.typescriptlang.org/docs/handbook/type-inference.html) | ||
- [TpeScript Inference](https://www.typescriptlang.org/docs/handbook/type-inference.html) |
@@ -9,5 +9,7 @@ --- | ||
## Examples | ||
import TypeScriptOverlap from "@site/src/components/TypeScriptOverlap"; | ||
<TypeScriptOverlap strict /> | ||
This rule extends the base [`eslint/no-invalid-this`](https://eslint.org/docs/rules/no-invalid-this) rule. | ||
It adds support for TypeScript's `this` parameters. |
@@ -69,3 +69,3 @@ --- | ||
```ts | ||
```ts option='{ "allowInGenericTypeArguments": false }' showPlaygroundButton | ||
logAndReturn<void>(undefined); | ||
@@ -79,3 +79,3 @@ | ||
```ts | ||
```ts option='{ "allowInGenericTypeArguments": ["Ex.Mx.Tx"] }' showPlaygroundButton | ||
logAndReturn<void>(undefined); | ||
@@ -90,3 +90,3 @@ | ||
```ts | ||
```ts option='{ "allowInGenericTypeArguments": ["Ex.Mx.Tx"] }' showPlaygroundButton | ||
type AllowedVoid = Ex.Mx.Tx<void>; | ||
@@ -105,3 +105,3 @@ type AllowedVoidUnion = void | Ex.Mx.Tx<void>; | ||
```ts | ||
```ts option='{ "allowAsThisParameter": false }' showPlaygroundButton | ||
function doThing(this: void) {} | ||
@@ -116,3 +116,2 @@ class Example { | ||
If you don't care about if `void` is used with other types, | ||
or in invalid places, then you don't need this rule. | ||
If you don't care about if `void` is used with other types, or in invalid places, then you don't need this rule. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-loop-func`](https://eslint.org/docs/rules/no-loop-func) rule. | ||
It adds support for TypeScript types. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-loss-of-precision`](https://eslint.org/docs/rules/no-loss-of-precision) rule. | ||
It adds support for [numeric separators](https://github.com/tc39/proposal-numeric-separator). |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-magic-numbers`](https://eslint.org/docs/rules/no-magic-numbers) rule. | ||
@@ -46,5 +44,3 @@ It adds support for: | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnums": false }]*/ | ||
```ts option='{ "ignoreEnums": false }' showPlaygroundButton | ||
enum foo { | ||
@@ -57,5 +53,3 @@ SECOND = 1000, | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnums": true }]*/ | ||
```ts option='{ "ignoreEnums": true }' showPlaygroundButton | ||
enum foo { | ||
@@ -72,5 +66,3 @@ SECOND = 1000, | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": false }]*/ | ||
```ts option='{ "ignoreNumericLiteralTypes": false }' showPlaygroundButton | ||
type SmallPrimes = 2 | 3 | 5 | 7 | 11; | ||
@@ -81,5 +73,3 @@ ``` | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreNumericLiteralTypes": true }]*/ | ||
```ts option='{ "ignoreNumericLiteralTypes": true }' showPlaygroundButton | ||
type SmallPrimes = 2 | 3 | 5 | 7 | 11; | ||
@@ -92,5 +82,3 @@ ``` | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": false }]*/ | ||
```ts option='{ "ignoreReadonlyClassProperties": false }' showPlaygroundButton | ||
class Foo { | ||
@@ -106,5 +94,3 @@ readonly A = 1; | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": true }]*/ | ||
```ts option='{ "ignoreReadonlyClassProperties": true }' showPlaygroundButton | ||
class Foo { | ||
@@ -124,5 +110,3 @@ readonly A = 1; | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreTypeIndexes": false }]*/ | ||
```ts option='{ "ignoreTypeIndexes": false }' showPlaygroundButton | ||
type Foo = Bar[0]; | ||
@@ -134,7 +118,11 @@ type Baz = Parameters<Foo>[2]; | ||
```ts | ||
/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreTypeIndexes": true }]*/ | ||
```ts option='{ "ignoreTypeIndexes": true }' showPlaygroundButton | ||
type Foo = Bar[0]; | ||
type Baz = Parameters<Foo>[2]; | ||
``` | ||
## When Not To Use It | ||
If your project frequently deals with constant numbers and you don't wish to take up extra space to declare them, this rule might not be for you. | ||
We recommend at least using descriptive comments and/or names to describe constants. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) instead of completely disabling this rule. |
@@ -48,1 +48,5 @@ --- | ||
`checkNever: true` will suggest removing `void` when the argument has type `never`. | ||
## When Not To Use It | ||
If you don't mind extra `void`s in your project, you can avoid this rule. |
@@ -46,2 +46,3 @@ --- | ||
If you intentionally want a class with a `new` method, and you're confident nobody working in your code will mistake it with a constructor. | ||
If you intentionally want a class with a `new` method, and you're confident nobody working in your code will mistake it with a constructor, you might not want this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -43,3 +43,3 @@ --- | ||
```ts | ||
```ts option='{ "checksConditionals": true }' | ||
const promise = Promise.resolve('value'); | ||
@@ -60,3 +60,3 @@ | ||
```ts | ||
```ts option='{ "checksConditionals": true }' | ||
const promise = Promise.resolve('value'); | ||
@@ -80,4 +80,4 @@ | ||
Likewise, if you don't want functions that return promises where a void return is | ||
expected to be checked, your configuration will look like this: | ||
Likewise, if you don't want to check functions that return promises where a void return is | ||
expected, your configuration will look like this: | ||
@@ -126,3 +126,3 @@ ```json | ||
```ts | ||
```ts option='{ "checksVoidReturn": true }' | ||
[1, 2, 3].forEach(async value => { | ||
@@ -147,3 +147,3 @@ await doSomething(value); | ||
```ts | ||
```ts option='{ "checksVoidReturn": true }' | ||
// for-of puts `await` in outer context | ||
@@ -211,3 +211,3 @@ for (const value of [1, 2, 3]) { | ||
```ts | ||
```ts option='{ "checksSpreads": true }' | ||
const getData = () => someAsyncOperation({ myArg: 'foo' }); | ||
@@ -226,3 +226,3 @@ | ||
```ts | ||
```ts option='{ "checksSpreads": true }' | ||
const getData = () => someAsyncOperation({ myArg: 'foo' }); | ||
@@ -243,4 +243,5 @@ | ||
If you do not use Promises in your codebase or are not concerned with possible | ||
misuses of them outside of what the TypeScript compiler will check. | ||
This rule can be difficult to enable on large existing projects that set up many misused Promises. | ||
Alternately, if you're not worried about crashes from floating or misused Promises -such as if you have global unhandled Promise handlers registered- then in some cases it may be safe to not use this rule. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -247,0 +248,0 @@ ## Further Reading |
@@ -51,3 +51,3 @@ --- | ||
```ts | ||
```ts option='{ "allowDeclarations": true }' | ||
module foo {} | ||
@@ -59,3 +59,3 @@ namespace foo {} | ||
```ts | ||
```ts option='{ "allowDeclarations": true }' | ||
declare module 'foo' {} | ||
@@ -82,3 +82,3 @@ declare module foo {} | ||
```ts | ||
```ts option='{ "allowDeclarations": false }' | ||
module foo {} | ||
@@ -92,3 +92,3 @@ namespace foo {} | ||
```ts | ||
```ts option='{ "allowDeclarations": false }' | ||
declare module 'foo' {} | ||
@@ -105,3 +105,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowDefinitionFiles": true }' | ||
// if outside a d.ts file | ||
@@ -120,3 +120,3 @@ module foo {} | ||
```ts | ||
```ts option='{ "allowDefinitionFiles": true }' | ||
declare module 'foo' {} | ||
@@ -129,3 +129,5 @@ | ||
If you are using the ES2015 module syntax, then you will not need this rule. | ||
If your project was architected before modern modules and namespaces, it may be difficult to migrate off of namespaces. | ||
In that case you may not be able to use this rule for parts of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -132,0 +134,0 @@ ## Further Reading |
@@ -46,2 +46,7 @@ --- | ||
## When Not To Use It | ||
If your project's types don't yet fully describe whether certain values may be nullable, such as if you're transitioning to `strictNullChecks`, this rule might create many false reports. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Further Reading | ||
@@ -48,0 +53,0 @@ |
@@ -32,2 +32,7 @@ --- | ||
## When Not To Use It | ||
If your project's types don't yet fully describe whether certain values may be nullable, such as if you're transitioning to `strictNullChecks`, this rule might create many false reports. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Further Reading | ||
@@ -34,0 +39,0 @@ |
@@ -41,3 +41,3 @@ --- | ||
If your project does not use the `strictNullChecks` compiler option, this rule is likely useless to you. | ||
If your code is often wildly incorrect with respect to strict null-checking, your code may not yet be ready for this rule. | ||
If your project's types don't yet fully describe whether certain values may be nullable, such as if you're transitioning to `strictNullChecks`, this rule might create many false reports. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -9,4 +9,6 @@ --- | ||
## Examples | ||
import TypeScriptOverlap from "@site/src/components/TypeScriptOverlap"; | ||
<TypeScriptOverlap /> | ||
This rule extends the base [`eslint/no-redeclare`](https://eslint.org/docs/rules/no-redeclare) rule. | ||
@@ -44,3 +46,3 @@ It adds support for TypeScript function overloads, and declaration merging. | ||
```ts | ||
```ts option='{ "ignoreDeclarationMerge": true }' showPlaygroundButton | ||
interface A { | ||
@@ -71,3 +73,3 @@ prop1: 1; | ||
```ts | ||
```ts option='{ "ignoreDeclarationMerge": true }' showPlaygroundButton | ||
type something = string; | ||
@@ -74,0 +76,0 @@ // eslint-disable-next-line @typescript-eslint/no-redeclare -- intentionally naming the variable the same as the type |
@@ -73,2 +73,16 @@ --- | ||
## When Not To Use It | ||
Some projects choose to occasionally intentionally include a redundant type constituent for documentation purposes. | ||
For example, the following code includes `string` in a union even though the `unknown` makes it redundant: | ||
```ts | ||
/** | ||
* Normally a string name, but sometimes arbitrary unknown data. | ||
*/ | ||
type NameOrOther = string | unknown; | ||
``` | ||
If you strongly feel a preference for these unnecessary type constituents, this rule might not be for you. | ||
## Further Reading | ||
@@ -75,0 +89,0 @@ |
@@ -33,3 +33,4 @@ --- | ||
If you don't care about using newer module syntax, then you will not need this rule. | ||
If your project frequently uses older CommonJS `require`s, then this rule might not be applicable to you. | ||
If only a subset of your project uses `require`s then you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -36,0 +37,0 @@ ## Related To |
@@ -9,6 +9,4 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-restricted-imports`](https://eslint.org/docs/rules/no-restricted-imports) rule. It adds support for the type import (`import type X from "..."`, `import { type X } from "..."`) and `import x = require("...")` syntaxes. | ||
This rule extends the base [`eslint/no-restricted-imports`](https://eslint.org/docs/rules/no-restricted-imports) rule. | ||
## Options | ||
@@ -25,13 +23,23 @@ | ||
```jsonc | ||
"@typescript-eslint/no-restricted-imports": ["error", { | ||
"paths": [{ | ||
"name": "import-foo", | ||
"message": "Please use import-bar instead.", | ||
"allowTypeImports": true | ||
}, { | ||
"name": "import-baz", | ||
"message": "Please use import-quux instead.", | ||
"allowTypeImports": true | ||
}] | ||
}] | ||
{ | ||
"rules": { | ||
"@typescript-eslint/no-restricted-imports": [ | ||
"error", | ||
{ | ||
"paths": [ | ||
{ | ||
"name": "import-foo", | ||
"message": "Please use import-bar instead.", | ||
"allowTypeImports": true | ||
}, | ||
{ | ||
"name": "import-baz", | ||
"message": "Please use import-quux instead.", | ||
"allowTypeImports": true | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
``` | ||
@@ -47,3 +55,3 @@ | ||
```ts | ||
```ts option='{"paths":[{"name":"import-foo","message":"Please use import-bar instead.","allowTypeImports":true},{"name":"import-baz","message":"Please use import-quux instead.","allowTypeImports":true}]}' | ||
import foo from 'import-foo'; | ||
@@ -58,3 +66,3 @@ export { Foo } from 'import-foo'; | ||
```ts | ||
```ts option='{"paths":[{"name":"import-foo","message":"Please use import-bar instead.","allowTypeImports":true},{"name":"import-baz","message":"Please use import-quux instead.","allowTypeImports":true}]}' | ||
import { foo } from 'other-module'; | ||
@@ -61,0 +69,0 @@ |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-shadow`](https://eslint.org/docs/rules/no-shadow) rule. | ||
@@ -40,3 +38,3 @@ It adds support for TypeScript's `this` parameters and global augmentation, and adds options for TypeScript features. | ||
```ts | ||
```ts option='{ "ignoreTypeValueShadow": true }' showPlaygroundButton | ||
type Foo = number; | ||
@@ -79,3 +77,3 @@ const Foo = 1; | ||
```ts | ||
```ts option='{ "ignoreFunctionTypeParameterNameValueShadow": true }' showPlaygroundButton | ||
const test = 1; | ||
@@ -82,0 +80,0 @@ type Func = (test: string) => typeof test; |
@@ -38,2 +38,3 @@ --- | ||
If you need to assign `this` to variables, you shouldn’t use this rule. | ||
If your project is structured in a way that it needs to assign `this` to variables, this rule is likely not for you. | ||
If only a subset of your project assigns `this` to variables then you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -23,4 +23,2 @@ --- | ||
```ts | ||
/*eslint @typescript-eslint/no-throw-literal: "error"*/ | ||
throw 'error'; | ||
@@ -57,15 +55,13 @@ | ||
```ts | ||
/*eslint @typescript-eslint/no-throw-literal: "error"*/ | ||
throw new Error(); | ||
throw new Error("error"); | ||
throw new Error('error'); | ||
const e = new Error("error"); | ||
const e = new Error('error'); | ||
throw e; | ||
try { | ||
throw new Error("error"); | ||
throw new Error('error'); | ||
} catch (e) { | ||
throw e; | ||
throw e; | ||
} | ||
@@ -82,4 +78,4 @@ | ||
const foo = { | ||
bar: new Error(); | ||
} | ||
bar: new Error(), | ||
}; | ||
throw foo.bar; | ||
@@ -89,3 +85,3 @@ | ||
// ... | ||
}; | ||
} | ||
throw new CustomError(); | ||
@@ -116,1 +112,3 @@ ``` | ||
``` | ||
<!-- Intentionally omitted: When Not To Use It --> |
@@ -9,2 +9,16 @@ --- | ||
:::danger Deprecated | ||
This rule has been deprecated in favour of the [`@typescript-eslint/consistent-type-definitions`](./consistent-type-definitions.md) rule. | ||
TypeScript type aliases are a commonly necessary language feature; banning it altogether is oftentimes counterproductive. | ||
::: | ||
:::note | ||
If you want to ban certain classifications of type aliases, consider using [`no-restricted-syntax`](https://eslint.org/docs/latest/rules/no-restricted-syntax). | ||
See [Troubleshooting & FAQs](/linting/troubleshooting#how-can-i-ban-specific-language-feature). | ||
::: | ||
In TypeScript, type aliases serve three purposes: | ||
@@ -102,3 +116,3 @@ | ||
```ts | ||
```ts option='{ "allowAliases": "always" }' showPlaygroundButton | ||
// primitives | ||
@@ -130,3 +144,3 @@ type Foo = 'a'; | ||
```ts | ||
```ts option='{ "allowAliases": "in-unions" }' showPlaygroundButton | ||
// primitives | ||
@@ -152,3 +166,3 @@ type Foo = 'a'; | ||
```ts | ||
```ts option='{ "allowAliases": "in-unions" }' showPlaygroundButton | ||
// primitives | ||
@@ -170,3 +184,3 @@ type Foo = 'a' | 'b'; | ||
```ts | ||
```ts option='{ "allowAliases": "in-intersections" }' showPlaygroundButton | ||
// primitives | ||
@@ -194,3 +208,3 @@ type Foo = 'a'; | ||
```ts | ||
```ts option='{ "allowAliases": "in-intersections" }' showPlaygroundButton | ||
// primitives | ||
@@ -210,3 +224,3 @@ type Foo = string & string[]; | ||
```ts | ||
```ts option='{ "allowAliases": "in-unions-and-intersections" }' showPlaygroundButton | ||
// primitives | ||
@@ -228,3 +242,3 @@ type Foo = 'a'; | ||
```ts | ||
```ts option='{ "allowAliases": "in-unions-and-intersections" }' showPlaygroundButton | ||
// primitives | ||
@@ -260,3 +274,3 @@ type Foo = 'a' | 'b'; | ||
```ts | ||
```ts option='{ "allowCallbacks": "always" }' showPlaygroundButton | ||
type Foo = () => void; | ||
@@ -279,3 +293,3 @@ | ||
```ts | ||
```ts option='{ "allowConditionalTypes": "always" }' showPlaygroundButton | ||
type Foo<T> = T extends number ? number : null; | ||
@@ -294,3 +308,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowConstructors": "always" }' showPlaygroundButton | ||
type Foo = new () => void; | ||
@@ -312,3 +326,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowLiterals": "always" }' showPlaygroundButton | ||
type Foo = {}; | ||
@@ -334,3 +348,3 @@ | ||
```ts | ||
```ts option='{ "allowLiterals": "in-unions" }' showPlaygroundButton | ||
type Foo = {}; | ||
@@ -354,3 +368,3 @@ | ||
```ts | ||
```ts option='{ "allowLiterals": "in-unions" }' showPlaygroundButton | ||
type Foo = { name: string } | { age: number }; | ||
@@ -361,3 +375,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowLiterals": "in-intersections" }' showPlaygroundButton | ||
type Foo = {}; | ||
@@ -381,3 +395,3 @@ | ||
```ts | ||
```ts option='{ "allowLiterals": "in-intersections" }' showPlaygroundButton | ||
type Foo = { name: string } & { age: number }; | ||
@@ -388,3 +402,3 @@ ``` | ||
```ts | ||
```ts option='{ "allowLiterals": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo = {}; | ||
@@ -406,3 +420,3 @@ | ||
```ts | ||
```ts option='{ "allowLiterals": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo = { name: string } | { age: number }; | ||
@@ -426,3 +440,3 @@ | ||
```ts | ||
```ts option='{ "allowMappedTypes": "always" }' showPlaygroundButton | ||
type Foo<T> = { readonly [P in keyof T]: T[P] }; | ||
@@ -447,3 +461,3 @@ | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-unions" }' showPlaygroundButton | ||
type Foo<T> = { readonly [P in keyof T]: T[P] }; | ||
@@ -462,3 +476,3 @@ | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-unions" }' showPlaygroundButton | ||
type Foo<T, U> = | ||
@@ -473,3 +487,3 @@ | { readonly [P in keyof T]: T[P] } | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-intersections" }' showPlaygroundButton | ||
type Foo<T> = { readonly [P in keyof T]: T[P] }; | ||
@@ -488,3 +502,3 @@ | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-intersections" }' showPlaygroundButton | ||
type Foo<T, U> = { readonly [P in keyof T]: T[P] } & { | ||
@@ -499,3 +513,3 @@ readonly [P in keyof U]: U[P]; | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo<T> = { readonly [P in keyof T]: T[P] }; | ||
@@ -508,3 +522,3 @@ | ||
```ts | ||
```ts option='{ "allowMappedTypes": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo<T, U> = | ||
@@ -536,3 +550,3 @@ | { readonly [P in keyof T]: T[P] } | ||
```ts | ||
```ts option='{ "allowTupleTypes": "always" }' showPlaygroundButton | ||
type Foo = [number]; | ||
@@ -549,3 +563,3 @@ | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-unions" }' showPlaygroundButton | ||
type Foo = [number]; | ||
@@ -560,3 +574,3 @@ | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-unions" }' showPlaygroundButton | ||
type Foo = [number] | [number, number]; | ||
@@ -569,3 +583,3 @@ | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-intersections" }' showPlaygroundButton | ||
type Foo = [number]; | ||
@@ -580,3 +594,3 @@ | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-intersections" }' showPlaygroundButton | ||
type Foo = [number] & [number, number]; | ||
@@ -589,3 +603,3 @@ | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo = [number]; | ||
@@ -596,5 +610,5 @@ | ||
Examples of **correct** code for the `{ "allowLiterals": "in-unions-and-intersections" }` option: | ||
Examples of **correct** code for the `{ "allowTupleTypes": "in-unions-and-intersections" }` option: | ||
```ts | ||
```ts option='{ "allowTupleTypes": "in-unions-and-intersections" }' showPlaygroundButton | ||
type Foo = [number] & [number, number]; | ||
@@ -615,3 +629,3 @@ | ||
```ts | ||
```ts option='{ "allowGenerics": "always" }' showPlaygroundButton | ||
type Foo = Bar<string>; | ||
@@ -628,9 +642,6 @@ | ||
## When Not To Use It | ||
<!-- Intentionally Omitted: When Not To Use It --> | ||
When you can't express some shape with an interface or you need to use a union, tuple type, | ||
callback, etc. that would cause the code to be unreadable or impractical. | ||
## Further Reading | ||
- [Advanced Types](https://www.typescriptlang.org/docs/handbook/advanced-types.html) |
@@ -64,3 +64,3 @@ --- | ||
```ts | ||
```ts option='{ "allowComparingNullableBooleansToTrue": false }' | ||
declare const someUndefinedCondition: boolean | undefined; | ||
@@ -77,3 +77,3 @@ if (someUndefinedCondition === true) { | ||
```ts | ||
```ts option='{ "allowComparingNullableBooleansToTrue": false }' | ||
declare const someUndefinedCondition: boolean | undefined; | ||
@@ -96,3 +96,3 @@ if (someUndefinedCondition) { | ||
```ts | ||
```ts option='{ "allowComparingNullableBooleansToFalse": false }' | ||
declare const someUndefinedCondition: boolean | undefined; | ||
@@ -109,3 +109,3 @@ if (someUndefinedCondition === false) { | ||
```ts | ||
```ts option='{ "allowComparingNullableBooleansToFalse": false }' | ||
declare const someUndefinedCondition: boolean | undefined; | ||
@@ -122,14 +122,14 @@ if (someUndefinedCondition ?? true) { | ||
| Comparison | Fixer Output | Notes | | ||
| :----------------------------: | ------------------------------- | ----------------------------------------------------------------------------------- | | ||
| `booleanVar === true` | `booleanVar` | | | ||
| `booleanVar !== true` | `!booleanVar` | | | ||
| `booleanVar === false` | `!booleanVar` | | | ||
| `booleanVar !== false` | `booleanVar` | | | ||
| `nullableBooleanVar === true` | `nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | | ||
| `nullableBooleanVar !== true` | `!nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | | ||
| `nullableBooleanVar === false` | `nullableBooleanVar ?? true` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | | ||
| `nullableBooleanVar !== false` | `!(nullableBooleanVar ?? true)` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | | ||
| Comparison | Fixer Output | Notes | | ||
| :-------------------------------: | ------------------------------- | ----------------------------------------------------------------------------------- | | ||
| `booleanVar === true` | `booleanVar` | | | ||
| `booleanVar !== true` | `!booleanVar` | | | ||
| `booleanVar === false` | `!booleanVar` | | | ||
| `booleanVar !== false` | `booleanVar` | | | ||
| `nullableBooleanVar === true` | `nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | | ||
| `nullableBooleanVar !== true` | `!nullableBooleanVar` | Only checked/fixed if the `allowComparingNullableBooleansToTrue` option is `false` | | ||
| `!(nullableBooleanVar === false)` | `nullableBooleanVar ?? true` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | | ||
| `!(nullableBooleanVar !== false)` | `!(nullableBooleanVar ?? true)` | Only checked/fixed if the `allowComparingNullableBooleansToFalse` option is `false` | | ||
## Not To Use It | ||
## When Not To Use It | ||
@@ -136,0 +136,0 @@ Do not use this rule when `strictNullChecks` is disabled. |
@@ -80,3 +80,3 @@ --- | ||
```ts | ||
```ts option='{ "allowConstantLoopConditions": true }' showPlaygroundButton | ||
while (true) {} | ||
@@ -99,4 +99,21 @@ for (; true; ) {} | ||
The main downside to using this rule is the need for type information. | ||
If your project is not accurately typed, such as if it's in the process of being converted to TypeScript or is susceptible to [trade-offs in control flow analysis](https://github.com/Microsoft/TypeScript/issues/9998), it may be difficult to enable this rule for particularly non-type-safe areas of code. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
This rule has a known edge case of triggering on conditions that were modified within function calls (as side effects). | ||
It is due to limitations of TypeScript's type narrowing. | ||
See [#9998](https://github.com/microsoft/TypeScript/issues/9998) for details. | ||
We recommend upcasting the variable with a [type assertion](https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions). | ||
```ts | ||
let condition = false as boolean; | ||
const f = () => (condition = true); | ||
f(); | ||
if (condition) { | ||
} | ||
``` | ||
## Related To | ||
@@ -103,0 +120,0 @@ |
@@ -51,2 +51,2 @@ --- | ||
If you don't care about having unneeded enum or namespace qualifiers, then you don't need to use this rule. | ||
If you explicitly prefer to use fully qualified names, such as for explicitness, then you don't need to use this rule. |
@@ -74,1 +74,5 @@ --- | ||
``` | ||
## When Not To Use It | ||
If you prefer explicitly specifying type parameters even when they are equal to the default, you can skip this rule. |
@@ -68,5 +68,5 @@ --- | ||
With `@typescript-eslint/no-unnecessary-type-assertion: ["error", { typesToIgnore: ['Foo'] }]`, the following is **correct** code": | ||
With `@typescript-eslint/no-unnecessary-type-assertion: ["error", { typesToIgnore: ['Foo'] }]`, the following is **correct** code: | ||
```ts | ||
```ts option='{ "typesToIgnore": ["Foo"] }' showPlaygroundButton | ||
type Foo = 3; | ||
@@ -73,0 +73,0 @@ const foo: Foo = 3; |
@@ -10,4 +10,4 @@ --- | ||
Generic type parameters (`<T>`) in TypeScript may be "constrained" with an [`extends` keyword](https://www.typescriptlang.org/docs/handbook/generics.html#generic-constraints). | ||
When no `extends` is provided, type parameters default a constraint to `any`. | ||
It is therefore redundant to `extend` from `any`. | ||
When no `extends` is provided, type parameters default a constraint to `unknown`. | ||
It is therefore redundant to `extend` from `any` or `unknown`. | ||
@@ -23,4 +23,8 @@ ## Examples | ||
interface FooUnknown<T extends unknown> {} | ||
type BarAny<T extends any> = {}; | ||
type BarUnknown<T extends unknown> = {}; | ||
class BazAny<T extends any> { | ||
@@ -27,0 +31,0 @@ quxAny<U extends any>() {} |
@@ -76,9 +76,19 @@ --- | ||
```ts | ||
declare function foo(arg1: unknown, arg2: Set<unkown>, arg3: unknown[]): void; | ||
```ts showPlaygroundButton | ||
declare function foo(arg1: unknown, arg2: Set<unknown>, arg3: unknown[]): void; | ||
foo(1 as any, new Set<any>(), [] as any[]); | ||
``` | ||
## When Not To Use It | ||
If your codebase has many existing `any`s or areas of unsafe code, it may be difficult to enable this rule. | ||
It may be easier to skip the `no-unsafe-*` rules pending increasing type safety in unsafe areas of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`no-explicit-any`](./no-explicit-any.md) | ||
- [`no-unsafe-assignment`](./no-unsafe-assignment.md) | ||
- [`no-unsafe-call`](./no-unsafe-call.md) | ||
- [`no-unsafe-member-access`](./no-unsafe-member-access.md) | ||
- [`no-unsafe-return`](./no-unsafe-return.md) |
@@ -78,3 +78,3 @@ --- | ||
```ts | ||
```ts showPlaygroundButton | ||
const x: unknown = y as any; | ||
@@ -85,4 +85,14 @@ const x: unknown[] = y as any[]; | ||
## When Not To Use It | ||
If your codebase has many existing `any`s or areas of unsafe code, it may be difficult to enable this rule. | ||
It may be easier to skip the `no-unsafe-*` rules pending increasing type safety in unsafe areas of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`no-explicit-any`](./no-explicit-any.md) | ||
- [`no-unsafe-argument`](./no-unsafe-argument.md) | ||
- [`no-unsafe-call`](./no-unsafe-call.md) | ||
- [`no-unsafe-member-access`](./no-unsafe-member-access.md) | ||
- [`no-unsafe-return`](./no-unsafe-return.md) |
@@ -56,4 +56,14 @@ --- | ||
## When Not To Use It | ||
If your codebase has many existing `any`s or areas of unsafe code, it may be difficult to enable this rule. | ||
It may be easier to skip the `no-unsafe-*` rules pending increasing type safety in unsafe areas of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`no-explicit-any`](./no-explicit-any.md) | ||
- [`no-unsafe-argument`](./no-unsafe-argument.md) | ||
- [`no-unsafe-assignment`](./no-unsafe-assignment.md) | ||
- [`no-unsafe-member-access`](./no-unsafe-member-access.md) | ||
- [`no-unsafe-return`](./no-unsafe-return.md) |
@@ -52,4 +52,9 @@ --- | ||
## When Not To Use It | ||
If your project intentionally defines classes and interfaces with unsafe declaration merging patterns, this rule might not be for you. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Further Reading | ||
- [Declaration Merging](https://www.typescriptlang.org/docs/handbook/declaration-merging.html) |
@@ -57,3 +57,3 @@ --- | ||
arr[1]; | ||
const idx = 1; | ||
let idx = 1; | ||
arr[idx]; | ||
@@ -63,4 +63,14 @@ arr[idx++]; | ||
## When Not To Use It | ||
If your codebase has many existing `any`s or areas of unsafe code, it may be difficult to enable this rule. | ||
It may be easier to skip the `no-unsafe-*` rules pending increasing type safety in unsafe areas of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`no-explicit-any`](./no-explicit-any.md) | ||
- [`no-unsafe-argument`](./no-unsafe-argument.md) | ||
- [`no-unsafe-assignment`](./no-unsafe-assignment.md) | ||
- [`no-unsafe-call`](./no-unsafe-call.md) | ||
- [`no-unsafe-return`](./no-unsafe-return.md) |
@@ -91,3 +91,3 @@ --- | ||
```ts | ||
```ts showPlaygroundButton | ||
function foo1(): unknown { | ||
@@ -102,4 +102,14 @@ return JSON.parse(singleObjString); // Return type for JSON.parse is any. | ||
## When Not To Use It | ||
If your codebase has many existing `any`s or areas of unsafe code, it may be difficult to enable this rule. | ||
It may be easier to skip the `no-unsafe-*` rules pending increasing type safety in unsafe areas of your project. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
## Related To | ||
- [`no-explicit-any`](./no-explicit-any.md) | ||
- [`no-unsafe-argument`](./no-unsafe-argument.md) | ||
- [`no-unsafe-assignment`](./no-unsafe-assignment.md) | ||
- [`no-unsafe-call`](./no-unsafe-call.md) | ||
- [`no-unsafe-member-access`](./no-unsafe-member-access.md) |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-unused-expressions`](https://eslint.org/docs/rules/no-unused-expressions) rule. | ||
It adds support for optional call expressions `x?.()`, and directive in module declarations. |
@@ -9,5 +9,20 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-unused-vars`](https://eslint.org/docs/rules/no-unused-vars) rule. | ||
It adds support for TypeScript features, such as types. | ||
## Benefits Over TypeScript | ||
TypeScript provides [`noUnusedLocals`](https://www.typescriptlang.org/tsconfig#noUnusedLocals) and [`noUnusedParameters`](https://www.typescriptlang.org/tsconfig#noUnusedParameters) compiler options that can report errors on unused local variables or parameters, respectively. | ||
Those compiler options can be convenient to use if you don't want to set up ESLint and typescript-eslint. | ||
However: | ||
- These lint rules are more configurable than TypeScript's compiler options. | ||
- For example, the [`varsIgnorePattern` option](https://eslint.org/docs/latest/rules/no-unused-vars#varsignorepattern) can customize what names are always allowed to be exempted. TypeScript hardcodes its exemptions to names starting with `_`. | ||
- [ESLint can be configured](https://eslint.org/docs/latest/use/configure/rules) within lines, files, and folders. TypeScript compiler options are linked to their TSConfig file. | ||
- Many projects configure TypeScript's reported errors to block builds more aggressively than ESLint complaints. Blocking builds on unused variables can be inconvenient. | ||
We generally recommend using `@typescript-eslint/no-unused-vars` to flag unused locals and parameters instead of TypeScript. | ||
:::tip | ||
Editors such as VS Code will still generally "grey out" unused variables even if `noUnusedLocals` and `noUnusedParameters` are not enabled in a project. | ||
::: |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-use-before-define`](https://eslint.org/docs/rules/no-use-before-define) rule. | ||
@@ -45,5 +43,3 @@ It adds support for `type`, `interface` and `enum` declarations. | ||
```ts | ||
/*eslint no-use-before-define: ["error", { "enums": true }]*/ | ||
```ts option='{ "enums": true }' | ||
const x = Foo.FOO; | ||
@@ -58,5 +54,3 @@ | ||
```ts | ||
/*eslint no-use-before-define: ["error", { "enums": false }]*/ | ||
```ts option='{ "enums": false }' | ||
function foo() { | ||
@@ -78,5 +72,3 @@ return Foo.FOO; | ||
```ts | ||
/*eslint no-use-before-define: ["error", { "typedefs": false }]*/ | ||
```ts option='{ "typedefs": false }' showPlaygroundButton | ||
let myVar: StringOrNumber; | ||
@@ -93,5 +85,3 @@ type StringOrNumber = string | number; | ||
```ts | ||
/*eslint no-use-before-define: ["error", { "ignoreTypeReferences": true }]*/ | ||
```ts option='{ "ignoreTypeReferences": true }' showPlaygroundButton | ||
let var1: StringOrNumber; | ||
@@ -98,0 +88,0 @@ type StringOrNumber = string | number; |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/no-useless-constructor`](https://eslint.org/docs/rules/no-useless-constructor) rule. | ||
@@ -13,0 +11,0 @@ It adds support for: |
@@ -44,1 +44,5 @@ --- | ||
``` | ||
## When Not To Use It | ||
If you don't mind an empty `export {}` at the bottom of files, you likely don't need this rule. |
@@ -33,3 +33,4 @@ --- | ||
If you don't care about using newer module syntax, then you will not need this rule. | ||
If your project frequently uses older CommonJS `require`s, then this rule might not be applicable to you. | ||
If only a subset of your project uses `require`s then you might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -36,0 +37,0 @@ ## Related To |
@@ -41,2 +41,2 @@ --- | ||
If you don't mind having unnecessarily verbose type casts, you can avoid this rule. | ||
If you don't mind having unnecessarily verbose type assertions, you can avoid this rule. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/object-curly-spacing`](https://eslint.org/docs/rules/object-curly-spacing) rule. | ||
It adds support for TypeScript's object types. |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/padding-line-between-statements`](https://eslint.org/docs/rules/padding-line-between-statements) rule. | ||
@@ -13,0 +11,0 @@ It adds support for TypeScript constructs such as `interface` and `type`. |
@@ -112,3 +112,3 @@ --- | ||
```ts | ||
```ts option='{ "allow": ["readonly"] }' | ||
class Foo { | ||
@@ -141,3 +141,3 @@ constructor(private name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["readonly"] }' | ||
class Foo { | ||
@@ -160,3 +160,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["private"] }' | ||
class Foo { | ||
@@ -189,3 +189,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["private"] }' | ||
class Foo { | ||
@@ -208,3 +208,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["protected"] }' | ||
class Foo { | ||
@@ -237,3 +237,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["protected"] }' | ||
class Foo { | ||
@@ -256,3 +256,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["public"] }' | ||
class Foo { | ||
@@ -285,3 +285,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["public"] }' | ||
class Foo { | ||
@@ -304,3 +304,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["private readonly"] }' | ||
class Foo { | ||
@@ -333,3 +333,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["private readonly"] }' | ||
class Foo { | ||
@@ -352,3 +352,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["protected readonly"] }' | ||
class Foo { | ||
@@ -381,3 +381,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["protected readonly"] }' | ||
class Foo { | ||
@@ -400,3 +400,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["public readonly"] }' | ||
class Foo { | ||
@@ -429,3 +429,3 @@ constructor(readonly name: string) {} | ||
```ts | ||
```ts option='{ "allow": ["public readonly"] }' | ||
class Foo { | ||
@@ -448,3 +448,3 @@ constructor(name: string) {} | ||
```ts | ||
```ts option='{ "prefer": "parameter-property" }' | ||
class Foo { | ||
@@ -474,3 +474,3 @@ private name: string; | ||
```ts | ||
```ts option='{ "prefer": "parameter-property" }' | ||
class Foo { | ||
@@ -501,2 +501,5 @@ private differentName: string; | ||
If you don't care about the using parameter properties in constructors, then you will not need this rule. | ||
If you don't care about which style of parameter properties in constructors is used in your classes, then you will not need this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -44,2 +44,5 @@ --- | ||
If you are using TypeScript < 3.4 | ||
If you don't care about which style of literals assertions is used in your code, then you will not need this rule. | ||
However, keep in mind that inconsistent style can harm readability in a project. | ||
We recommend picking a single option for this rule that works best for your project. |
@@ -44,4 +44,2 @@ --- | ||
## When Not To Use It | ||
If you transpile for browsers that do not support for-of loops, you may wish to use traditional for loops that produce more compact code. | ||
<!-- Intentionally Omitted: When Not To Use It --> |
@@ -87,3 +87,3 @@ --- | ||
If you specifically want to use an interface or type literal with a single call signature for stylistic reasons, you can disable this rule. | ||
If you specifically want to use an interface or type literal with a single call signature for stylistic reasons, you can avoid this rule. | ||
@@ -90,0 +90,0 @@ This rule has a known edge case of sometimes triggering on global augmentations such as `interface Function`. |
@@ -60,3 +60,3 @@ --- | ||
array.includes(value); | ||
readonlyArray.includes(value); | ||
!readonlyArray.includes(value); | ||
typedArray.includes(value); | ||
@@ -76,4 +76,2 @@ maybe?.includes(''); | ||
## When Not To Use It | ||
If you don't want to suggest `includes`, you can safely turn this rule off. | ||
<!-- Intentionally Omitted: When Not To Use It --> |
@@ -72,3 +72,3 @@ --- | ||
```ts | ||
```ts option='{ "allowBitwiseExpressions": true }' | ||
const x = 1; | ||
@@ -88,3 +88,3 @@ enum Foo { | ||
```ts | ||
```ts option='{ "allowBitwiseExpressions": true }' | ||
enum Foo { | ||
@@ -103,2 +103,2 @@ A = 1 << 0, | ||
If you want use anything other than simple literals as an enum value. | ||
If you want use anything other than simple literals as an enum value, this rule might not be for you. |
@@ -41,3 +41,3 @@ --- | ||
If you are using the ES2015 module syntax, then you will not need this rule. | ||
If you are not using TypeScript's older `module`/`namespace` keywords, then you will not need this rule. | ||
@@ -44,0 +44,0 @@ ## Further Reading |
--- | ||
description: 'Enforce using the nullish coalescing operator instead of logical chaining.' | ||
description: 'Enforce using the nullish coalescing operator instead of logical assignments or chaining.' | ||
--- | ||
@@ -12,4 +12,7 @@ | ||
This rule reports when an `||` operator can be safely replaced with a `??`. | ||
This rule reports when you may consider replacing: | ||
- An `||` operator with `??` | ||
- An `||=` operator with `??=` | ||
:::caution | ||
@@ -23,7 +26,7 @@ This rule will not work as expected if [`strictNullChecks`](https://www.typescriptlang.org/tsconfig#strictNullChecks) is not enabled. | ||
Setting this option to `true` (the default) will cause the rule to ignore any ternary expressions that could be simplified by using the nullish coalescing operator. | ||
Setting this option to `true` will cause the rule to ignore any ternary expressions that could be simplified by using the nullish coalescing operator. This is set to `false` by default. | ||
Incorrect code for `ignoreTernaryTests: false`, and correct code for `ignoreTernaryTests: true`: | ||
```ts | ||
```ts option='{ "ignoreTernaryTests": false }' showPlaygroundButton | ||
const foo: any = 'bar'; | ||
@@ -46,3 +49,3 @@ foo !== undefined && foo !== null ? foo : 'a string'; | ||
```ts | ||
```ts option='{ "ignoreTernaryTests": false }' showPlaygroundButton | ||
const foo: any = 'bar'; | ||
@@ -65,3 +68,3 @@ foo ?? 'a string'; | ||
Setting this option to `true` (the default) will cause the rule to ignore any cases that are located within a conditional test. | ||
Setting this option to `true` will cause the rule to ignore any cases that are located within a conditional test. This is set to `false` by default. | ||
@@ -74,3 +77,3 @@ Generally expressions within conditional tests intentionally use the falsy fallthrough behavior of the logical or operator, meaning that fixing the operator to the nullish coalesce operator could cause bugs. | ||
```ts | ||
```ts option='{ "ignoreConditionalTests": false }' showPlaygroundButton | ||
declare const a: string | null; | ||
@@ -81,3 +84,6 @@ declare const b: string | null; | ||
} | ||
if ((a ||= b)) { | ||
} | ||
while (a || b) {} | ||
while ((a ||= b)) {} | ||
do {} while (a || b); | ||
@@ -90,3 +96,3 @@ for (let i = 0; a || b; i += 1) {} | ||
```ts | ||
```ts option='{ "ignoreConditionalTests": false }' showPlaygroundButton | ||
declare const a: string | null; | ||
@@ -97,3 +103,6 @@ declare const b: string | null; | ||
} | ||
if ((a ??= b)) { | ||
} | ||
while (a ?? b) {} | ||
while ((a ??= b)) {} | ||
do {} while (a ?? b); | ||
@@ -106,3 +115,3 @@ for (let i = 0; a ?? b; i += 1) {} | ||
Setting this option to `true` (the default) will cause the rule to ignore any logical or expressions that are part of a mixed logical expression (with `&&`). | ||
Setting this option to `true` will cause the rule to ignore any logical or expressions that are part of a mixed logical expression (with `&&`). This is set to `false` by default. | ||
@@ -115,3 +124,3 @@ Generally expressions within mixed logical expressions intentionally use the falsy fallthrough behavior of the logical or operator, meaning that fixing the operator to the nullish coalesce operator could cause bugs. | ||
```ts | ||
```ts option='{ "ignoreMixedLogicalExpressions": false }' showPlaygroundButton | ||
declare const a: string | null; | ||
@@ -123,2 +132,3 @@ declare const b: string | null; | ||
a || (b && c); | ||
a ||= b && c; | ||
(a && b) || c || d; | ||
@@ -131,3 +141,3 @@ a || (b && c) || d; | ||
```ts | ||
```ts option='{ "ignoreMixedLogicalExpressions": false }' showPlaygroundButton | ||
declare const a: string | null; | ||
@@ -139,2 +149,3 @@ declare const b: string | null; | ||
a ?? (b && c); | ||
a ??= b && c; | ||
(a && b) ?? c ?? d; | ||
@@ -147,2 +158,27 @@ a ?? (b && c) ?? d; | ||
### `ignorePrimitives` | ||
If you would like to ignore expressions containing operands of certain primitive types that can be falsy then you may pass an object containing a boolean value for each primitive: | ||
- `string: true`, ignores `null` or `undefined` unions with `string` (default: false). | ||
- `number: true`, ignores `null` or `undefined` unions with `number` (default: false). | ||
- `bigint: true`, ignores `null` or `undefined` unions with `bigint` (default: false). | ||
- `boolean: true`, ignores `null` or `undefined` unions with `boolean` (default: false). | ||
Incorrect code for `ignorePrimitives: { string: false }`, and correct code for `ignorePrimitives: { string: true }`: | ||
```ts option='{ "ignorePrimitives": { "string": true } }' showPlaygroundButton | ||
const foo: string | undefined = 'bar'; | ||
foo || 'a string'; | ||
``` | ||
Correct code for both `ignorePrimitives: { string: false }` and `ignorePrimitives: { string: true }`: | ||
```ts option='{ "ignorePrimitives": { "string": true } }' showPlaygroundButton | ||
const foo: string | undefined = 'bar'; | ||
foo ?? 'a string'; | ||
``` | ||
Also, if you would like to ignore all primitives types, you can set `ignorePrimitives: true`. It is equivalent to `ignorePrimitives: { string: true, number: true, bigint: true, boolean: true }`. | ||
## When Not To Use It | ||
@@ -149,0 +185,0 @@ |
@@ -60,9 +60,201 @@ --- | ||
:::note | ||
There are a few edge cases where this rule will false positive. Use your best judgement when evaluating reported errors. | ||
::: | ||
## Options | ||
In the context of the descriptions below a "loose boolean" operand is any operand that implicitly coerces the value to a boolean. | ||
Specifically the argument of the not operator (`!loose`) or a bare value in a logical expression (`loose && looser`). | ||
### `allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing` | ||
When this option is `true`, the rule will not provide an auto-fixer for cases where the return type of the expression would change. For example for the expression `!foo || foo.bar` the return type of the expression is `true | T`, however for the equivalent optional chain `foo?.bar` the return type of the expression is `undefined | T`. Thus changing the code from a logical expression to an optional chain expression has altered the type of the expression. | ||
In some cases this distinction _may_ matter - which is why these fixers are considered unsafe - they may break the build! For example in the following code: | ||
```ts option='{ "allowPotentiallyUnsafeFixesThatModifyTheReturnTypeIKnowWhatImDoing": true }' showPlaygroundButton | ||
declare const foo: { bar: boolean } | null | undefined; | ||
declare function acceptsBoolean(arg: boolean): void; | ||
// ✅ typechecks succesfully as the expression only returns `boolean` | ||
acceptsBoolean(foo != null && foo.bar); | ||
// ❌ typechecks UNSUCCESSFULLY as the expression returns `boolean | undefined` | ||
acceptsBoolean(foo?.bar); | ||
``` | ||
This style of code isn't super common - which means having this option set to `true` _should_ be safe in most codebases. However we default it to `false` due to its unsafe nature. We have provided this option for convenience because it increases the autofix cases covered by the rule. If you set option to `true` the onus is entirely on you and your team to ensure that each fix is correct and safe and that it does not break the build. | ||
When this option is `false` unsafe cases will have suggestion fixers provided instead of auto-fixers - meaning you can manually apply the fix using your IDE tooling. | ||
### `checkAny` | ||
When this option is `true` the rule will check operands that are typed as `any` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkAny: true` | ||
```ts option='{ "checkAny": true }' | ||
declare const thing: any; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkAny: false` | ||
```ts option='{ "checkAny": false }' | ||
declare const thing: any; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `checkUnknown` | ||
When this option is `true` the rule will check operands that are typed as `unknown` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkUnknown: true` | ||
```ts option='{ "checkUnknown": true }' | ||
declare const thing: unknown; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkUnknown: false` | ||
```ts option='{ "checkUnknown": false }' | ||
declare const thing: unknown; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `checkString` | ||
When this option is `true` the rule will check operands that are typed as `string` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkString: true` | ||
```ts option='{ "checkString": true }' | ||
declare const thing: string; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkString: false` | ||
```ts option='{ "checkString": false }' | ||
declare const thing: string; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `checkNumber` | ||
When this option is `true` the rule will check operands that are typed as `number` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkNumber: true` | ||
```ts option='{ "checkNumber": true }' | ||
declare const thing: number; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkNumber: false` | ||
```ts option='{ "checkNumber": false }' | ||
declare const thing: number; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `checkBoolean` | ||
When this option is `true` the rule will check operands that are typed as `boolean` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkBoolean: true` | ||
```ts option='{ "checkBoolean": true }' | ||
declare const thing: boolean; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkBoolean: false` | ||
```ts option='{ "checkBoolean": false }' | ||
declare const thing: boolean; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `checkBigInt` | ||
When this option is `true` the rule will check operands that are typed as `bigint` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `checkBigInt: true` | ||
```ts option='{ "checkBigInt": true }' | ||
declare const thing: bigint; | ||
thing && thing.toString(); | ||
``` | ||
#### ✅ Correct for `checkBigInt: false` | ||
```ts option='{ "checkBigInt": false }' | ||
declare const thing: bigint; | ||
thing && thing.toString(); | ||
``` | ||
<!--/tabs--> | ||
### `requireNullish` | ||
When this option is `true` the rule will skip operands that are not typed with `null` and/or `undefined` when inspecting "loose boolean" operands. | ||
<!--tabs--> | ||
#### ❌ Incorrect for `requireNullish: true` | ||
```ts option='{ "requireNullish": true }' | ||
declare const thing1: string | null; | ||
thing1 && thing1.toString(); | ||
``` | ||
#### ✅ Correct for `requireNullish: true` | ||
```ts option='{ "requireNullish": true }' | ||
declare const thing1: string | null; | ||
thing1?.toString(); | ||
declare const thing2: string; | ||
thing2 && thing2.toString(); | ||
``` | ||
<!--/tabs--> | ||
## When Not To Use It | ||
If you don't mind using more explicit `&&`s, you don't need this rule. | ||
If your project is not accurately typed, such as if it's in the process of being converted to TypeScript or is susceptible to [trade-offs in control flow analysis](https://github.com/Microsoft/TypeScript/issues/9998), it may be difficult to enable this rule for particularly non-type-safe areas of code. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -69,0 +261,0 @@ ## Further Reading |
@@ -132,2 +132,116 @@ --- | ||
### `allow` | ||
Some complex types cannot easily be made readonly, for example the `HTMLElement` type or the `JQueryStatic` type from `@types/jquery`. This option allows you to globally disable reporting of such types. | ||
Each item must be one of: | ||
- A type defined in a file (`{from: "file", name: "Foo", path: "src/foo-file.ts"}` with `path` being an optional path relative to the project root directory) | ||
- A type from the default library (`{from: "lib", name: "Foo"}`) | ||
- A type from a package (`{from: "package", name: "Foo", package: "foo-lib"}`, this also works for types defined in a typings package). | ||
Additionally, a type may be defined just as a simple string, which then matches the type independently of its origin. | ||
Examples of code for this rule with: | ||
```json | ||
{ | ||
"allow": [ | ||
"$", | ||
{ "source": "file", "name": "Foo" }, | ||
{ "source": "lib", "name": "HTMLElement" }, | ||
{ "from": "package", "name": "Bar", "package": "bar-lib" } | ||
] | ||
} | ||
``` | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts option='{"allow":["$",{"source":"file","name":"Foo"},{"source":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]}' | ||
interface ThisIsMutable { | ||
prop: string; | ||
} | ||
interface Wrapper { | ||
sub: ThisIsMutable; | ||
} | ||
interface WrapperWithOther { | ||
readonly sub: Foo; | ||
otherProp: string; | ||
} | ||
// Incorrect because ThisIsMutable is not readonly | ||
function fn1(arg: ThisIsMutable) {} | ||
// Incorrect because Wrapper.sub is not readonly | ||
function fn2(arg: Wrapper) {} | ||
// Incorrect because WrapperWithOther.otherProp is not readonly and not in the allowlist | ||
function fn3(arg: WrapperWithOther) {} | ||
``` | ||
```ts option='{"allow":["$",{"source":"file","name":"Foo"},{"source":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]}' | ||
import { Foo } from 'some-lib'; | ||
import { Bar } from 'incorrect-lib'; | ||
interface HTMLElement { | ||
prop: string; | ||
} | ||
// Incorrect because Foo is not a local type | ||
function fn1(arg: Foo) {} | ||
// Incorrect because HTMLElement is not from the default library | ||
function fn2(arg: HTMLElement) {} | ||
// Incorrect because Bar is not from "bar-lib" | ||
function fn3(arg: Bar) {} | ||
``` | ||
#### ✅ Correct | ||
```ts option='{"allow":["$",{"source":"file","name":"Foo"},{"source":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]}' | ||
interface Foo { | ||
prop: string; | ||
} | ||
interface Wrapper { | ||
readonly sub: Foo; | ||
readonly otherProp: string; | ||
} | ||
// Works because Foo is allowed | ||
function fn1(arg: Foo) {} | ||
// Works even when Foo is nested somewhere in the type, with other properties still being checked | ||
function fn2(arg: Wrapper) {} | ||
``` | ||
```ts option='{"allow":["$",{"source":"file","name":"Foo"},{"source":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]}' | ||
import { Bar } from 'bar-lib'; | ||
interface Foo { | ||
prop: string; | ||
} | ||
// Works because Foo is a local type | ||
function fn1(arg: Foo) {} | ||
// Works because HTMLElement is from the default library | ||
function fn2(arg: HTMLElement) {} | ||
// Works because Bar is from "bar-lib" | ||
function fn3(arg: Bar) {} | ||
``` | ||
```ts option='{"allow":["$",{"source":"file","name":"Foo"},{"source":"lib","name":"HTMLElement"},{"from":"package","name":"Bar","package":"bar-lib"}]}' | ||
import { Foo } from './foo'; | ||
// Works because Foo is still a local type - it has to be in the same package | ||
function fn(arg: Foo) {} | ||
``` | ||
### `checkParameterProperties` | ||
@@ -144,3 +258,3 @@ | ||
```ts | ||
```ts option='{ "checkParameterProperties": true }' | ||
class Foo { | ||
@@ -153,3 +267,3 @@ constructor(private paramProp: string[]) {} | ||
```ts | ||
```ts option='{ "checkParameterProperties": true }' | ||
class Foo { | ||
@@ -164,3 +278,3 @@ constructor(private paramProp: readonly string[]) {} | ||
```ts | ||
```ts option='{ "checkParameterProperties": false }' showPlaygroundButton | ||
class Foo { | ||
@@ -184,3 +298,3 @@ constructor( | ||
```ts | ||
```ts option='{ "ignoreInferredTypes": true }' | ||
import { acceptsCallback, CallbackOptions } from 'external-dependency'; | ||
@@ -194,3 +308,3 @@ | ||
```ts | ||
```ts option='{ "ignoreInferredTypes": true }' | ||
export interface CallbackOptions { | ||
@@ -209,3 +323,3 @@ prop: string; | ||
```ts | ||
```ts option='{ "ignoreInferredTypes": true }' | ||
import { acceptsCallback } from 'external-dependency'; | ||
@@ -219,3 +333,3 @@ | ||
```ts | ||
```ts option='{ "ignoreInferredTypes": true }' | ||
export interface CallbackOptions { | ||
@@ -242,3 +356,3 @@ prop: string; | ||
```ts | ||
```ts option='{ "treatMethodsAsReadonly": false }' | ||
type MyType = { | ||
@@ -253,3 +367,3 @@ readonly prop: string; | ||
```ts | ||
```ts option='{ "treatMethodsAsReadonly": false }' | ||
type MyType = Readonly<{ | ||
@@ -272,3 +386,3 @@ prop: string; | ||
```ts | ||
```ts option='{ "treatMethodsAsReadonly": true }' showPlaygroundButton | ||
type MyType = { | ||
@@ -280,1 +394,5 @@ readonly prop: string; | ||
``` | ||
## When Not To Use It | ||
If your project does not attempt to enforce strong immutability guarantees of parameters, you can avoid this rule. |
@@ -9,3 +9,3 @@ --- | ||
Member variables with the privacy `private` are never permitted to be modified outside of their declaring class. | ||
Private member variables (whether using the `private` modifier or private `#` fields) are never permitted to be modified outside of their declaring class. | ||
If that class never modifies their value, they may safely be marked as `readonly`. | ||
@@ -26,2 +26,3 @@ | ||
private onlyModifiedInConstructor: number; | ||
#neverModifiedPrivateField = 3; | ||
@@ -54,2 +55,9 @@ public constructor( | ||
} | ||
// This is modified later on by the class | ||
#modifiedLaterPrivateField = 'unchanged'; | ||
public mutatePrivateField() { | ||
this.#modifiedLaterPrivateField = 'mutated'; | ||
} | ||
} | ||
@@ -76,3 +84,3 @@ ``` | ||
```ts | ||
```ts option='{ "onlyInlineLambdas": true }' | ||
class Container { | ||
@@ -87,3 +95,3 @@ private onClick = () => { | ||
```ts | ||
```ts option='{ "onlyInlineLambdas": true }' | ||
class Container { | ||
@@ -93,1 +101,5 @@ private neverModifiedPrivate = 'unchanged'; | ||
``` | ||
## When Not To Use It | ||
If you aren't trying to enforce strong immutability guarantees, this rule may be too restrictive for your project. |
@@ -58,2 +58,4 @@ --- | ||
If you don't want to use typechecking in your linting, you can't use this rule. | ||
This rule can sometimes be difficult to work around when creating objects using a `.reduce`. | ||
See [[prefer-reduce-type-parameter] unfixable reporting #3440](https://github.com/typescript-eslint/typescript-eslint/issues/3440) for more details. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. |
@@ -57,2 +57,3 @@ --- | ||
If you don't mind that style, you can turn this rule off safely. | ||
If you don't mind which style of string checking is used, you can turn this rule off safely. | ||
However, keep in mind that inconsistent style can harm readability in a project. |
@@ -66,2 +66,3 @@ --- | ||
If you are compiling against multiple versions of TypeScript and using `@ts-ignore` to ignore version-specific type errors, this rule might get in your way. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -68,0 +69,0 @@ ## Further Reading |
@@ -60,1 +60,6 @@ --- | ||
``` | ||
## When Not To Use It | ||
This rule can be difficult to enable on projects that use APIs which require functions to always be `async`. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) along with filing issues on your dependencies for those specific situations instead of completely disabling this rule. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/quotes`](https://eslint.org/docs/rules/quotes) rule. | ||
It adds support for TypeScript features which allow quoted names, but not backtick quoted names. |
@@ -9,16 +9,53 @@ --- | ||
`@typescript-eslint/eslint-plugin` includes over 100 rules that detect best practice violations, bugs, and/or stylistic issues specifically for TypeScript code. | ||
See [Configs](/linting/configs) for how to enable recommended rules using configs. | ||
`@typescript-eslint/eslint-plugin` includes over 100 rules that detect best practice violations, bugs, and/or stylistic issues specifically for TypeScript code. All of our rules are listed below. | ||
## Supported Rules | ||
:::tip | ||
Instead of enabling rules one by one, we recommend using one of [our pre-defined configs](/linting/configs) to enable a large set of recommended rules. | ||
::: | ||
## Rules | ||
The rules are listed in alphabetical order. You can optionally filter them based on these categories: | ||
import RulesTable from "@site/src/components/RulesTable"; | ||
<RulesTable ruleset="supported-rules" /> | ||
<RulesTable /> | ||
## Filtering | ||
### Config Group (⚙️) | ||
"Config Group" refers to the [pre-defined config](/linting/configs) that includes the rule. Extending from a configuration preset allow for enabling a large set of recommended rules all at once. | ||
### Metadata | ||
- `🔧 fixable` refers to whether the rule contains an [ESLint `--fix` auto-fixer](https://eslint.org/docs/latest/use/command-line-interface#--fix). | ||
- `💡 has suggestions` refers to whether the rule contains an ESLint suggestion fixer. | ||
- Sometimes, it is not safe to automatically fix the code with an auto-fixer. But in these cases, we often have a good guess of what the correct fix should be, and we can provide it as a suggestion to the developer. | ||
- `💭 requires type information` refers to whether the rule requires [typed linting](/linting/typed-linting). | ||
- `🧱 extension rule` means that the rule is an extension of an [core ESLint rule](https://eslint.org/docs/latest/rules) (see [Extension Rules](#extension-rules)). | ||
- `📐 formatting rule` means that the rule has to do with formatting. | ||
- We [strongly recommend against using ESLint for formatting](/linting/troubleshooting/formatting). | ||
- Soon, formatting rules will be moved to the [ESLint stylistic plugin](https://eslint.style). | ||
- `💀 deprecated rule` means that the rule should no longer be used and will be removed from the plugin in a future version. | ||
## Extension Rules | ||
In some cases, ESLint provides a rule itself, but it doesn't support TypeScript syntax; either it crashes, or it ignores the syntax, or it falsely reports against it. | ||
In these cases, we create what we call an extension rule; a rule within our plugin that has the same functionality, but also supports TypeScript. | ||
Some core ESLint rules do not support TypeScript syntax: either they crash, ignore the syntax, or falsely report against it. | ||
In these cases, we create what we call an "extension rule": a rule within our plugin that has the same functionality, but also supports TypeScript. | ||
<RulesTable ruleset="extension-rules" /> | ||
Extension rules generally completely replace the base rule from ESLint core. | ||
If the base rule is enabled in a config you extend from, you'll need to disable the base rule: | ||
```js | ||
module.exports = { | ||
extends: ['eslint:recommended'], | ||
rules: { | ||
// Note: you must disable the base rule as it can report incorrect errors | ||
'no-unused-vars': 'off', | ||
'@typescript-eslint/no-unused-vars': 'error', | ||
}, | ||
}; | ||
``` | ||
[Search for `🧱 extension rule`s](?=extension#rules) in this page to see all extension rules. |
--- | ||
description: 'Require `Array#sort` calls to always provide a `compareFunction`.' | ||
description: 'Require `Array#sort` and `Array#toSorted` calls to always provide a `compareFunction`.' | ||
--- | ||
@@ -9,3 +9,3 @@ | ||
When called without a compare function, `Array#sort()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units [[ECMA specification](https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare)]. | ||
When called without a compare function, `Array#sort()` and `Array#toSorted()` converts all non-undefined array elements into strings and then compares said strings based off their UTF-16 code units [[ECMA specification](https://www.ecma-international.org/ecma-262/9.0/#sec-sortcompare)]. | ||
@@ -19,7 +19,7 @@ The result is that elements are sorted alphabetically, regardless of their type. | ||
This rule reports on any call to the `Array#sort()` method that doesn't provide a `compare` argument. | ||
This rule reports on any call to the sort methods that do not provide a `compare` argument. | ||
## Examples | ||
This rule aims to ensure all calls of the native `Array#sort` method provide a `compareFunction`, while ignoring calls to user-defined `sort` methods. | ||
This rule aims to ensure all calls of the native sort methods provide a `compareFunction`, while ignoring calls to user-defined methods. | ||
@@ -62,3 +62,3 @@ <!--tabs--> | ||
```ts | ||
```ts option='{ "ignoreStringArrays": true }' | ||
const one = 1; | ||
@@ -72,3 +72,3 @@ const two = 2; | ||
```ts | ||
```ts option='{ "ignoreStringArrays": true }' | ||
const one = '1'; | ||
@@ -82,2 +82,2 @@ const two = '2'; | ||
If you understand the language specification enough, and/or only ever sort arrays in a string-like manner, you can turn this rule off safely. | ||
If you intentionally want your arrays to be always sorted in a string-like manner, you can turn this rule off safely. |
@@ -9,7 +9,7 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/require-await`](https://eslint.org/docs/rules/require-await) rule. | ||
It uses type information to add support for `async` functions that return a `Promise`. | ||
## Examples | ||
Examples of **correct** code for this rule: | ||
@@ -24,3 +24,1 @@ | ||
``` | ||
## How to Use |
@@ -21,4 +21,4 @@ --- | ||
```ts | ||
var foo = '5.5' + 5; | ||
var foo = 1n + 1; | ||
let foo = '5.5' + 5; | ||
let foo = 1n + 1; | ||
``` | ||
@@ -29,4 +29,4 @@ | ||
```ts | ||
var foo = parseInt('5.5', 10) + 10; | ||
var foo = 1n + 1n; | ||
let foo = parseInt('5.5', 10) + 10; | ||
let foo = 1n + 1n; | ||
``` | ||
@@ -36,6 +36,41 @@ | ||
### `checkCompoundAssignments` | ||
:::caution | ||
We generally recommend against using these options, as they limit which varieties of incorrect `+` usage can be checked. | ||
This in turn severely limits the validation that the rule can do to ensure that resulting strings and numbers are correct. | ||
Examples of code for this rule with `{ checkCompoundAssignments: true }`: | ||
Safer alternatives to using the `allow*` options include: | ||
- Using variadic forms of logging APIs to avoid needing to `+` values. | ||
```ts | ||
// Remove this line | ||
console.log('The result is ' + true); | ||
// Add this line | ||
console.log('The result is', true); | ||
``` | ||
- Using `.toFixed()` to coerce numbers to well-formed string representations: | ||
```ts | ||
const number = 1.123456789; | ||
const result = 'The number is ' + number.toFixed(2); | ||
// result === 'The number is 1.12' | ||
``` | ||
- Calling `.toString()` on other types to mark explicit and intentional string coercion: | ||
```ts | ||
const arg = '11'; | ||
const regex = /[0-9]/; | ||
const result = | ||
'The result of ' + | ||
regex.toString() + | ||
'.test("' + | ||
arg + | ||
'") is ' + | ||
regex.test(arg).toString(); | ||
// result === 'The result of /[0-9]/.test("11") is true' | ||
``` | ||
::: | ||
### `allowAny` | ||
Examples of code for this rule with `{ allowAny: true }`: | ||
<!--tabs--> | ||
@@ -45,28 +80,62 @@ | ||
```ts | ||
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/ | ||
```ts option='{ "allowAny": true }' | ||
let fn = (a: number, b: []) => a + b; | ||
let fn = (a: string, b: []) => a + b; | ||
``` | ||
let foo: string | undefined; | ||
foo += 'some data'; | ||
#### ✅ Correct | ||
let bar: string = ''; | ||
bar += 0; | ||
```ts option='{ "allowAny": true }' | ||
let fn = (a: number, b: any) => a + b; | ||
let fn = (a: string, b: any) => a + b; | ||
``` | ||
### `allowBoolean` | ||
Examples of code for this rule with `{ allowBoolean: true }`: | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts option='{ "allowBoolean": true }' | ||
let fn = (a: number, b: unknown) => a + b; | ||
let fn = (a: string, b: unknown) => a + b; | ||
``` | ||
#### ✅ Correct | ||
```ts | ||
/*eslint @typescript-eslint/restrict-plus-operands: ["error", { "checkCompoundAssignments": true }]*/ | ||
```ts option='{ "allowBoolean": true }' | ||
let fn = (a: number, b: boolean) => a + b; | ||
let fn = (a: string, b: boolean) => a + b; | ||
``` | ||
let foo: number = 0; | ||
foo += 1; | ||
### `allowNullish` | ||
let bar = ''; | ||
bar += 'test'; | ||
Examples of code for this rule with `{ allowNullish: true }`: | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts option='{ "allowNullish": true }' | ||
let fn = (a: number, b: unknown) => a + b; | ||
let fn = (a: number, b: never) => a + b; | ||
let fn = (a: string, b: unknown) => a + b; | ||
let fn = (a: string, b: never) => a + b; | ||
``` | ||
### `allowAny` | ||
#### ✅ Correct | ||
Examples of code for this rule with `{ allowAny: true }`: | ||
```ts option='{ "allowNullish": true }' | ||
let fn = (a: number, b: undefined) => a + b; | ||
let fn = (a: number, b: null) => a + b; | ||
let fn = (a: string, b: undefined) => a + b; | ||
let fn = (a: string, b: null) => a + b; | ||
``` | ||
### `allowNumberAndString` | ||
Examples of code for this rule with `{ allowNumberAndString: true }`: | ||
<!--tabs--> | ||
@@ -76,6 +145,5 @@ | ||
```ts | ||
var fn = (a: any, b: boolean) => a + b; | ||
var fn = (a: any, b: []) => a + b; | ||
var fn = (a: any, b: {}) => a + b; | ||
```ts option='{ "allowNumberAndString": true }' | ||
let fn = (a: number, b: unknown) => a + b; | ||
let fn = (a: number, b: never) => a + b; | ||
``` | ||
@@ -85,12 +153,54 @@ | ||
```ts | ||
var fn = (a: any, b: any) => a + b; | ||
var fn = (a: any, b: string) => a + b; | ||
var fn = (a: any, b: bigint) => a + b; | ||
var fn = (a: any, b: number) => a + b; | ||
```ts option='{ "allowNumberAndString": true }' | ||
let fn = (a: number, b: string) => a + b; | ||
let fn = (a: number, b: number | string) => a + b; | ||
``` | ||
### `allowRegExp` | ||
Examples of code for this rule with `{ allowRegExp: true }`: | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts option='{ "allowRegExp": true }' | ||
let fn = (a: number, b: RegExp) => a + b; | ||
``` | ||
#### ✅ Correct | ||
```ts option='{ "allowRegExp": true }' | ||
let fn = (a: string, b: RegExp) => a + b; | ||
``` | ||
### `skipCompoundAssignments` | ||
Examples of code for this rule with `{ skipCompoundAssignments: false }`: | ||
<!--tabs--> | ||
#### ❌ Incorrect | ||
```ts option='{ "skipCompoundAssignments": true }' | ||
let foo: string | undefined; | ||
foo += 'some data'; | ||
let bar: string = ''; | ||
bar += 0; | ||
``` | ||
#### ✅ Correct | ||
```ts option='{ "skipCompoundAssignments": true }' | ||
let foo: number = 0; | ||
foo += 1; | ||
let bar = ''; | ||
bar += 'test'; | ||
``` | ||
## When Not To Use It | ||
If you don't mind `"[object Object]"` in your strings, then you will not need this rule. | ||
If you don't mind a risk of `"[object Object]"` or incorrect type coercions in your values, then you will not need this rule. | ||
@@ -97,0 +207,0 @@ ## Related To |
@@ -9,6 +9,16 @@ --- | ||
JavaScript will call `toString()` on an object when it is converted to a string, such as when `+` adding to a string or in `${}` template literals. | ||
The default Object `.toString()` returns `"[object Object]"`, which is often not what was intended. | ||
This rule reports on values used in a template literal string that aren't primitives and don't define a more useful `.toString()` method. | ||
JavaScript automatically [converts an object to a string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion) in a string context, such as when concatenating it with a string using `+` or embedding it in a template literal using `${}`. | ||
The default `toString()` method of objects returns `"[object Object]"`, which is often not what was intended. | ||
This rule reports on values used in a template literal string that aren't strings, numbers, or BigInts, optionally allowing other data types that provide useful stringification results. | ||
:::note | ||
This rule intentionally does not allow objects with a custom `toString()` method to be used in template literals, because the stringification result may not be user-friendly. | ||
For example, arrays have a custom [`toString()`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/toString) method, which only calls `join()` internally, which joins the array elements with commas. This means that (1) array elements are not necessarily stringified to useful results (2) the commas don't have spaces after them, making the result not user-friendly. The best way to format arrays is to use [`Intl.ListFormat`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat), which even supports adding the "and" conjunction where necessary. | ||
You must explicitly call `object.toString()` if you want to use this object in a template literal. | ||
The [`no-base-to-string`](./no-base-to-string.md) rule can be used to guard this case against producing `"[object Object]"` by accident. | ||
::: | ||
## Examples | ||
@@ -45,3 +55,3 @@ | ||
```ts | ||
```ts option='{ "allowNumber": true }' showPlaygroundButton | ||
const arg = 123; | ||
@@ -52,2 +62,4 @@ const msg1 = `arg = ${arg}`; | ||
This option controls both numbers and BigInts. | ||
### `allowBoolean` | ||
@@ -57,3 +69,3 @@ | ||
```ts | ||
```ts option='{ "allowBoolean": true }' showPlaygroundButton | ||
const arg = true; | ||
@@ -68,3 +80,3 @@ const msg1 = `arg = ${arg}`; | ||
```ts | ||
```ts option='{ "allowAny": true }' showPlaygroundButton | ||
const user = JSON.parse('{ "name": "foo" }'); | ||
@@ -79,3 +91,3 @@ const msg1 = `arg = ${user.name}`; | ||
```ts | ||
```ts option='{ "allowNullish": true }' showPlaygroundButton | ||
const arg = condition ? 'ok' : null; | ||
@@ -89,3 +101,3 @@ const msg1 = `arg = ${arg}`; | ||
```ts | ||
```ts option='{ "allowRegExp": true }' showPlaygroundButton | ||
const arg = new RegExp('foo'); | ||
@@ -95,3 +107,3 @@ const msg1 = `arg = ${arg}`; | ||
```ts | ||
```ts option='{ "allowRegExp": true }' showPlaygroundButton | ||
const arg = /foo/; | ||
@@ -105,3 +117,3 @@ const msg1 = `arg = ${arg}`; | ||
```ts | ||
```ts option='{ "allowNever": true }' showPlaygroundButton | ||
const arg = 'something'; | ||
@@ -111,2 +123,6 @@ const msg1 = typeof arg === 'string' ? arg : `arg = ${arg}`; | ||
## When Not To Use It | ||
If you're not worried about incorrectly stringifying non-string values in template literals, then you likely don't need this rule. | ||
## Related To | ||
@@ -113,0 +129,0 @@ |
@@ -11,7 +11,7 @@ --- | ||
## Examples | ||
This rule builds on top of the [`eslint/no-return-await`](https://eslint.org/docs/rules/no-return-await) rule. | ||
It expands upon the base rule to add support for optionally requiring `return await` in certain cases. | ||
The extended rule is named `return-await` instead of `no-return-await` because the extended rule can enforce the positive or the negative. Additionally, while the core rule is now deprecated, the extended rule is still useful in many contexts. | ||
## Options | ||
@@ -41,3 +41,3 @@ | ||
```ts | ||
```ts option='"in-try-catch"' | ||
async function invalidInTryCatch1() { | ||
@@ -88,3 +88,3 @@ try { | ||
```ts | ||
```ts option='"in-try-catch"' | ||
async function validInTryCatch1() { | ||
@@ -143,3 +143,3 @@ try { | ||
```ts | ||
```ts option='"always"' | ||
async function invalidAlways1() { | ||
@@ -162,3 +162,3 @@ try { | ||
```ts | ||
```ts option='"always"' | ||
async function validAlways1() { | ||
@@ -189,3 +189,3 @@ try { | ||
```ts | ||
```ts option='"never"' | ||
async function invalidNever1() { | ||
@@ -208,3 +208,3 @@ try { | ||
```ts | ||
```ts option='"never"' | ||
async function validNever1() { | ||
@@ -211,0 +211,0 @@ try { |
@@ -9,6 +9,2 @@ --- | ||
This rule enforces consistent use of semicolons after statements. | ||
## Examples | ||
This rule extends the base [`eslint/semi`](https://eslint.org/docs/rules/semi) rule. | ||
@@ -15,0 +11,0 @@ It adds support for TypeScript features that require semicolons. |
@@ -63,4 +63,2 @@ --- | ||
type T4 = | ||
| any | ||
| string | ||
| A | ||
@@ -70,8 +68,10 @@ | B | ||
| string[] | ||
| any | ||
| string | ||
| readonly number[] | ||
| readonly string[] | ||
| 'a' | ||
| 'b' | ||
| 'a' | ||
| 'b' | ||
| 'b' | ||
| (() => string) | ||
@@ -104,1 +104,7 @@ | (() => void) | ||
- `nullish` - `null` and `undefined` | ||
## When Not To Use It | ||
This rule is purely a stylistic rule for maintaining consistency in your project. | ||
You can turn it off if you don't want to keep a consistent, predictable order for intersection and union types. | ||
However, keep in mind that inconsistent style can harm readability in a project. |
@@ -9,4 +9,2 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/space-before-blocks`](https://eslint.org/docs/rules/space-before-blocks) rule. | ||
@@ -13,0 +11,0 @@ It adds support for interfaces and enums. |
@@ -9,5 +9,3 @@ --- | ||
## Examples | ||
This rule extends the base [`eslint/space-before-function-paren`](https://eslint.org/docs/rules/space-before-function-paren) rule. | ||
It adds support for generic type parameters on function calls. |
@@ -181,4 +181,11 @@ --- | ||
## When Not To Use It | ||
If your project isn't likely to experience bugs from falsy non-boolean values being used in logical conditions, you can skip enabling this rule. | ||
Otherwise, this rule can be quite strict around requiring exact comparisons in logical checks. | ||
If you prefer more succinct checks over more precise boolean logic, this rule might not be for you. | ||
## Related To | ||
- [no-unnecessary-condition](./no-unnecessary-condition.md) - Similar rule which reports always-truthy and always-falsy values in conditions |
--- | ||
description: 'Require switch-case statements to be exhaustive with union type.' | ||
description: 'Require switch-case statements to be exhaustive.' | ||
--- | ||
@@ -9,9 +9,15 @@ | ||
When working with union types in TypeScript, it's common to want to write a `switch` statement intended to contain a `case` for each constituent (possible type in the union). | ||
However, if the union type changes, it's easy to forget to modify the cases to account for any new types. | ||
When working with union types or enums in TypeScript, it's common to want to write a `switch` statement intended to contain a `case` for each constituent (possible type in the union or the enum). | ||
However, if the union type or the enum changes, it's easy to forget to modify the cases to account for any new types. | ||
This rule reports when a `switch` statement over a value typed as a union of literals is missing a case for any of those literal types and does not have a `default` clause. | ||
This rule reports when a `switch` statement over a value typed as a union of literals or as an enum is missing a case for any of those literal types and does not have a `default` clause. | ||
There is also an option to check the exhaustiveness of switches on non-union types by requiring a default clause. | ||
## Examples | ||
When the switch doesn't have exhaustive cases, either filling them all out or adding a default will correct the rule's complaint. | ||
Here are some examples of code working with a union of literals: | ||
<!--tabs--> | ||
@@ -31,3 +37,3 @@ | ||
const day = 'Monday' as Day; | ||
declare const day: Day; | ||
let result = 0; | ||
@@ -54,3 +60,3 @@ | ||
const day = 'Monday' as Day; | ||
declare const day: Day; | ||
let result = 0; | ||
@@ -95,3 +101,3 @@ | ||
const day = 'Monday' as Day; | ||
declare const day: Day; | ||
let result = 0; | ||
@@ -108,4 +114,99 @@ | ||
<!--/tabs--> | ||
Likewise, here are some examples of code working with an enum: | ||
<!--tabs--> | ||
### ❌ Incorrect | ||
```ts | ||
enum Fruit { | ||
Apple, | ||
Banana, | ||
Cherry, | ||
} | ||
declare const fruit: Fruit; | ||
switch (fruit) { | ||
case Fruit.Apple: | ||
console.log('an apple'); | ||
break; | ||
} | ||
``` | ||
### ✅ Correct | ||
```ts | ||
enum Fruit { | ||
Apple, | ||
Banana, | ||
Cherry, | ||
} | ||
declare const fruit: Fruit; | ||
switch (fruit) { | ||
case Fruit.Apple: | ||
console.log('an apple'); | ||
break; | ||
case Fruit.Banana: | ||
console.log('a banana'); | ||
break; | ||
case Fruit.Cherry: | ||
console.log('a cherry'); | ||
break; | ||
} | ||
``` | ||
### ✅ Correct | ||
```ts | ||
enum Fruit { | ||
Apple, | ||
Banana, | ||
Cherry, | ||
} | ||
declare const fruit: Fruit; | ||
switch (fruit) { | ||
case Fruit.Apple: | ||
console.log('an apple'); | ||
break; | ||
default: | ||
console.log('a fruit'); | ||
break; | ||
} | ||
``` | ||
<!--/tabs--> | ||
## Options | ||
### `requireDefaultForNonUnion` | ||
Examples of additional **incorrect** code for this rule with `{ requireDefaultForNonUnion: true }`: | ||
```ts option='{ "requireDefaultForNonUnion": true }' showPlaygroundButton | ||
const value: number = Math.floor(Math.random() * 3); | ||
switch (value) { | ||
case 0: | ||
return 0; | ||
case 1: | ||
return 1; | ||
} | ||
``` | ||
Since `value` is a non-union type it requires the switch case to have a default clause only with `requireDefaultForNonUnion` enabled. | ||
<!--/tabs--> | ||
## When Not To Use It | ||
If you don't frequently `switch` over union types with many parts, or intentionally wish to leave out some parts. | ||
If you don't frequently `switch` over union types or enums with many parts, or intentionally wish to leave out some parts, this rule may not be for you. |
@@ -0,4 +1,8 @@ | ||
--- | ||
description: '<Description from rule metadata here>' | ||
--- | ||
> 🛑 This file is source code, not the primary documentation location! 🛑 | ||
> | ||
> See **https://typescript-eslint.io/rules/your-rule-name** for documentation. | ||
> See **https://typescript-eslint.io/rules/RULE_NAME_REPLACEME** for documentation. | ||
@@ -5,0 +9,0 @@ ## Examples |
@@ -13,4 +13,2 @@ --- | ||
## Examples | ||
## Options | ||
@@ -20,3 +18,3 @@ | ||
```ts | ||
```ts option='{ "path": "never", "types": "never", "lib": "never" }' showPlaygroundButton | ||
/// <reference path="foo" /> | ||
@@ -29,3 +27,3 @@ /// <reference types="bar" /> | ||
```ts | ||
```ts option='{ "types": "prefer-import" }' showPlaygroundButton | ||
/// <reference types="foo" /> | ||
@@ -35,3 +33,3 @@ import * as foo from 'foo'; | ||
```ts | ||
```ts option='{ "types": "prefer-import" }' showPlaygroundButton | ||
/// <reference types="foo" /> | ||
@@ -43,3 +41,3 @@ import foo = require('foo'); | ||
```ts | ||
```ts option='{ "path": "always", "types": "always", "lib": "always" }' showPlaygroundButton | ||
/// <reference path="foo" /> | ||
@@ -52,13 +50,16 @@ /// <reference types="bar" /> | ||
```ts | ||
```ts option='{ "types": "prefer-import" }' showPlaygroundButton | ||
import * as foo from 'foo'; | ||
``` | ||
```ts | ||
```ts option='{ "types": "prefer-import" }' showPlaygroundButton | ||
import foo = require('foo'); | ||
``` | ||
## When To Use It | ||
## When Not 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. | ||
Most modern TypeScript projects generally use `import` statements to bring in types. | ||
It's rare to need a `///` triple-slash reference outside of auto-generated code. | ||
If your project is a rare one with one of those use cases, this rule might not be for you. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
@@ -65,0 +66,0 @@ ## When Not To Use It |
@@ -42,6 +42,2 @@ --- | ||
## Options | ||
Examples of code for this rule with no options at all: | ||
<!--tabs--> | ||
@@ -93,5 +89,9 @@ | ||
## Options | ||
### after | ||
Examples of code for this rule with `{ "before": false, "after": true }`: | ||
```json | ||
{ "before": false, "after": true } | ||
``` | ||
@@ -103,3 +103,3 @@ <!--tabs--> | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{ "before": false, "after": true }' | ||
let foo:string = "bar"; | ||
@@ -133,3 +133,3 @@ let foo :string = "bar"; | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{ "before": false, "after": true }' | ||
let foo: string = "bar"; | ||
@@ -148,3 +148,5 @@ | ||
Examples of code for this rule with `{ "before": true, "after": true }` options: | ||
```json | ||
{ "before": true, "after": true } | ||
``` | ||
@@ -156,3 +158,3 @@ <!--tabs--> | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{ "before": true, "after": true }' | ||
let foo: string = "bar"; | ||
@@ -186,3 +188,3 @@ let foo:string = "bar"; | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{ "before": true, "after": true }' | ||
let foo : string = "bar"; | ||
@@ -201,3 +203,9 @@ | ||
Examples of code for this rule with `{ "before": false, "after": false, overrides: { colon: { before: true, after: true }} }` options: | ||
```json | ||
{ | ||
"before": false, | ||
"after": false, | ||
"overrides": { "colon": { "before": true, "after": true } } | ||
} | ||
``` | ||
@@ -209,3 +217,3 @@ <!--tabs--> | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{"before":false,"after":false,"overrides":{"colon":{"before":true,"after":true}}}' | ||
let foo: string = "bar"; | ||
@@ -239,3 +247,3 @@ let foo:string = "bar"; | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{"before":false,"after":false,"overrides":{"colon":{"before":true,"after":true}}}' | ||
let foo : string = "bar"; | ||
@@ -258,3 +266,9 @@ | ||
Examples of code for this rule with `{ "before": false, "after": false, overrides: { arrow: { before: true, after: true }} }` options: | ||
```json | ||
{ | ||
"before": false, | ||
"after": false, | ||
"overrides": { "arrow": { "before": true, "after": true } } | ||
} | ||
``` | ||
@@ -266,3 +280,3 @@ <!--tabs--> | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{"before":false,"after":false,"overrides":{"arrow":{"before":true,"after":true}}}' | ||
let foo: string = "bar"; | ||
@@ -296,3 +310,3 @@ let foo : string = "bar"; | ||
<!-- prettier-ignore --> | ||
```ts | ||
```ts option='{"before":false,"after":false,"overrides":{"arrow":{"before":true,"after":true}}}' | ||
let foo:string = "bar"; | ||
@@ -299,0 +313,0 @@ |
@@ -70,3 +70,3 @@ --- | ||
```ts | ||
```ts option='{ "arrayDestructuring": true }' | ||
const [a] = [1]; | ||
@@ -78,3 +78,3 @@ const [b, c] = [1, 2]; | ||
```ts | ||
```ts option='{ "arrayDestructuring": true }' | ||
const [a]: number[] = [1]; | ||
@@ -98,3 +98,3 @@ const [b]: [number] = [2]; | ||
```ts | ||
```ts option='{ "arrowParameter": true }' | ||
const logsSize = size => console.log(size); | ||
@@ -111,3 +111,3 @@ | ||
```ts | ||
```ts option='{ "arrowParameter": true }' | ||
const logsSize = (size: number) => console.log(size); | ||
@@ -132,3 +132,3 @@ | ||
```ts | ||
```ts option='{ "memberVariableDeclaration": true }' | ||
class ContainsText { | ||
@@ -142,3 +142,3 @@ delayedText; | ||
```ts | ||
```ts option='{ "memberVariableDeclaration": true }' | ||
class ContainsText { | ||
@@ -160,3 +160,3 @@ delayedText: string; | ||
```ts | ||
```ts option='{ "objectDestructuring": true }' | ||
const { length } = 'text'; | ||
@@ -168,3 +168,3 @@ const [b, c] = Math.random() ? [1, 2] : [3, 4]; | ||
```ts | ||
```ts option='{ "objectDestructuring": true }' | ||
const { length }: { length: number } = 'text'; | ||
@@ -187,3 +187,3 @@ const [b, c]: [number, number] = Math.random() ? [1, 2] : [3, 4]; | ||
```ts | ||
```ts option='{ "parameter": true }' | ||
function logsSize(size): void { | ||
@@ -216,3 +216,3 @@ console.log(size); | ||
```ts | ||
```ts option='{ "parameter": true }' | ||
function logsSize(size: number): void { | ||
@@ -253,3 +253,3 @@ console.log(size); | ||
```ts | ||
```ts option='{ "propertyDeclaration": true }' | ||
type Members = { | ||
@@ -263,3 +263,3 @@ member; | ||
```ts | ||
```ts option='{ "propertyDeclaration": true }' | ||
type Members = { | ||
@@ -281,3 +281,3 @@ member: boolean; | ||
```ts | ||
```ts option='{ "variableDeclaration": true }' | ||
const text = 'text'; | ||
@@ -290,3 +290,3 @@ let initialText = 'text'; | ||
```ts | ||
```ts option='{ "variableDeclaration": true }' | ||
const text: string = 'text'; | ||
@@ -307,3 +307,3 @@ let initialText: string = 'text'; | ||
```ts | ||
```ts option='{ "variableDeclaration": true, "variableDeclarationIgnoreFunction": true }' | ||
const text = 'text'; | ||
@@ -314,3 +314,3 @@ ``` | ||
```ts | ||
```ts option='{ "variableDeclaration": true, "variableDeclarationIgnoreFunction": true }' | ||
const a = (): void => {}; | ||
@@ -317,0 +317,0 @@ const b = function (): void => {}; |
@@ -86,3 +86,3 @@ --- | ||
```ts | ||
```ts option='{ "ignoreStatic": true }' showPlaygroundButton | ||
class OtherClass { | ||
@@ -102,4 +102,6 @@ static log() { | ||
If your code intentionally waits to bind methods after use, such as by passing a `scope: this` along with the method, you can disable this rule. | ||
If your project dynamically changes `this` scopes around in a way TypeScript has difficulties modeling, this rule may not be viable to use. | ||
One likely difficult pattern is if your code intentionally waits to bind methods after use, such as by passing a `scope: this` along with the method. | ||
You might consider using [ESLint disable comments](https://eslint.org/docs/latest/use/configure/rules#using-configuration-comments-1) for those specific situations instead of completely disabling this rule. | ||
If you're wanting to use `toBeCalled` and similar matches in `jest` tests, you can disable this rule for your test files in favor of [`eslint-plugin-jest`'s version of this rule](https://github.com/jest-community/eslint-plugin-jest/blob/main/docs/rules/unbound-method.md). |
@@ -58,3 +58,3 @@ --- | ||
```ts | ||
```ts option='{ "ignoreDifferentlyNamedParameters": true }' | ||
function f(a: number): void; | ||
@@ -66,3 +66,3 @@ function f(a: string): void; | ||
```ts | ||
```ts option='{ "ignoreDifferentlyNamedParameters": true }' | ||
function f(a: number): void; | ||
@@ -72,2 +72,9 @@ function f(b: string): void; | ||
## Options | ||
## When Not To Use It | ||
This is purely a stylistic rule to help with readability of function signature overloads. | ||
You can turn it off if you don't want to consistently keep them next to each other and unified. | ||
## Related To | ||
- [`adjacent-overload-signatures`](./adjacent-overload-signatures.md) |
@@ -1,4 +0,9 @@ | ||
import type { TSESLint } from '@typescript-eslint/utils'; | ||
import type { ClassicConfig } from '@typescript-eslint/utils/ts-eslint'; | ||
export const rules: Record<string, TSESLint.RuleModule<string, unknown[]>>; | ||
export const configs: Record<string, TSESLint.Linter.Config>; | ||
import type rules from './rules'; | ||
declare const cjsExport: { | ||
configs: Record<string, ClassicConfig.Config>; | ||
rules: typeof rules; | ||
}; | ||
export = cjsExport; |
{ | ||
"name": "@typescript-eslint/eslint-plugin", | ||
"version": "5.57.0", | ||
"version": "6.15.0", | ||
"description": "TypeScript plugin for ESLint", | ||
"keywords": [ | ||
"eslint", | ||
"eslintplugin", | ||
"eslint-plugin", | ||
"typescript" | ||
], | ||
"engines": { | ||
"node": "^12.22.0 || ^14.17.0 || >=16.0.0" | ||
}, | ||
"files": [ | ||
@@ -18,2 +9,3 @@ "dist", | ||
"index.d.ts", | ||
"rules.d.ts", | ||
"package.json", | ||
@@ -23,2 +15,17 @@ "README.md", | ||
], | ||
"type": "commonjs", | ||
"exports": { | ||
".": { | ||
"types": "./index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"./package.json": "./package.json", | ||
"./use-at-your-own-risk/rules": { | ||
"types": "./rules.d.ts", | ||
"default": "./dist/rules/index.js" | ||
} | ||
}, | ||
"engines": { | ||
"node": "^16.0.0 || >=18.0.0" | ||
}, | ||
"repository": { | ||
@@ -33,4 +40,8 @@ "type": "git", | ||
"license": "MIT", | ||
"main": "dist/index.js", | ||
"types": "index.d.ts", | ||
"keywords": [ | ||
"eslint", | ||
"eslintplugin", | ||
"eslint-plugin", | ||
"typescript" | ||
], | ||
"scripts": { | ||
@@ -43,39 +54,47 @@ "build": "tsc -b tsconfig.build.json", | ||
"format": "prettier --write \"./**/*.{ts,mts,cts,tsx,js,mjs,cjs,jsx,json,md,css}\" --ignore-path ../../.prettierignore", | ||
"generate:breaking-changes": "yarn tsx tools/generate-breaking-changes.ts", | ||
"generate:breaking-changes": "yarn tsx tools/generate-breaking-changes.mts", | ||
"generate:configs": "yarn tsx tools/generate-configs.ts", | ||
"lint": "nx lint", | ||
"test": "jest --coverage", | ||
"lint": "npx nx lint", | ||
"test": "jest --coverage --logHeapUsage", | ||
"test-single": "jest --no-coverage", | ||
"typecheck": "tsc -p tsconfig.json --noEmit" | ||
}, | ||
"dependencies": { | ||
"@eslint-community/regexpp": "^4.4.0", | ||
"@typescript-eslint/scope-manager": "5.57.0", | ||
"@typescript-eslint/type-utils": "5.57.0", | ||
"@typescript-eslint/utils": "5.57.0", | ||
"@eslint-community/regexpp": "^4.5.1", | ||
"@typescript-eslint/scope-manager": "6.15.0", | ||
"@typescript-eslint/type-utils": "6.15.0", | ||
"@typescript-eslint/utils": "6.15.0", | ||
"@typescript-eslint/visitor-keys": "6.15.0", | ||
"debug": "^4.3.4", | ||
"grapheme-splitter": "^1.0.4", | ||
"ignore": "^5.2.0", | ||
"natural-compare-lite": "^1.4.0", | ||
"semver": "^7.3.7", | ||
"tsutils": "^3.21.0" | ||
"graphemer": "^1.4.0", | ||
"ignore": "^5.2.4", | ||
"natural-compare": "^1.4.0", | ||
"semver": "^7.5.4", | ||
"ts-api-utils": "^1.0.1" | ||
}, | ||
"devDependencies": { | ||
"@prettier/sync": "*", | ||
"@types/debug": "*", | ||
"@types/json-schema": "*", | ||
"@types/marked": "*", | ||
"@types/natural-compare-lite": "^1.4.0", | ||
"@types/prettier": "*", | ||
"chalk": "^5.0.1", | ||
"cross-fetch": "^3.1.5", | ||
"@types/natural-compare": "*", | ||
"@typescript-eslint/rule-schema-to-typescript-types": "6.15.0", | ||
"@typescript-eslint/rule-tester": "6.15.0", | ||
"ajv": "^6.12.6", | ||
"chalk": "^5.3.0", | ||
"cross-fetch": "*", | ||
"grapheme-splitter": "^1.0.4", | ||
"jest": "29.7.0", | ||
"jest-specific-snapshot": "^8.0.0", | ||
"json-schema": "*", | ||
"markdown-table": "^3.0.2", | ||
"marked": "^4.0.15", | ||
"prettier": "*", | ||
"markdown-table": "^3.0.3", | ||
"marked": "^5.1.1", | ||
"prettier": "^3.0.3", | ||
"rimraf": "*", | ||
"title-case": "^3.0.3", | ||
"tsx": "*", | ||
"typescript": "*" | ||
}, | ||
"peerDependencies": { | ||
"@typescript-eslint/parser": "^5.0.0", | ||
"eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" | ||
"@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", | ||
"eslint": "^7.0.0 || ^8.0.0" | ||
}, | ||
@@ -91,3 +110,3 @@ "peerDependenciesMeta": { | ||
}, | ||
"gitHead": "69f827c81bfe29ea85b0794b9856c2d66539aa2c" | ||
"gitHead": "6128a02cb15d500fe22fe265c83e4d7a73ae52c3" | ||
} |
@@ -11,1 +11,3 @@ # `@typescript-eslint/eslint-plugin` | ||
> See https://typescript-eslint.io for general documentation on typescript-eslint, the tooling that allows you to run ESLint and Prettier on TypeScript code. | ||
<!-- Local path for docs: docs/packages/ESLint_Plugin.mdx --> |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
2530623
508
30145
13
13
20
+ Addedgraphemer@^1.4.0
+ Addednatural-compare@^1.4.0
+ Addedts-api-utils@^1.0.1
+ Added@typescript-eslint/parser@6.21.0(transitive)
+ Added@typescript-eslint/scope-manager@6.15.06.21.0(transitive)
+ Added@typescript-eslint/type-utils@6.15.0(transitive)
+ Added@typescript-eslint/types@6.15.06.21.0(transitive)
+ Added@typescript-eslint/typescript-estree@6.15.06.21.0(transitive)
+ Added@typescript-eslint/utils@6.15.0(transitive)
+ Added@typescript-eslint/visitor-keys@6.15.06.21.0(transitive)
+ Addedbrace-expansion@2.0.1(transitive)
+ Addedminimatch@9.0.3(transitive)
+ Addedts-api-utils@1.3.0(transitive)
- Removedgrapheme-splitter@^1.0.4
- Removednatural-compare-lite@^1.4.0
- Removedtsutils@^3.21.0
- Removed@typescript-eslint/parser@5.62.0(transitive)
- Removed@typescript-eslint/scope-manager@5.57.05.62.0(transitive)
- Removed@typescript-eslint/type-utils@5.57.0(transitive)
- Removed@typescript-eslint/types@5.57.05.62.0(transitive)
- Removed@typescript-eslint/typescript-estree@5.57.05.62.0(transitive)
- Removed@typescript-eslint/utils@5.57.0(transitive)
- Removed@typescript-eslint/visitor-keys@5.57.05.62.0(transitive)
- Removedeslint-scope@5.1.1(transitive)
- Removedestraverse@4.3.0(transitive)
- Removedgrapheme-splitter@1.0.4(transitive)
- Removednatural-compare-lite@1.4.0(transitive)
- Removedtslib@1.14.1(transitive)
- Removedtsutils@3.21.0(transitive)
Updatedignore@^5.2.4
Updatedsemver@^7.5.4