From fff00adf5726d1ad5de62096a2de4ce5bed4290b Mon Sep 17 00:00:00 2001 From: Ahmed Abdelbaset Date: Sat, 28 Sep 2024 00:02:51 +0300 Subject: [PATCH 1/2] add failed tests for MemberExpression --- src/rules/no-phyisical-properties/test.ts | 86 +++++++++++++++++++++-- src/utils/ast.test.ts | 20 ++++++ src/utils/ast.ts | 28 ++++---- src/utils/eslint.ts | 47 +++++++++++++ 4 files changed, 162 insertions(+), 19 deletions(-) create mode 100644 src/utils/ast.test.ts create mode 100644 src/utils/eslint.ts diff --git a/src/rules/no-phyisical-properties/test.ts b/src/rules/no-phyisical-properties/test.ts index 170c328..fa17b15 100644 --- a/src/rules/no-phyisical-properties/test.ts +++ b/src/rules/no-phyisical-properties/test.ts @@ -319,20 +319,55 @@ vitest.describe(RULE_NAME, () => { ], }, { - name: "Outside the scope", + skip: true, + name: "MemberExpression", code: ` - const cls = "left-2"; function Comp() { - return
+ const styles = { main: "left-2" }; + return
} `, + errors: [{ messageId: IDENTIFIER_USED }], output: ` - const cls = "start-2"; function Comp() { - return
+ const styles = { main: "start-2" }; + return
+ } + `, + }, + { + skip: true, + name: "MemberExpression with computed property", + code: ` + const styles = { main: "left-2" }; + function Comp() { + return
+ } + `, + errors: [{ messageId: IDENTIFIER_USED }], + output: ` + const styles = { main: "start-2" }; + function Comp() { + return
+ } + `, + }, + { + skip: true, + name: "MemberExpression deeply", + code: ` + const styles = { main: { title: "left-2" } }; + function Comp() { + return
} `, errors: [{ messageId: IDENTIFIER_USED }], + output: ` + const styles = { main: { title: "start-2" } }; + function Comp() { + return
+ } + `, }, { name: "Reassignment in a nested scope", @@ -355,6 +390,47 @@ vitest.describe(RULE_NAME, () => { { messageId: IDENTIFIER_USED }, ], }, + { + skip: true, + name: "Reassignment object in a nested scope", + code: ` + let styles = { main: "left-2" }; + function Comp() { + styles = { main: "text-left", hey: "pl-2" }; + return
+ } + `, + output: ` + let styles = { main: "start-2" }; + function Comp() { + styles = { main: "text-start", hey: "pl-2" }; + return
+ } + `, + errors: [ + { messageId: IDENTIFIER_USED }, + { messageId: IDENTIFIER_USED }, + ], + }, + { + skip: true, + name: "Reassignment object property in a nested scope", + code: ` + const styles = { main: "left-2" }; + function Comp() { + styles.main = "text-left"; + return
+ } + `, + output: ` + const styles = { main: "start-2" }; + function Comp() { + styles.main = "text-start"; + return
+ } + `, + errors: [{ messageId: IDENTIFIER_USED }], + }, { name: "Don't conflict with other vars with the same name", code: ` diff --git a/src/utils/ast.test.ts b/src/utils/ast.test.ts new file mode 100644 index 0000000..eb7c76f --- /dev/null +++ b/src/utils/ast.test.ts @@ -0,0 +1,20 @@ +// the ast.ts exports are tested in `test.ts` but this file is only to 100% coverage + +import { describe, expect, it } from "vitest"; +import { extractTokensFromNode } from "./ast.js"; +import type { Context } from "../rules/no-phyisical-properties/rule.js"; +import type { AST_NODE_TYPES, TSESTree } from "@typescript-eslint/utils"; + +describe("ast", () => { + it("non JSXAttribute", () => { + expect( + extractTokensFromNode( + { + type: "VariableDeclaration" as AST_NODE_TYPES.VariableDeclaration, + } as TSESTree.Node, + {} as Context, + "fixer" + ) + ).toEqual([]); + }); +}); diff --git a/src/utils/ast.ts b/src/utils/ast.ts index 465360b..f055652 100644 --- a/src/utils/ast.ts +++ b/src/utils/ast.ts @@ -25,8 +25,6 @@ export function extractTokensFromNode( ctx: Context, runner: "checker" | "fixer" ): Token[] { - const run = (exp: Exp) => extractTokensFromExpression(exp, ctx, runner); - if (node.type === "JSXAttribute") { // value: Literal | JSXExpressionContainer | JSXElement | JSXFragment | null const value = node.value; @@ -45,17 +43,18 @@ export function extractTokensFromNode( return extractTokensFromExpression(expression, ctx, runner); } - if (value.type === "JSXElement" || value.type === "JSXSpreadChild") { - return []; - } + // if (value.type === "JSXElement" || value.type === "JSXSpreadChild") { + // return []; + // } - return []; + // return []; } - if (is(node, "VariableDeclarator")) { - if (!node.init) return []; - return run(node.init); - } + // Handled somewhere else > find the call of `getDefinitions` + // if (is(node, "VariableDeclarator")) { + // if (!node.init) return []; + // return run(node.init); + // } // if (is(node, "ArrowFunctionExpression")) return run(node); @@ -170,14 +169,15 @@ function extractTokensFromExpression( const writes = getDefinitions(exp, ctx, scope).filter( (r) => r?.type === "Literal" || r?.type === "Identifier" + // || r?.type === "ObjectExpression" || + // r?.type === "AssignmentExpression" ); - return writes.flatMap((n) => rerun(n, true)); } - if (is(exp, "MemberExpression")) { - return []; - } + // if (is(exp, "MemberExpression") && is(exp.property, "Identifier")) { + // return []; + // } /* if (is(exp, "ArrowFunctionExpression")) { diff --git a/src/utils/eslint.ts b/src/utils/eslint.ts new file mode 100644 index 0000000..331447a --- /dev/null +++ b/src/utils/eslint.ts @@ -0,0 +1,47 @@ +/// + +import type { TSESLint, TSESTree } from "@typescript-eslint/utils"; + +export function findVariable( + initialScope: TSESLint.Scope.Scope, + node: TSESTree.Identifier +) { + let scope: TSESLint.Scope.Scope | null = initialScope; + const name = node.name; + + scope = getInnermostScope(scope, node); + + while (scope != null) { + const variable = scope.set.get(name); + if (variable != null) { + return variable; + } + scope = scope.upper; + } + + return null; +} + +export function getInnermostScope( + initialScope: TSESLint.Scope.Scope, + node: TSESTree.Node +): TSESLint.Scope.Scope { + const location = node.range[0]; + + let scope = initialScope; + let found = false; + do { + found = false; + for (const childScope of scope.childScopes) { + const range = childScope.block.range; + + if (range[0] <= location && location < range[1]) { + scope = childScope; + found = true; + break; + } + } + } while (found); + + return scope; +} From 0bb45954db6a516e56d2c61b326290ac96530df0 Mon Sep 17 00:00:00 2001 From: Ahmed Abdelbaset Date: Sat, 28 Sep 2024 00:03:15 +0300 Subject: [PATCH 2/2] update typescript --- package.json | 2 +- pnpm-lock.yaml | 80 +++++++++++++++++++++++++------------------------- 2 files changed, 41 insertions(+), 41 deletions(-) diff --git a/package.json b/package.json index efad5a3..5d2840b 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,7 @@ "eslint-plugin-eslint-plugin": "^6.2.0", "tailwindcss": "~3.3.3", "tsup": "^8.2.4", - "typescript": "^5.5.4", + "typescript": "^5.6.2", "typescript-eslint": "^8.0.0", "vitest": "^2.0.5" }, diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 756a3a1..e34c86a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -25,10 +25,10 @@ importers: version: 20.16.2 '@typescript-eslint/rule-tester': specifier: ^8.0.0 - version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) '@typescript-eslint/utils': specifier: ^8.0.0 - version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) '@vitest/coverage-v8': specifier: ^2.0.5 version: 2.0.5(vitest@2.0.5(@types/node@20.16.2)) @@ -43,13 +43,13 @@ importers: version: 3.3.7 tsup: specifier: ^8.2.4 - version: 8.2.4(jiti@1.21.6)(postcss@8.4.42)(typescript@5.5.4)(yaml@2.5.0) + version: 8.2.4(jiti@1.21.6)(postcss@8.4.42)(typescript@5.6.2)(yaml@2.5.0) typescript: - specifier: ^5.5.4 - version: 5.5.4 + specifier: ^5.6.2 + version: 5.6.2 typescript-eslint: specifier: ^8.0.0 - version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + version: 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) vitest: specifier: ^2.0.5 version: 2.0.5(@types/node@20.16.2) @@ -1859,8 +1859,8 @@ packages: typescript: optional: true - typescript@5.5.4: - resolution: {integrity: sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==} + typescript@5.6.2: + resolution: {integrity: sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==} engines: {node: '>=14.17'} hasBin: true @@ -2524,41 +2524,41 @@ snapshots: '@types/semver@7.5.8': {} - '@typescript-eslint/eslint-plugin@8.3.0(@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': + '@typescript-eslint/eslint-plugin@8.3.0(@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)': dependencies: '@eslint-community/regexpp': 4.11.0 - '@typescript-eslint/parser': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + '@typescript-eslint/parser': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/type-utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + '@typescript-eslint/type-utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) '@typescript-eslint/visitor-keys': 8.3.0 eslint: 9.9.1(jiti@1.21.6) graphemer: 1.4.0 ignore: 5.3.2 natural-compare: 1.4.0 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': + '@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)': dependencies: '@typescript-eslint/scope-manager': 8.3.0 '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.6.2) '@typescript-eslint/visitor-keys': 8.3.0 debug: 4.3.6 eslint: 9.9.1(jiti@1.21.6) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/rule-tester@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': + '@typescript-eslint/rule-tester@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) ajv: 6.12.6 eslint: 9.9.1(jiti@1.21.6) json-stable-stringify-without-jsonify: 1.0.1 @@ -2573,21 +2573,21 @@ snapshots: '@typescript-eslint/types': 8.3.0 '@typescript-eslint/visitor-keys': 8.3.0 - '@typescript-eslint/type-utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': + '@typescript-eslint/type-utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)': dependencies: - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.6.2) + '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) debug: 4.3.6 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - eslint - supports-color '@typescript-eslint/types@8.3.0': {} - '@typescript-eslint/typescript-estree@8.3.0(typescript@5.5.4)': + '@typescript-eslint/typescript-estree@8.3.0(typescript@5.6.2)': dependencies: '@typescript-eslint/types': 8.3.0 '@typescript-eslint/visitor-keys': 8.3.0 @@ -2596,18 +2596,18 @@ snapshots: is-glob: 4.0.3 minimatch: 9.0.5 semver: 7.6.3 - ts-api-utils: 1.3.0(typescript@5.5.4) + ts-api-utils: 1.3.0(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - supports-color - '@typescript-eslint/utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4)': + '@typescript-eslint/utils@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2)': dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@9.9.1(jiti@1.21.6)) '@typescript-eslint/scope-manager': 8.3.0 '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) + '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.6.2) eslint: 9.9.1(jiti@1.21.6) transitivePeerDependencies: - supports-color @@ -3718,13 +3718,13 @@ snapshots: tree-kill@1.2.2: {} - ts-api-utils@1.3.0(typescript@5.5.4): + ts-api-utils@1.3.0(typescript@5.6.2): dependencies: - typescript: 5.5.4 + typescript: 5.6.2 ts-interface-checker@0.1.13: {} - tsup@8.2.4(jiti@1.21.6)(postcss@8.4.42)(typescript@5.5.4)(yaml@2.5.0): + tsup@8.2.4(jiti@1.21.6)(postcss@8.4.42)(typescript@5.6.2)(yaml@2.5.0): dependencies: bundle-require: 5.0.0(esbuild@0.23.1) cac: 6.7.14 @@ -3744,7 +3744,7 @@ snapshots: tree-kill: 1.2.2 optionalDependencies: postcss: 8.4.42 - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - jiti - supports-color @@ -3755,18 +3755,18 @@ snapshots: dependencies: prelude-ls: 1.2.1 - typescript-eslint@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4): + typescript-eslint@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2): dependencies: - '@typescript-eslint/eslint-plugin': 8.3.0(@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4))(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) - '@typescript-eslint/parser': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.5.4) + '@typescript-eslint/eslint-plugin': 8.3.0(@typescript-eslint/parser@8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2))(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/parser': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) + '@typescript-eslint/utils': 8.3.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.6.2) optionalDependencies: - typescript: 5.5.4 + typescript: 5.6.2 transitivePeerDependencies: - eslint - supports-color - typescript@5.5.4: {} + typescript@5.6.2: {} undici-types@6.19.8: {}