@typescript-eslint/eslint-plugin 8.45.1-alpha.1 → 8.45.1-alpha.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -785,7 +785,7 @@ declare const _default: {
785
785
  'no-unsafe-declaration-merging': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeMerging", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
786
786
  'no-unsafe-enum-comparison': import("@typescript-eslint/utils/ts-eslint").RuleModule<"mismatchedCase" | "mismatchedCondition" | "replaceValueWithEnum", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
787
787
  'no-unsafe-function-type': import("@typescript-eslint/utils/ts-eslint").RuleModule<"bannedFunctionType", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
788
- 'no-unsafe-member-access': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeComputedMemberAccess" | "unsafeMemberExpression" | "unsafeThisMemberExpression", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
788
+ 'no-unsafe-member-access': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./rules/no-unsafe-member-access").MessageIds, import("./rules/no-unsafe-member-access").Options, import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
789
789
  'no-unsafe-return': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeReturn" | "unsafeReturnAssignment" | "unsafeReturnThis", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
790
790
  'no-unsafe-type-assertion': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeOfAnyTypeAssertion" | "unsafeToAnyTypeAssertion" | "unsafeToUnconstrainedTypeAssertion" | "unsafeTypeAssertion" | "unsafeTypeAssertionAssignableToConstraint", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
791
791
  'no-unsafe-unary-minus': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unaryMinus", [], import("../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
@@ -808,7 +808,7 @@ declare const _default: {
808
808
  'no-unsafe-declaration-merging': TSESLint.RuleModule<"unsafeMerging", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
809
809
  'no-unsafe-enum-comparison': TSESLint.RuleModule<"mismatchedCase" | "mismatchedCondition" | "replaceValueWithEnum", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
810
810
  'no-unsafe-function-type': TSESLint.RuleModule<"bannedFunctionType", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
811
- 'no-unsafe-member-access': TSESLint.RuleModule<"unsafeComputedMemberAccess" | "unsafeMemberExpression" | "unsafeThisMemberExpression", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
811
+ 'no-unsafe-member-access': TSESLint.RuleModule<import("./rules/no-unsafe-member-access").MessageIds, import("./rules/no-unsafe-member-access").Options, import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
812
812
  'no-unsafe-return': TSESLint.RuleModule<"unsafeReturn" | "unsafeReturnAssignment" | "unsafeReturnThis", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
813
813
  'no-unsafe-type-assertion': TSESLint.RuleModule<"unsafeOfAnyTypeAssertion" | "unsafeToAnyTypeAssertion" | "unsafeToUnconstrainedTypeAssertion" | "unsafeTypeAssertion" | "unsafeTypeAssertionAssignableToConstraint", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
814
814
  'no-unsafe-unary-minus': TSESLint.RuleModule<"unaryMinus", [], import("../rules").ESLintPluginDocs, TSESLint.RuleListener>;
@@ -115,7 +115,7 @@ declare const rules: {
115
115
  'no-unsafe-declaration-merging': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeMerging", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
116
116
  'no-unsafe-enum-comparison': import("@typescript-eslint/utils/ts-eslint").RuleModule<"mismatchedCase" | "mismatchedCondition" | "replaceValueWithEnum", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
117
117
  'no-unsafe-function-type': import("@typescript-eslint/utils/ts-eslint").RuleModule<"bannedFunctionType", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
118
- 'no-unsafe-member-access': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeComputedMemberAccess" | "unsafeMemberExpression" | "unsafeThisMemberExpression", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
118
+ 'no-unsafe-member-access': import("@typescript-eslint/utils/ts-eslint").RuleModule<import("./no-unsafe-member-access").MessageIds, import("./no-unsafe-member-access").Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
119
119
  'no-unsafe-return': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeReturn" | "unsafeReturnAssignment" | "unsafeReturnThis", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
120
120
  'no-unsafe-type-assertion': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeOfAnyTypeAssertion" | "unsafeToAnyTypeAssertion" | "unsafeToUnconstrainedTypeAssertion" | "unsafeTypeAssertion" | "unsafeTypeAssertionAssignableToConstraint", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
121
121
  'no-unsafe-unary-minus': import("@typescript-eslint/utils/ts-eslint").RuleModule<"unaryMinus", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
@@ -72,7 +72,7 @@ exports.default = (0, util_1.createRule)({
72
72
  },
73
73
  ignoredTypeNames: {
74
74
  type: 'array',
75
- description: 'Stringified regular expressions of type names to ignore.',
75
+ description: 'Stringified type names to ignore.',
76
76
  items: {
77
77
  type: 'string',
78
78
  },
@@ -149,6 +149,9 @@ exports.default = (0, util_1.createRule)({
149
149
  case utils_1.AST_NODE_TYPES.TSTypeAliasDeclaration:
150
150
  case utils_1.AST_NODE_TYPES.TSTypeParameter:
151
151
  return true;
152
+ // treat `export import Bar = Foo;` (and `import Foo = require('...')`) as declarations
153
+ case utils_1.AST_NODE_TYPES.TSImportEqualsDeclaration:
154
+ return parent.id === node;
152
155
  default:
153
156
  return false;
154
157
  }
@@ -35,7 +35,6 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  const utils_1 = require("@typescript-eslint/utils");
37
37
  const tsutils = __importStar(require("ts-api-utils"));
38
- const ts = __importStar(require("typescript"));
39
38
  const util_1 = require("../util");
40
39
  const promiseUtils_1 = require("../util/promiseUtils");
41
40
  const messageBase = 'Promises must be awaited, end with a call to .catch, or end with a call to .then with a rejection handler.';
@@ -141,8 +140,9 @@ exports.default = (0, util_1.createRule)({
141
140
  {
142
141
  messageId: 'floatingFixVoid',
143
142
  fix(fixer) {
144
- const tsNode = services.esTreeNodeToTSNodeMap.get(node.expression);
145
- if (isHigherPrecedenceThanUnary(tsNode)) {
143
+ if ((0, util_1.isParenthesized)(expression, context.sourceCode) ||
144
+ (0, util_1.getOperatorPrecedenceForNode)(expression) >
145
+ util_1.OperatorPrecedence.Unary) {
146
146
  return fixer.insertTextBefore(node, 'void ');
147
147
  }
148
148
  return [
@@ -180,8 +180,8 @@ exports.default = (0, util_1.createRule)({
180
180
  expression.operator === 'void') {
181
181
  return fixer.replaceTextRange([expression.range[0], expression.range[0] + 4], 'await');
182
182
  }
183
- const tsNode = services.esTreeNodeToTSNodeMap.get(node.expression);
184
- if (isHigherPrecedenceThanUnary(tsNode)) {
183
+ if ((0, util_1.isParenthesized)(expression, context.sourceCode) ||
184
+ (0, util_1.getOperatorPrecedenceForNode)(expression) > util_1.OperatorPrecedence.Unary) {
185
185
  return fixer.insertTextBefore(node, 'await ');
186
186
  }
187
187
  return [
@@ -199,13 +199,6 @@ exports.default = (0, util_1.createRule)({
199
199
  }
200
200
  return (0, util_1.typeMatchesSomeSpecifier)(type, allowForKnownSafeCalls, services.program);
201
201
  }
202
- function isHigherPrecedenceThanUnary(node) {
203
- const operator = ts.isBinaryExpression(node)
204
- ? node.operatorToken.kind
205
- : ts.SyntaxKind.Unknown;
206
- const nodePrecedence = (0, util_1.getOperatorPrecedence)(node.kind, operator);
207
- return nodePrecedence > util_1.OperatorPrecedence.Unary;
208
- }
209
202
  function isAsyncIife(node) {
210
203
  if (node.expression.type !== utils_1.AST_NODE_TYPES.CallExpression) {
211
204
  return false;
@@ -1,2 +1,8 @@
1
- declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<"unsafeComputedMemberAccess" | "unsafeMemberExpression" | "unsafeThisMemberExpression", [], import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
1
+ export type Options = [
2
+ {
3
+ allowOptionalChaining?: boolean;
4
+ }
5
+ ];
6
+ export type MessageIds = 'unsafeComputedMemberAccess' | 'unsafeMemberExpression' | 'unsafeThisMemberExpression';
7
+ declare const _default: import("@typescript-eslint/utils/ts-eslint").RuleModule<MessageIds, Options, import("../../rules").ESLintPluginDocs, import("@typescript-eslint/utils/ts-eslint").RuleListener>;
2
8
  export default _default;
@@ -40,6 +40,7 @@ var State;
40
40
  (function (State) {
41
41
  State[State["Unsafe"] = 1] = "Unsafe";
42
42
  State[State["Safe"] = 2] = "Safe";
43
+ State[State["Chained"] = 3] = "Chained";
43
44
  })(State || (State = {}));
44
45
  function createDataType(type) {
45
46
  const isErrorType = tsutils.isIntrinsicErrorType(type);
@@ -62,15 +63,41 @@ exports.default = (0, util_1.createRule)({
62
63
  'You can try to fix this by turning on the `noImplicitThis` compiler option, or adding a `this` parameter to the function.',
63
64
  ].join('\n'),
64
65
  },
65
- schema: [],
66
+ schema: [
67
+ {
68
+ type: 'object',
69
+ additionalProperties: false,
70
+ properties: {
71
+ allowOptionalChaining: {
72
+ type: 'boolean',
73
+ description: 'Whether to allow `?.` optional chains on `any` values.',
74
+ },
75
+ },
76
+ },
77
+ ],
66
78
  },
67
- defaultOptions: [],
68
- create(context) {
79
+ defaultOptions: [
80
+ {
81
+ allowOptionalChaining: false,
82
+ },
83
+ ],
84
+ create(context, [{ allowOptionalChaining }]) {
69
85
  const services = (0, util_1.getParserServices)(context);
70
86
  const compilerOptions = services.program.getCompilerOptions();
71
87
  const isNoImplicitThis = tsutils.isStrictCompilerOptionEnabled(compilerOptions, 'noImplicitThis');
72
88
  const stateCache = new Map();
89
+ // Case notes:
90
+ // value?.outer.middle.inner
91
+ // The ChainExpression is a child of the root expression, and a parent of all the MemberExpressions.
92
+ // But the left-most expression is what we want to report on: the inner-most expressions.
93
+ // In fact, this is true even if the chain is on the inside!
94
+ // value.outer.middle?.inner;
95
+ // It was already true that every `object` (MemberExpression) has optional: boolean
73
96
  function checkMemberExpression(node) {
97
+ if (allowOptionalChaining && node.optional) {
98
+ stateCache.set(node, State.Chained);
99
+ return State.Chained;
100
+ }
74
101
  const cachedState = stateCache.get(node);
75
102
  if (cachedState) {
76
103
  return cachedState;
@@ -113,6 +140,10 @@ exports.default = (0, util_1.createRule)({
113
140
  // ignore MemberExpressions with ancestors of type `TSClassImplements` or `TSInterfaceHeritage`
114
141
  'MemberExpression:not(TSClassImplements MemberExpression, TSInterfaceHeritage MemberExpression)': checkMemberExpression,
115
142
  'MemberExpression[computed = true] > *.property'(node) {
143
+ if (allowOptionalChaining &&
144
+ node.parent.optional) {
145
+ return;
146
+ }
116
147
  if (
117
148
  // x[1]
118
149
  node.type === utils_1.AST_NODE_TYPES.Literal ||
@@ -9,6 +9,7 @@ export type Options = [
9
9
  destructuredArrayIgnorePattern?: string;
10
10
  ignoreClassWithStaticInitBlock?: boolean;
11
11
  ignoreRestSiblings?: boolean;
12
+ ignoreUsingDeclarations?: boolean;
12
13
  reportUsedIgnorePattern?: boolean;
13
14
  vars?: 'all' | 'local';
14
15
  varsIgnorePattern?: string;
@@ -60,6 +60,10 @@ exports.default = (0, util_1.createRule)({
60
60
  type: 'boolean',
61
61
  description: 'Whether to ignore sibling properties in `...` destructurings.',
62
62
  },
63
+ ignoreUsingDeclarations: {
64
+ type: 'boolean',
65
+ description: 'Whether to ignore using or await using declarations.',
66
+ },
63
67
  reportUsedIgnorePattern: {
64
68
  type: 'boolean',
65
69
  description: 'Whether to report variables that match any of the valid ignore pattern options if they have been used.',
@@ -88,6 +92,7 @@ exports.default = (0, util_1.createRule)({
88
92
  caughtErrors: 'all',
89
93
  ignoreClassWithStaticInitBlock: false,
90
94
  ignoreRestSiblings: false,
95
+ ignoreUsingDeclarations: false,
91
96
  reportUsedIgnorePattern: false,
92
97
  vars: 'all',
93
98
  };
@@ -99,6 +104,9 @@ exports.default = (0, util_1.createRule)({
99
104
  options.args = firstOption.args ?? options.args;
100
105
  options.ignoreRestSiblings =
101
106
  firstOption.ignoreRestSiblings ?? options.ignoreRestSiblings;
107
+ options.ignoreUsingDeclarations =
108
+ firstOption.ignoreUsingDeclarations ??
109
+ options.ignoreUsingDeclarations;
102
110
  options.caughtErrors = firstOption.caughtErrors ?? options.caughtErrors;
103
111
  options.ignoreClassWithStaticInitBlock =
104
112
  firstOption.ignoreClassWithStaticInitBlock ??
@@ -382,6 +390,11 @@ exports.default = (0, util_1.createRule)({
382
390
  }
383
391
  continue;
384
392
  }
393
+ if (def.type === utils_1.TSESLint.Scope.DefinitionType.Variable &&
394
+ options.ignoreUsingDeclarations &&
395
+ (def.parent.kind === 'await using' || def.parent.kind === 'using')) {
396
+ continue;
397
+ }
385
398
  if (hasRestSpreadSibling(variable)) {
386
399
  continue;
387
400
  }
@@ -99,7 +99,10 @@ const isNotImported = (symbol, currentSourceFile) => {
99
99
  return (!!currentSourceFile &&
100
100
  currentSourceFile !== valueDeclaration.getSourceFile());
101
101
  };
102
- const BASE_MESSAGE = 'Avoid referencing unbound methods which may cause unintentional scoping of `this`.';
102
+ const BASE_MESSAGE = [
103
+ `A method that is not declared with \`this: void\` may cause unintentional scoping of \`this\` when separated from its object.`,
104
+ `Consider using an arrow function or explicitly \`.bind()\`ing the method to avoid calling the method with an unintended \`this\` value. `,
105
+ ].join('\n');
103
106
  exports.default = (0, util_1.createRule)({
104
107
  name: 'unbound-method',
105
108
  meta: {
@@ -111,7 +114,7 @@ exports.default = (0, util_1.createRule)({
111
114
  },
112
115
  messages: {
113
116
  unbound: BASE_MESSAGE,
114
- unboundWithoutThisAnnotation: `${BASE_MESSAGE}\nIf your function does not access \`this\`, you can annotate it with \`this: void\`, or consider using an arrow function instead.`,
117
+ unboundWithoutThisAnnotation: `${BASE_MESSAGE}\nIf a function does not access \`this\`, it can be annotated with \`this: void\`.`,
115
118
  },
116
119
  schema: [
117
120
  {
@@ -28,6 +28,10 @@ export declare enum OperatorPrecedence {
28
28
  Lowest = 0,
29
29
  Invalid = -1
30
30
  }
31
+ /**
32
+ * Note that this does not take into account parenthesization. You should check
33
+ * for parenthesization separately if it's relevant to your usage.
34
+ */
31
35
  export declare function getOperatorPrecedenceForNode(node: TSESTree.Node): OperatorPrecedence;
32
36
  type TSESTreeOperatorKind = ValueOf<TSESTree.BinaryOperatorToText> | ValueOf<TSESTree.PunctuatorTokenToText>;
33
37
  export declare function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean): OperatorPrecedence;
@@ -175,6 +175,10 @@ var OperatorPrecedence;
175
175
  // parsing to stop.
176
176
  OperatorPrecedence[OperatorPrecedence["Invalid"] = -1] = "Invalid";
177
177
  })(OperatorPrecedence || (exports.OperatorPrecedence = OperatorPrecedence = {}));
178
+ /**
179
+ * Note that this does not take into account parenthesization. You should check
180
+ * for parenthesization separately if it's relevant to your usage.
181
+ */
178
182
  function getOperatorPrecedenceForNode(node) {
179
183
  switch (node.type) {
180
184
  case utils_1.AST_NODE_TYPES.SpreadElement:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@typescript-eslint/eslint-plugin",
3
- "version": "8.45.1-alpha.1",
3
+ "version": "8.45.1-alpha.10",
4
4
  "description": "TypeScript plugin for ESLint",
5
5
  "files": [
6
6
  "dist",
@@ -59,10 +59,10 @@
59
59
  },
60
60
  "dependencies": {
61
61
  "@eslint-community/regexpp": "^4.10.0",
62
- "@typescript-eslint/scope-manager": "8.45.1-alpha.1",
63
- "@typescript-eslint/type-utils": "8.45.1-alpha.1",
64
- "@typescript-eslint/utils": "8.45.1-alpha.1",
65
- "@typescript-eslint/visitor-keys": "8.45.1-alpha.1",
62
+ "@typescript-eslint/scope-manager": "8.45.1-alpha.10",
63
+ "@typescript-eslint/type-utils": "8.45.1-alpha.10",
64
+ "@typescript-eslint/utils": "8.45.1-alpha.10",
65
+ "@typescript-eslint/visitor-keys": "8.45.1-alpha.10",
66
66
  "graphemer": "^1.4.0",
67
67
  "ignore": "^7.0.0",
68
68
  "natural-compare": "^1.4.0",
@@ -71,8 +71,8 @@
71
71
  "devDependencies": {
72
72
  "@types/mdast": "^4.0.3",
73
73
  "@types/natural-compare": "*",
74
- "@typescript-eslint/rule-schema-to-typescript-types": "8.45.1-alpha.1",
75
- "@typescript-eslint/rule-tester": "8.45.1-alpha.1",
74
+ "@typescript-eslint/rule-schema-to-typescript-types": "8.45.1-alpha.10",
75
+ "@typescript-eslint/rule-tester": "8.45.1-alpha.10",
76
76
  "@vitest/coverage-v8": "^3.1.3",
77
77
  "ajv": "^6.12.6",
78
78
  "cross-fetch": "*",
@@ -92,7 +92,7 @@
92
92
  "vitest": "^3.1.3"
93
93
  },
94
94
  "peerDependencies": {
95
- "@typescript-eslint/parser": "^8.45.1-alpha.1",
95
+ "@typescript-eslint/parser": "^8.45.1-alpha.10",
96
96
  "eslint": "^8.57.0 || ^9.0.0",
97
97
  "typescript": ">=4.8.4 <6.0.0"
98
98
  },