Skip to content

Commit

Permalink
handle defs outside the scope
Browse files Browse the repository at this point in the history
  • Loading branch information
AhmedBaset committed Aug 16, 2024
1 parent 835fd10 commit 9119153
Show file tree
Hide file tree
Showing 4 changed files with 140 additions and 9 deletions.
2 changes: 1 addition & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { FlatConfig } from "@typescript-eslint/utils/ts-eslint";
import { noPhysicalProperties } from "./rules/no-phyisical-properties/rule";
import { name, version } from "../package.json";
import { noPhysicalProperties } from "./rules/no-phyisical-properties/rule";

Check warning on line 3 in src/index.ts

View check run for this annotation

Codecov / codecov/patch

src/index.ts#L3

Added line #L3 was not covered by tests

const rtlFriendly = {
meta: { name, version },
Expand Down
110 changes: 109 additions & 1 deletion src/rules/no-phyisical-properties/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,16 @@ vitest.describe(RULE_NAME, () => {
});

tester.run("Look for variable decleration", noPhysicalProperties, {
valid: [],
valid: [
{
name: "function arg",
code: `
function Comp({className}) {
return <div className={cn(className)} />
}
`,
},
],
invalid: [
{
name: "className={variable}",
Expand Down Expand Up @@ -244,6 +253,105 @@ vitest.describe(RULE_NAME, () => {
`,
errors: [{ messageId: NO_PHYSICAL_CLASSESS }],
},
{
name: "let b = '...'",
code: `
let b = "text-left";
<div className={b} />
`,
output: `
let b = "text-start";
<div className={b} />
`,
errors: [{ messageId: NO_PHYSICAL_CLASSESS }],
},
{
name: "let b = '...'; b = '...'",
code: `
let b = "text-left";
b = "text-right";
<div className={b} />
`,
output: `
let b = "text-start";
b = "text-end";
<div className={b} />
`,
errors: [
{ messageId: NO_PHYSICAL_CLASSESS },
{ messageId: NO_PHYSICAL_CLASSESS },
],
},
{
name: "Outside the scope",
code: `
const cls = "left-2";
function Comp() {
return <div className={cls} />
}
`,
output: `
const cls = "start-2";
function Comp() {
return <div className={cls} />
}
`,
errors: [{ messageId: NO_PHYSICAL_CLASSESS }],
},
{
name: "Reassignment in a nested scope",
code: `
let cls = "left-2";
function Comp() {
cls = "text-left";
return <div className={cls} />
}
`,
output: `
let cls = "start-2";
function Comp() {
cls = "text-start";
return <div className={cls} />
}
`,
errors: [
{ messageId: NO_PHYSICAL_CLASSESS },
{ messageId: NO_PHYSICAL_CLASSESS },
],
},
{
name: "Don't conflict with other vars with the same name",
code: `
const cls = "left-2";
function Comp() {
const cls = "text-left";
return <div className={cls} />
}
`,
output: `
const cls = "left-2";
function Comp() {
const cls = "text-start";
return <div className={cls} />
}
`,
errors: [{ messageId: NO_PHYSICAL_CLASSESS }],
},
{
name: "function arg",
code: `
function Comp({ className = "text-left" }) {
return <div className={cn(className)} />
}
`,
output: `
function Comp({ className = "text-start" }) {
return <div className={cn(className)} />
}
`,
errors: [{ messageId: NO_PHYSICAL_CLASSESS }],
skip: true,
},
],
});

Expand Down
35 changes: 29 additions & 6 deletions src/utils/ast.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { TSESTree } from "@typescript-eslint/utils";
import type { TSESTree } from "@typescript-eslint/utils";
import type { Scope } from "@typescript-eslint/utils/ts-eslint";
import type { Context } from "../rules/no-phyisical-properties/rule";

const unimplemented = new Set<string>();
Expand Down Expand Up @@ -50,7 +51,7 @@ export function extractTokensFromNode(
return run(node.init);
}

Check warning on line 52 in src/utils/ast.ts

View check run for this annotation

Codecov / codecov/patch

src/utils/ast.ts#L49-L52

Added lines #L49 - L52 were not covered by tests

if (is(node, "ArrowFunctionExpression")) return run(node);
// if (is(node, "ArrowFunctionExpression")) return run(node);

return [];
}
Expand Down Expand Up @@ -150,11 +151,12 @@ function extractTokensFromExpression(
if (is(exp, "Identifier")) {
// We should follow the identifier and get the value
const scope = ctx.sourceCode.getScope(exp);
const binding = scope?.set.get(exp.name);
const node = binding?.defs[0].node;
if (!node) return [];

return extractTokensFromNode(node, ctx, runner);
const writes = getDefinitions(exp, ctx, scope).filter(
(r) => r?.type === "Literal" || r?.type === "Identifier"
);

return writes.flatMap((n) => rerun(n));
}

if (is(exp, "MemberExpression")) {

Check warning on line 162 in src/utils/ast.ts

View check run for this annotation

Codecov / codecov/patch

src/utils/ast.ts#L162

Added line #L162 was not covered by tests
Expand Down Expand Up @@ -259,3 +261,24 @@ function is<E extends Exp | TSESTree.Node, T extends E["type"]>(
): exp is Extract<E, { type: T }> {
return exp.type === type;
}

function getDefinitions(
identifier: TSESTree.Identifier,
ctx: Context,
scope: Scope.Scope
) {
const writes = scope.references
.filter((r) => r.identifier.name === identifier.name && r.writeExpr)
.flatMap((r) => r.writeExpr);

const defs = scope.set.get(identifier.name)?.defs ?? [];
if (!defs.length && scope.upper) {
const defs = getDefinitions(identifier, ctx, scope.upper);
writes.push(...defs);
}

if (writes.length) return writes;

if (scope.upper) return getDefinitions(identifier, ctx, scope.upper);
return [];
}
2 changes: 1 addition & 1 deletion vitest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,6 @@ export default defineConfig({
include: ["src/**/test.ts"],
coverage: {
include: ["src/**"],
}
},
},
});

0 comments on commit 9119153

Please sign in to comment.