Skip to content

Commit 5f5523d

Browse files
authored
Merge branch 'main' into no-use-in-try-catch
2 parents 46e426e + 633a1bb commit 5f5523d

File tree

37 files changed

+620
-622
lines changed

37 files changed

+620
-622
lines changed

.pkgs/eslint-plugin-local/dist/index.js

Lines changed: 40 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import * as AST from '@eslint-react/ast';
22
import { ESLintUtils, AST_NODE_TYPES } from '@typescript-eslint/utils';
3-
import * as VAR from '@eslint-react/var';
3+
import { _ } from '@eslint-react/eff';
4+
import { findVariable } from '@eslint-react/var';
5+
import { AST_NODE_TYPES as AST_NODE_TYPES$1 } from '@typescript-eslint/types';
46
import { nullThrows, NullThrowsReasons } from '@typescript-eslint/utils/eslint-utils';
57

68
// package.json
@@ -10,6 +12,40 @@ function getDocsUrl() {
1012
return "TODO: add docs for local ESLint rules";
1113
}
1214
var createRule = ESLintUtils.RuleCreator(getDocsUrl);
15+
function isInitializedFromSource(name2, source, initialScope) {
16+
const latestDef = findVariable(name2, initialScope)?.defs.at(-1);
17+
if (latestDef == null) return false;
18+
const { node, parent } = latestDef;
19+
if (node.type === AST_NODE_TYPES$1.VariableDeclarator && node.init != null) {
20+
const { init } = node;
21+
if (init.type === AST_NODE_TYPES$1.MemberExpression && init.object.type === AST_NODE_TYPES$1.Identifier) {
22+
return isInitializedFromSource(init.object.name, source, initialScope);
23+
}
24+
if (init.type === AST_NODE_TYPES$1.Identifier) {
25+
return isInitializedFromSource(init.name, source, initialScope);
26+
}
27+
const args = getRequireExpressionArguments(init);
28+
const arg0 = args?.[0];
29+
if (arg0 == null || !AST.isStringLiteral(arg0)) {
30+
return false;
31+
}
32+
return arg0.value === source || arg0.value.startsWith(`${source}/`);
33+
}
34+
return parent?.type === AST_NODE_TYPES$1.ImportDeclaration && parent.source.value === source;
35+
}
36+
function getRequireExpressionArguments(node) {
37+
switch (true) {
38+
// require('source')
39+
case (node.type === AST_NODE_TYPES$1.CallExpression && node.callee.type === AST_NODE_TYPES$1.Identifier && node.callee.name === "require"): {
40+
return node.arguments;
41+
}
42+
// require('source').variable
43+
case node.type === AST_NODE_TYPES$1.MemberExpression: {
44+
return getRequireExpressionArguments(node.object);
45+
}
46+
}
47+
return _;
48+
}
1349

1450
// src/rules/avoid-multiline-template-expression.ts
1551
var RULE_NAME = "avoid-multiline-template-expression";
@@ -43,6 +79,8 @@ var avoid_multiline_template_expression_default = createRule({
4379
},
4480
defaultOptions: []
4581
});
82+
83+
// src/rules/no-shadow-underscore.ts
4684
var RULE_NAME2 = "no-shadow-underscore";
4785
var RULE_FEATURES2 = [
4886
"CHK"
@@ -64,7 +102,7 @@ var no_shadow_underscore_default = createRule({
64102
return {
65103
"Identifier[name='_']"(node) {
66104
const initialScope = context.sourceCode.getScope(node);
67-
const isFromImport = VAR.isInitializedFromSource("_", "@eslint-react/eff", initialScope);
105+
const isFromImport = isInitializedFromSource("_", "@eslint-react/eff", initialScope);
68106
if (!isFromImport) {
69107
context.report({
70108
messageId: "noShadowUnderscore",

.pkgs/eslint-plugin-local/package.json

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@
2525
"@eslint-react/eff": "workspace:*",
2626
"@eslint-react/shared": "workspace:*",
2727
"@eslint-react/var": "workspace:*",
28-
"@typescript-eslint/scope-manager": "^8.24.1",
29-
"@typescript-eslint/type-utils": "^8.24.1",
30-
"@typescript-eslint/types": "^8.24.1",
31-
"@typescript-eslint/utils": "^8.24.1",
28+
"@typescript-eslint/scope-manager": "^8.25.0",
29+
"@typescript-eslint/type-utils": "^8.25.0",
30+
"@typescript-eslint/types": "^8.25.0",
31+
"@typescript-eslint/utils": "^8.25.0",
3232
"string-ts": "^2.2.1",
3333
"ts-pattern": "^5.6.2"
3434
},

.pkgs/eslint-plugin-local/src/rules/no-shadow-underscore.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import type { RuleFeature } from "@eslint-react/shared";
2-
import * as VAR from "@eslint-react/var";
32
import type { TSESTree } from "@typescript-eslint/types";
43
import type { CamelCase } from "string-ts";
54

6-
import { createRule } from "../utils";
5+
import { createRule, isInitializedFromSource } from "../utils";
76

87
export const RULE_NAME = "no-shadow-underscore";
98

@@ -30,7 +29,7 @@ export default createRule<[], MessageID>({
3029
return {
3130
"Identifier[name='_']"(node: TSESTree.Identifier & { name: "_" }) {
3231
const initialScope = context.sourceCode.getScope(node);
33-
const isFromImport = VAR.isInitializedFromSource("_", "@eslint-react/eff", initialScope);
32+
const isFromImport = isInitializedFromSource("_", "@eslint-react/eff", initialScope);
3433
if (!isFromImport) {
3534
context.report({
3635
messageId: "noShadowUnderscore",
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from "./create-rule";
2+
export * from "./is-initialized-from-source";
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import * as AST from "@eslint-react/ast";
2+
import { _ } from "@eslint-react/eff";
3+
import { findVariable } from "@eslint-react/var";
4+
import type { Scope } from "@typescript-eslint/scope-manager";
5+
import type { TSESTree } from "@typescript-eslint/types";
6+
import { AST_NODE_TYPES as T } from "@typescript-eslint/types";
7+
8+
/**
9+
* Check if an identifier is initialized from the given source
10+
* @param name The top-level identifier's name
11+
* @param source The import source to check against
12+
* @param initialScope Initial scope to search for the identifier
13+
* @returns Whether the identifier is initialized from the given source
14+
*/
15+
export function isInitializedFromSource(
16+
name: string,
17+
source: string,
18+
initialScope: Scope,
19+
): boolean {
20+
const latestDef = findVariable(name, initialScope)?.defs.at(-1);
21+
if (latestDef == null) return false;
22+
const { node, parent } = latestDef;
23+
if (node.type === T.VariableDeclarator && node.init != null) {
24+
const { init } = node;
25+
// check for: `variable = Source.variable`
26+
if (init.type === T.MemberExpression && init.object.type === T.Identifier) {
27+
return isInitializedFromSource(init.object.name, source, initialScope);
28+
}
29+
// check for: `{ variable } = Source`
30+
if (init.type === T.Identifier) {
31+
return isInitializedFromSource(init.name, source, initialScope);
32+
}
33+
// check for: `variable = require('source')` or `variable = require('source').variable`
34+
const args = getRequireExpressionArguments(init);
35+
const arg0 = args?.[0];
36+
if (arg0 == null || !AST.isStringLiteral(arg0)) {
37+
return false;
38+
}
39+
// check for: `require('source')` or `require('source/...')`
40+
return arg0.value === source
41+
|| arg0
42+
.value
43+
.startsWith(`${source}/`);
44+
}
45+
// latest definition is an import declaration: import { variable } from 'source'
46+
return parent?.type === T.ImportDeclaration && parent.source.value === source;
47+
}
48+
49+
function getRequireExpressionArguments(node: TSESTree.Node): TSESTree.CallExpressionArgument[] | _ {
50+
switch (true) {
51+
// require('source')
52+
case node.type === T.CallExpression
53+
&& node.callee.type === T.Identifier
54+
&& node.callee.name === "require": {
55+
return node.arguments;
56+
}
57+
// require('source').variable
58+
case node.type === T.MemberExpression: {
59+
return getRequireExpressionArguments(node.object);
60+
}
61+
}
62+
return _;
63+
}

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
1.27.1-beta.6
1+
1.27.1-beta.8

apps/website/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,6 @@
5656
"postcss": "^8.5.3",
5757
"tailwindcss": "^4.0.8",
5858
"typescript": "^5.7.3",
59-
"typescript-eslint": "^8.24.1"
59+
"typescript-eslint": "^8.25.0"
6060
}
6161
}

examples/dual-react-dom-lib/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@
4747
"react": "^19.0.0",
4848
"tsup": "^8.3.6",
4949
"typescript": "^5.7.3",
50-
"typescript-eslint": "^8.24.1"
50+
"typescript-eslint": "^8.25.0"
5151
},
5252
"peerDependencies": {
5353
"react": "^19.0.0"

examples/next-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
"eslint-plugin-react-hooks": "^5.1.0",
3030
"eslint-plugin-react-refresh": "^0.4.19",
3131
"typescript": "^5.7.3",
32-
"typescript-eslint": "^8.24.1"
32+
"typescript-eslint": "^8.25.0"
3333
},
3434
"engines": {
3535
"node": ">=18.18.0"

examples/vite-react-dom-app/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828
"eslint-plugin-react-hooks": "^5.1.0",
2929
"eslint-plugin-react-refresh": "^0.4.19",
3030
"typescript": "^5.7.3",
31-
"typescript-eslint": "^8.24.1",
31+
"typescript-eslint": "^8.25.0",
3232
"vite": "^6.1.1"
3333
},
3434
"engines": {

0 commit comments

Comments
 (0)