diff --git a/packages/ast-spec/src/base/BinaryExpressionBase.ts b/packages/ast-spec/src/base/BinaryExpressionBase.ts deleted file mode 100644 index 926491d4985..00000000000 --- a/packages/ast-spec/src/base/BinaryExpressionBase.ts +++ /dev/null @@ -1,8 +0,0 @@ -import type { Expression } from '../unions/Expression'; -import type { BaseNode } from './BaseNode'; - -export interface BinaryExpressionBase extends BaseNode { - operator: string; - left: Expression; - right: Expression; -} diff --git a/packages/ast-spec/src/expression/AssignmentExpression/spec.ts b/packages/ast-spec/src/expression/AssignmentExpression/spec.ts index 8d76be21bdc..eb3c8effa99 100644 --- a/packages/ast-spec/src/expression/AssignmentExpression/spec.ts +++ b/packages/ast-spec/src/expression/AssignmentExpression/spec.ts @@ -1,7 +1,8 @@ import type { AST_NODE_TYPES } from '../../ast-node-types'; -import type { BinaryExpressionBase } from '../../base/BinaryExpressionBase'; +import type { BaseNode } from '../../base/BaseNode'; +import type { Expression } from '../../unions/Expression'; -export interface AssignmentExpression extends BinaryExpressionBase { +export interface AssignmentExpression extends BaseNode { type: AST_NODE_TYPES.AssignmentExpression; operator: | '-=' @@ -20,4 +21,6 @@ export interface AssignmentExpression extends BinaryExpressionBase { | '>>>=' | '|=' | '||='; + left: Expression; + right: Expression; } diff --git a/packages/ast-spec/src/expression/BinaryExpression/spec.ts b/packages/ast-spec/src/expression/BinaryExpression/spec.ts index 5df33cc3e16..fa43c88bcf5 100644 --- a/packages/ast-spec/src/expression/BinaryExpression/spec.ts +++ b/packages/ast-spec/src/expression/BinaryExpression/spec.ts @@ -1,6 +1,11 @@ import type { AST_NODE_TYPES } from '../../ast-node-types'; -import type { BinaryExpressionBase } from '../../base/BinaryExpressionBase'; +import type { BaseNode } from '../../base/BaseNode'; +import type { PrivateIdentifier } from '../../special/PrivateIdentifier/spec'; +import type { Expression } from '../../unions/Expression'; -export interface BinaryExpression extends BinaryExpressionBase { +export interface BinaryExpression extends BaseNode { type: AST_NODE_TYPES.BinaryExpression; + operator: string; + left: Expression | PrivateIdentifier; + right: Expression; } diff --git a/packages/ast-spec/src/expression/LogicalExpression/spec.ts b/packages/ast-spec/src/expression/LogicalExpression/spec.ts index 6d2b56b50dd..1eda8e3b615 100644 --- a/packages/ast-spec/src/expression/LogicalExpression/spec.ts +++ b/packages/ast-spec/src/expression/LogicalExpression/spec.ts @@ -1,7 +1,10 @@ import type { AST_NODE_TYPES } from '../../ast-node-types'; -import type { BinaryExpressionBase } from '../../base/BinaryExpressionBase'; +import type { BaseNode } from '../../base/BaseNode'; +import type { Expression } from '../../unions/Expression'; -export interface LogicalExpression extends BinaryExpressionBase { +export interface LogicalExpression extends BaseNode { type: AST_NODE_TYPES.LogicalExpression; operator: '??' | '&&' | '||'; + left: Expression; + right: Expression; } diff --git a/packages/eslint-plugin/src/rules/no-base-to-string.ts b/packages/eslint-plugin/src/rules/no-base-to-string.ts index 11962363c64..644bb88152a 100644 --- a/packages/eslint-plugin/src/rules/no-base-to-string.ts +++ b/packages/eslint-plugin/src/rules/no-base-to-string.ts @@ -166,7 +166,10 @@ export default util.createRule({ if (util.getTypeName(typeChecker, leftType) === 'string') { checkExpression(node.right, rightType); - } else if (util.getTypeName(typeChecker, rightType) === 'string') { + } else if ( + util.getTypeName(typeChecker, rightType) === 'string' && + node.left.type !== AST_NODE_TYPES.PrivateIdentifier + ) { checkExpression(node.left, leftType); } }, diff --git a/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts b/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts index f578c5d3a1d..1535a643397 100644 --- a/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts +++ b/packages/eslint-plugin/src/rules/no-confusing-non-null-assertion.ts @@ -38,7 +38,7 @@ export default util.createRule({ node: TSESTree.BinaryExpression | TSESTree.AssignmentExpression, ): void { function isLeftHandPrimaryExpression( - node: TSESTree.Expression, + node: TSESTree.Expression | TSESTree.PrivateIdentifier, ): boolean { return node.type === AST_NODE_TYPES.TSNonNullExpression; } diff --git a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts index 8583e657f91..41367d4115b 100644 --- a/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts +++ b/packages/eslint-plugin/src/rules/no-unnecessary-boolean-literal-compare.ts @@ -21,7 +21,7 @@ type Options = [ ]; interface BooleanComparison { - expression: TSESTree.Expression; + expression: TSESTree.Expression | TSESTree.PrivateIdentifier; literalBooleanInComparison: boolean; forTruthy: boolean; negated: boolean; diff --git a/packages/eslint-plugin/src/rules/prefer-for-of.ts b/packages/eslint-plugin/src/rules/prefer-for-of.ts index f00868d0409..e1c3a058016 100644 --- a/packages/eslint-plugin/src/rules/prefer-for-of.ts +++ b/packages/eslint-plugin/src/rules/prefer-for-of.ts @@ -33,7 +33,10 @@ export default util.createRule({ ); } - function isLiteral(node: TSESTree.Expression, value: number): boolean { + function isLiteral( + node: TSESTree.Expression | TSESTree.PrivateIdentifier, + value: number, + ): boolean { return node.type === AST_NODE_TYPES.Literal && node.value === value; } diff --git a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts index c90bb0a1a74..9bf63c08431 100644 --- a/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts +++ b/packages/eslint-plugin/src/rules/prefer-string-starts-ends-with.ts @@ -286,7 +286,9 @@ export default createRule({ return { isEndsWith, isStartsWith, text }; } - function getLeftNode(node: TSESTree.Expression): TSESTree.MemberExpression { + function getLeftNode( + node: TSESTree.Expression | TSESTree.PrivateIdentifier, + ): TSESTree.MemberExpression { if (node.type === AST_NODE_TYPES.ChainExpression) { return getLeftNode(node.expression); } diff --git a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts index 51b4da9be46..30c155e3dcd 100644 --- a/packages/eslint-plugin/src/rules/restrict-plus-operands.ts +++ b/packages/eslint-plugin/src/rules/restrict-plus-operands.ts @@ -93,7 +93,9 @@ export default util.createRule({ * Helper function to get base type of node * @param node the node to be evaluated. */ - function getNodeType(node: TSESTree.Expression): BaseLiteral { + function getNodeType( + node: TSESTree.Expression | TSESTree.PrivateIdentifier, + ): BaseLiteral { const tsNode = service.esTreeNodeToTSNodeMap.get(node); const type = util.getConstrainedTypeAtLocation(typeChecker, tsNode); diff --git a/packages/shared-fixtures/fixtures/typescript/basics/private-fields-in-in.src.ts b/packages/shared-fixtures/fixtures/typescript/basics/private-fields-in-in.src.ts new file mode 100644 index 00000000000..b75db0be222 --- /dev/null +++ b/packages/shared-fixtures/fixtures/typescript/basics/private-fields-in-in.src.ts @@ -0,0 +1,6 @@ +class Foo { + #prop1; + method(arg) { + return #prop1 in arg; + } +} diff --git a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap index ad3342300b6..d3a84fbb12a 100644 --- a/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap +++ b/packages/typescript-estree/tests/lib/__snapshots__/semantic-diagnostics-enabled.test.ts.snap @@ -2072,6 +2072,8 @@ exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" e exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/basics/parenthesized-use-strict.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; +exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/basics/private-fields-in-in.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; + exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/basics/readonly-arrays.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; exports[`Parse all fixtures with "errorOnTypeScriptSyntacticAndSemanticIssues" enabled fixtures/typescript/basics/readonly-tuples.src 1`] = `"TEST OUTPUT: No semantic or syntactic issues found"`; diff --git a/packages/typescript-estree/tests/snapshots/typescript/basics/private-fields-in-in.src.ts.shot b/packages/typescript-estree/tests/snapshots/typescript/basics/private-fields-in-in.src.ts.shot new file mode 100644 index 00000000000..27c37ed05ad --- /dev/null +++ b/packages/typescript-estree/tests/snapshots/typescript/basics/private-fields-in-in.src.ts.shot @@ -0,0 +1,599 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`typescript basics private-fields-in-in.src 1`] = ` +Object { + "body": Array [ + Object { + "body": Object { + "body": Array [ + Object { + "computed": false, + "declare": false, + "key": Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 2, + }, + "start": Object { + "column": 2, + "line": 2, + }, + }, + "name": "prop1", + "range": Array [ + 14, + 20, + ], + "type": "PrivateIdentifier", + }, + "loc": Object { + "end": Object { + "column": 9, + "line": 2, + }, + "start": Object { + "column": 2, + "line": 2, + }, + }, + "override": false, + "range": Array [ + 14, + 21, + ], + "readonly": undefined, + "static": false, + "type": "PropertyDefinition", + "value": null, + }, + Object { + "computed": false, + "key": Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 3, + }, + "start": Object { + "column": 2, + "line": 3, + }, + }, + "name": "method", + "range": Array [ + 24, + 30, + ], + "type": "Identifier", + }, + "kind": "method", + "loc": Object { + "end": Object { + "column": 3, + "line": 5, + }, + "start": Object { + "column": 2, + "line": 3, + }, + }, + "override": false, + "range": Array [ + 24, + 67, + ], + "static": false, + "type": "MethodDefinition", + "value": Object { + "async": false, + "body": Object { + "body": Array [ + Object { + "argument": Object { + "left": Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 4, + }, + "start": Object { + "column": 11, + "line": 4, + }, + }, + "name": "prop1", + "range": Array [ + 49, + 55, + ], + "type": "PrivateIdentifier", + }, + "loc": Object { + "end": Object { + "column": 24, + "line": 4, + }, + "start": Object { + "column": 11, + "line": 4, + }, + }, + "operator": "in", + "range": Array [ + 49, + 62, + ], + "right": Object { + "loc": Object { + "end": Object { + "column": 24, + "line": 4, + }, + "start": Object { + "column": 21, + "line": 4, + }, + }, + "name": "arg", + "range": Array [ + 59, + 62, + ], + "type": "Identifier", + }, + "type": "BinaryExpression", + }, + "loc": Object { + "end": Object { + "column": 25, + "line": 4, + }, + "start": Object { + "column": 4, + "line": 4, + }, + }, + "range": Array [ + 42, + 63, + ], + "type": "ReturnStatement", + }, + ], + "loc": Object { + "end": Object { + "column": 3, + "line": 5, + }, + "start": Object { + "column": 14, + "line": 3, + }, + }, + "range": Array [ + 36, + 67, + ], + "type": "BlockStatement", + }, + "expression": false, + "generator": false, + "id": null, + "loc": Object { + "end": Object { + "column": 3, + "line": 5, + }, + "start": Object { + "column": 8, + "line": 3, + }, + }, + "params": Array [ + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 3, + }, + "start": Object { + "column": 9, + "line": 3, + }, + }, + "name": "arg", + "range": Array [ + 31, + 34, + ], + "type": "Identifier", + }, + ], + "range": Array [ + 30, + 67, + ], + "type": "FunctionExpression", + }, + }, + ], + "loc": Object { + "end": Object { + "column": 1, + "line": 6, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 69, + ], + "type": "ClassBody", + }, + "id": Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "name": "Foo", + "range": Array [ + 6, + 9, + ], + "type": "Identifier", + }, + "loc": Object { + "end": Object { + "column": 1, + "line": 6, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 69, + ], + "superClass": null, + "type": "ClassDeclaration", + }, + ], + "comments": Array [], + "loc": Object { + "end": Object { + "column": 0, + "line": 7, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 70, + ], + "sourceType": "script", + "tokens": Array [ + Object { + "loc": Object { + "end": Object { + "column": 5, + "line": 1, + }, + "start": Object { + "column": 0, + "line": 1, + }, + }, + "range": Array [ + 0, + 5, + ], + "type": "Keyword", + "value": "class", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 1, + }, + "start": Object { + "column": 6, + "line": 1, + }, + }, + "range": Array [ + 6, + 9, + ], + "type": "Identifier", + "value": "Foo", + }, + Object { + "loc": Object { + "end": Object { + "column": 11, + "line": 1, + }, + "start": Object { + "column": 10, + "line": 1, + }, + }, + "range": Array [ + 10, + 11, + ], + "type": "Punctuator", + "value": "{", + }, + Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 2, + }, + "start": Object { + "column": 2, + "line": 2, + }, + }, + "range": Array [ + 14, + 20, + ], + "type": "Identifier", + "value": "#prop1", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 2, + }, + "start": Object { + "column": 8, + "line": 2, + }, + }, + "range": Array [ + 20, + 21, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 8, + "line": 3, + }, + "start": Object { + "column": 2, + "line": 3, + }, + }, + "range": Array [ + 24, + 30, + ], + "type": "Identifier", + "value": "method", + }, + Object { + "loc": Object { + "end": Object { + "column": 9, + "line": 3, + }, + "start": Object { + "column": 8, + "line": 3, + }, + }, + "range": Array [ + 30, + 31, + ], + "type": "Punctuator", + "value": "(", + }, + Object { + "loc": Object { + "end": Object { + "column": 12, + "line": 3, + }, + "start": Object { + "column": 9, + "line": 3, + }, + }, + "range": Array [ + 31, + 34, + ], + "type": "Identifier", + "value": "arg", + }, + Object { + "loc": Object { + "end": Object { + "column": 13, + "line": 3, + }, + "start": Object { + "column": 12, + "line": 3, + }, + }, + "range": Array [ + 34, + 35, + ], + "type": "Punctuator", + "value": ")", + }, + Object { + "loc": Object { + "end": Object { + "column": 15, + "line": 3, + }, + "start": Object { + "column": 14, + "line": 3, + }, + }, + "range": Array [ + 36, + 37, + ], + "type": "Punctuator", + "value": "{", + }, + Object { + "loc": Object { + "end": Object { + "column": 10, + "line": 4, + }, + "start": Object { + "column": 4, + "line": 4, + }, + }, + "range": Array [ + 42, + 48, + ], + "type": "Keyword", + "value": "return", + }, + Object { + "loc": Object { + "end": Object { + "column": 17, + "line": 4, + }, + "start": Object { + "column": 11, + "line": 4, + }, + }, + "range": Array [ + 49, + 55, + ], + "type": "Identifier", + "value": "#prop1", + }, + Object { + "loc": Object { + "end": Object { + "column": 20, + "line": 4, + }, + "start": Object { + "column": 18, + "line": 4, + }, + }, + "range": Array [ + 56, + 58, + ], + "type": "Keyword", + "value": "in", + }, + Object { + "loc": Object { + "end": Object { + "column": 24, + "line": 4, + }, + "start": Object { + "column": 21, + "line": 4, + }, + }, + "range": Array [ + 59, + 62, + ], + "type": "Identifier", + "value": "arg", + }, + Object { + "loc": Object { + "end": Object { + "column": 25, + "line": 4, + }, + "start": Object { + "column": 24, + "line": 4, + }, + }, + "range": Array [ + 62, + 63, + ], + "type": "Punctuator", + "value": ";", + }, + Object { + "loc": Object { + "end": Object { + "column": 3, + "line": 5, + }, + "start": Object { + "column": 2, + "line": 5, + }, + }, + "range": Array [ + 66, + 67, + ], + "type": "Punctuator", + "value": "}", + }, + Object { + "loc": Object { + "end": Object { + "column": 1, + "line": 6, + }, + "start": Object { + "column": 0, + "line": 6, + }, + }, + "range": Array [ + 68, + 69, + ], + "type": "Punctuator", + "value": "}", + }, + ], + "type": "Program", +} +`;