Explorar o código

Upgrade to ESLint 9 + share eslint config across workspaces (#3815)

Chris Estreich hai 7 meses
pai
achega
d5484b52fa

+ 0 - 4
.gitignore

@@ -30,10 +30,6 @@ docs/_site/
 .env.*
 !.env.*.sample
 
-
-# Local lint config
-.eslintrc.local.json
-
 # Logging
 logs
 

+ 1 - 0
.husky/pre-commit

@@ -28,3 +28,4 @@ else
 fi
 
 "$npx_cmd" lint-staged
+"$pnpm_cmd" lint

+ 1 - 1
.husky/pre-push

@@ -12,7 +12,7 @@ else
   pnpm_cmd="pnpm"
 fi
 
-"$pnpm_cmd" run lint check-types
+"$pnpm_cmd" run check-types
 
 # Check for new changesets.
 NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ')

+ 0 - 25
apps/vscode-nightly/.eslintrc.json

@@ -1,25 +0,0 @@
-{
-	"root": true,
-	"parser": "@typescript-eslint/parser",
-	"parserOptions": {
-		"ecmaVersion": 6,
-		"sourceType": "module"
-	},
-	"plugins": ["@typescript-eslint"],
-	"rules": {
-		"@typescript-eslint/naming-convention": [
-			"warn",
-			{
-				"selector": "import",
-				"format": ["camelCase", "PascalCase"]
-			}
-		],
-		"@typescript-eslint/semi": "off",
-		"no-unused-vars": "off",
-		"@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
-		"eqeqeq": "warn",
-		"no-throw-literal": "warn",
-		"semi": "off"
-	},
-	"ignorePatterns": ["dist"]
-}

+ 0 - 23
e2e/.eslintrc.json

@@ -1,23 +0,0 @@
-{
-	"root": true,
-	"parser": "@typescript-eslint/parser",
-	"parserOptions": {
-		"ecmaVersion": 6,
-		"sourceType": "module"
-	},
-	"plugins": ["@typescript-eslint"],
-	"rules": {
-		"@typescript-eslint/naming-convention": [
-			"warn",
-			{
-				"selector": "import",
-				"format": ["camelCase", "PascalCase"]
-			}
-		],
-		"@typescript-eslint/semi": "off",
-		"eqeqeq": "warn",
-		"no-throw-literal": "warn",
-		"semi": "off"
-	},
-	"ignorePatterns": ["out"]
-}

+ 4 - 0
e2e/eslint.config.mjs

@@ -0,0 +1,4 @@
+import { config } from "@roo-code/config-eslint/base"
+
+/** @type {import("eslint").Linter.Config} */
+export default [...config]

+ 3 - 1
e2e/package.json

@@ -2,7 +2,7 @@
 	"name": "@roo-code/vscode-e2e",
 	"private": true,
 	"scripts": {
-		"lint": "eslint src/**/*.ts --max-warnings=0",
+		"lint": "eslint **/*.ts --max-warnings=0",
 		"check-types": "tsc --noEmit",
 		"format": "prettier --write src",
 		"test:ci": "pnpm --filter roo-cline build:development && pnpm test:run",
@@ -10,6 +10,8 @@
 		"clean": "rimraf out .turbo"
 	},
 	"devDependencies": {
+		"@roo-code/config-eslint": "workspace:^",
+		"@roo-code/config-typescript": "workspace:^",
 		"@roo-code/types": "^1.12.0",
 		"@types/mocha": "^10.0.10",
 		"@types/node": "^22.14.1",

+ 1 - 13
package.json

@@ -23,7 +23,7 @@
 		"@dotenvx/dotenvx": "^1.34.0",
 		"@vscode/vsce": "3.3.2",
 		"esbuild": "^0.25.0",
-		"eslint": "^8.57.0",
+		"eslint": "^9.27.0",
 		"husky": "^9.1.7",
 		"knip": "^5.44.4",
 		"lint-staged": "^15.2.11",
@@ -38,18 +38,6 @@
 	"lint-staged": {
 		"*.{js,jsx,ts,tsx,json,css,md}": [
 			"prettier --write"
-		],
-		"src/**/*.{ts,tsx}": [
-			"npx eslint -c src/.eslintrc.json --max-warnings=0 --fix"
-		],
-		"webview-ui/**/*.{ts,tsx}": [
-			"npx eslint -c webview-ui/.eslintrc.json --max-warnings=0 --fix"
-		],
-		"e2e/**/*.{ts,tsx}": [
-			"npx eslint -c src/.eslintrc.json --max-warnings=0 --fix"
-		],
-		"{apps,packages}/**/*.{ts,tsx}": [
-			"npx eslint --max-warnings=0 --fix"
 		]
 	}
 }

+ 0 - 25
packages/build/.eslintrc.json

@@ -1,25 +0,0 @@
-{
-	"root": true,
-	"parser": "@typescript-eslint/parser",
-	"parserOptions": {
-		"ecmaVersion": 6,
-		"sourceType": "module"
-	},
-	"plugins": ["@typescript-eslint"],
-	"rules": {
-		"@typescript-eslint/naming-convention": [
-			"warn",
-			{
-				"selector": "import",
-				"format": ["camelCase", "PascalCase"]
-			}
-		],
-		"@typescript-eslint/semi": "off",
-		"no-unused-vars": "off",
-		"@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
-		"eqeqeq": "warn",
-		"no-throw-literal": "warn",
-		"semi": "off"
-	},
-	"ignorePatterns": ["dist"]
-}

+ 4 - 0
packages/build/eslint.config.mjs

@@ -0,0 +1,4 @@
+import { config } from "@roo-code/config-eslint/base"
+
+/** @type {import("eslint").Linter.Config} */
+export default [...config]

+ 8 - 5
packages/build/package.json

@@ -3,19 +3,22 @@
 	"description": "ESBuild utilities for Roo Code.",
 	"private": true,
 	"type": "module",
-	"exports": "./dist/index.js",
+	"main": "./dist/index.js",
+	"types": "./src/index.ts",
 	"scripts": {
-		"lint": "eslint src --ext .ts,.tsx --max-warnings=0",
+		"lint": "eslint src/**/*.ts --max-warnings=0",
 		"check-types": "tsc --noEmit",
 		"test": "vitest --globals --run",
 		"build": "tsc",
 		"clean": "rimraf dist .turbo"
 	},
+	"dependencies": {
+		"zod": "^3.24.2"
+	},
 	"devDependencies": {
+		"@roo-code/config-eslint": "workspace:^",
+		"@roo-code/config-typescript": "workspace:^",
 		"@types/node": "^22.15.20",
 		"vitest": "^3.1.3"
-	},
-	"dependencies": {
-		"zod": "^3.24.2"
 	}
 }

+ 4 - 18
packages/build/tsconfig.json

@@ -1,22 +1,8 @@
 {
-	"$schema": "https://json.schemastore.org/tsconfig",
+	"extends": "@roo-code/config-typescript/base.json",
 	"compilerOptions": {
-		"declaration": true,
-		"declarationMap": true,
-		"esModuleInterop": true,
-		"incremental": false,
-		"isolatedModules": true,
-		"lib": ["es2022", "DOM", "DOM.Iterable"],
-		"module": "NodeNext",
-		"moduleDetection": "force",
-		"moduleResolution": "NodeNext",
-		"noUncheckedIndexedAccess": true,
-		"resolveJsonModule": true,
-		"skipLibCheck": true,
-		"strict": true,
-		"target": "ES2022",
-		"types": ["vitest/globals"],
-		"outDir": "dist"
+		"types": ["vitest/globals"]
 	},
-	"include": ["src"]
+	"include": ["src"],
+	"exclude": ["node_modules"]
 }

+ 44 - 0
packages/config-eslint/base.js

@@ -0,0 +1,44 @@
+import js from "@eslint/js"
+import eslintConfigPrettier from "eslint-config-prettier"
+import turboPlugin from "eslint-plugin-turbo"
+import tseslint from "typescript-eslint"
+import onlyWarn from "eslint-plugin-only-warn"
+
+/**
+ * A shared ESLint configuration for the repository.
+ *
+ * @type {import("eslint").Linter.Config[]}
+ * */
+export const config = [
+	js.configs.recommended,
+	eslintConfigPrettier,
+	...tseslint.configs.recommended,
+	{
+		plugins: {
+			turbo: turboPlugin,
+		},
+		rules: {
+			"turbo/no-undeclared-env-vars": "off",
+		},
+	},
+	{
+		plugins: {
+			onlyWarn,
+		},
+	},
+	{
+		ignores: ["dist/**"],
+	},
+	{
+		rules: {
+			"@typescript-eslint/no-unused-vars": [
+				"error",
+				{
+					argsIgnorePattern: "^_",
+					varsIgnorePattern: "^_",
+					caughtErrorsIgnorePattern: "^_",
+				},
+			],
+		},
+	},
+]

+ 19 - 0
packages/config-eslint/next.js

@@ -0,0 +1,19 @@
+import pluginNext from "@next/eslint-plugin-next"
+
+import { reactConfig } from "./react.js"
+
+/**
+ * @type {import("eslint").Linter.Config[]}
+ */
+export const nextJsConfig = [
+	...reactConfig,
+	{
+		plugins: {
+			"@next/next": pluginNext,
+		},
+		rules: {
+			...pluginNext.configs.recommended.rules,
+			...pluginNext.configs["core-web-vitals"].rules,
+		},
+	},
+]

+ 22 - 0
packages/config-eslint/package.json

@@ -0,0 +1,22 @@
+{
+	"name": "@roo-code/config-eslint",
+	"private": true,
+	"type": "module",
+	"exports": {
+		"./base": "./base.js",
+		"./react": "./react.js",
+		"./next-js": "./next.js"
+	},
+	"devDependencies": {
+		"@eslint/js": "^9.22.0",
+		"@next/eslint-plugin-next": "^15.2.1",
+		"eslint": "^9.27.0",
+		"eslint-config-prettier": "^10.1.1",
+		"eslint-plugin-only-warn": "^1.1.0",
+		"eslint-plugin-react": "^7.37.4",
+		"eslint-plugin-react-hooks": "^5.2.0",
+		"eslint-plugin-turbo": "^2.4.4",
+		"globals": "^16.0.0",
+		"typescript-eslint": "^8.26.0"
+	}
+}

+ 38 - 0
packages/config-eslint/react.js

@@ -0,0 +1,38 @@
+import js from "@eslint/js"
+import eslintConfigPrettier from "eslint-config-prettier"
+import typescriptEslint from "typescript-eslint"
+import pluginReactHooks from "eslint-plugin-react-hooks"
+import pluginReact from "eslint-plugin-react"
+import globals from "globals"
+
+import { config } from "./base.js"
+
+/**
+ * @type {import("eslint").Linter.Config[]}
+ */
+export const reactConfig = [
+	...config,
+	js.configs.recommended,
+	eslintConfigPrettier,
+	...typescriptEslint.configs.recommended,
+	{
+		...pluginReact.configs.flat.recommended,
+		languageOptions: {
+			...pluginReact.configs.flat.recommended.languageOptions,
+			globals: {
+				...globals.serviceworker,
+			},
+		},
+	},
+	{
+		plugins: {
+			"react-hooks": pluginReactHooks,
+		},
+		settings: { react: { version: "detect" } },
+		rules: {
+			...pluginReactHooks.configs.recommended.rules,
+			// React scope no longer necessary with new JSX transform.
+			"react/react-in-jsx-scope": "off",
+		},
+	},
+]

+ 19 - 0
packages/config-typescript/base.json

@@ -0,0 +1,19 @@
+{
+	"$schema": "https://json.schemastore.org/tsconfig",
+	"compilerOptions": {
+		"declaration": true,
+		"declarationMap": true,
+		"esModuleInterop": true,
+		"incremental": false,
+		"isolatedModules": true,
+		"lib": ["es2022", "DOM", "DOM.Iterable"],
+		"module": "NodeNext",
+		"moduleDetection": "force",
+		"moduleResolution": "NodeNext",
+		"noUncheckedIndexedAccess": true,
+		"resolveJsonModule": true,
+		"skipLibCheck": true,
+		"strict": true,
+		"target": "ES2022"
+	}
+}

+ 14 - 0
packages/config-typescript/cjs.json

@@ -0,0 +1,14 @@
+{
+	"$schema": "https://json.schemastore.org/tsconfig",
+	"compilerOptions": {
+		"module": "CommonJS",
+		"moduleResolution": "Node",
+		"esModuleInterop": true,
+		"target": "ES2022",
+		"lib": ["ES2022", "ESNext.Disposable", "DOM"],
+		"sourceMap": true,
+		"strict": true,
+		"skipLibCheck": true,
+		"useUnknownInCatchVariables": false
+	}
+}

+ 12 - 0
packages/config-typescript/nextjs.json

@@ -0,0 +1,12 @@
+{
+	"$schema": "https://json.schemastore.org/tsconfig",
+	"extends": "./base.json",
+	"compilerOptions": {
+		"plugins": [{ "name": "next" }],
+		"module": "ESNext",
+		"moduleResolution": "bundler",
+		"allowJs": true,
+		"jsx": "preserve",
+		"noEmit": true
+	}
+}

+ 7 - 0
packages/config-typescript/package.json

@@ -0,0 +1,7 @@
+{
+	"name": "@roo-code/config-typescript",
+	"private": true,
+	"publishConfig": {
+		"access": "public"
+	}
+}

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 164 - 643
pnpm-lock.yaml


+ 0 - 25
src/.eslintrc.json

@@ -1,25 +0,0 @@
-{
-	"root": true,
-	"parser": "@typescript-eslint/parser",
-	"parserOptions": {
-		"ecmaVersion": 6,
-		"sourceType": "module"
-	},
-	"plugins": ["@typescript-eslint"],
-	"rules": {
-		"@typescript-eslint/naming-convention": [
-			"warn",
-			{
-				"selector": "import",
-				"format": ["camelCase", "PascalCase"]
-			}
-		],
-		"@typescript-eslint/semi": "off",
-		"no-unused-vars": "off",
-		"@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }],
-		"eqeqeq": "warn",
-		"no-throw-literal": "warn",
-		"semi": "off"
-	},
-	"ignorePatterns": ["out", "dist", "**/*.d.ts", "!roo-code.d.ts"]
-}

+ 30 - 0
src/eslint.config.mjs

@@ -0,0 +1,30 @@
+import { config } from "@roo-code/config-eslint/base"
+
+/** @type {import("eslint").Linter.Config} */
+export default [
+	...config,
+	{
+		rules: {
+			"@typescript-eslint/no-unused-vars": "off",
+			"@typescript-eslint/no-explicit-any": "off",
+		},
+	},
+	{
+		files: ["i18n/setup.ts", "utils/tts.ts"],
+		rules: {
+			"@typescript-eslint/no-require-imports": "off",
+		},
+	},
+	{
+		files: ["shared/support-prompt.ts"],
+		rules: {
+			"no-prototype-builtins": "off",
+		},
+	},
+	{
+		files: ["shared/combineApiRequests.ts", "utils/tts.ts"],
+		rules: {
+			"no-empty": "off",
+		},
+	},
+]

+ 3 - 4
src/package.json

@@ -318,7 +318,7 @@
 		}
 	},
 	"scripts": {
-		"lint": "eslint **/*.ts",
+		"lint": "eslint **/*.ts --max-warnings=0",
 		"check-types": "tsc --noEmit",
 		"pretest": "pnpm bundle",
 		"test": "jest -w=40% && vitest run",
@@ -400,6 +400,8 @@
 		"@changesets/cli": "^2.27.10",
 		"@changesets/types": "^6.0.0",
 		"@jest/globals": "^29.7.0",
+		"@roo-code/config-eslint": "workspace:^",
+		"@roo-code/config-typescript": "workspace:^",
 		"@roo-code/build": "workspace:^",
 		"@types/clone-deep": "^4.0.4",
 		"@types/debug": "^4.1.12",
@@ -416,12 +418,9 @@
 		"@types/tmp": "^0.2.6",
 		"@types/turndown": "^5.0.5",
 		"@types/vscode": "^1.84.0",
-		"@typescript-eslint/eslint-plugin": "^7.14.1",
-		"@typescript-eslint/parser": "^7.11.0",
 		"@vscode/test-electron": "^2.5.2",
 		"@vscode/vsce": "3.3.2",
 		"esbuild": "^0.25.0",
-		"eslint": "^8.57.0",
 		"execa": "^9.5.2",
 		"glob": "^11.0.1",
 		"jest": "^29.7.0",

+ 2 - 2
src/utils/config.ts

@@ -14,9 +14,9 @@ export async function injectEnv(config: string | Record<PropertyKey, any>, notFo
 	_config = _config.replace(/\$\{env:([\w]+)\}/g, (_, name) => {
 		// Check if null or undefined
 		// intentionally using == to match null | undefined
-		// eslint-disable-next-line eqeqeq
-		if (process.env[name] == null)
+		if (process.env[name] == null) {
 			console.warn(`[injectEnv] env variable ${name} referenced but not found in process.env`)
+		}
 
 		return process.env[name] ?? notFoundValue
 	})

+ 0 - 17
webview-ui/.eslintrc.json

@@ -1,17 +0,0 @@
-{
-	"extends": "react-app",
-	"ignorePatterns": ["!.storybook"],
-	"rules": {
-		"no-unused-vars": "off",
-		"@typescript-eslint/no-unused-vars": ["error", { "varsIgnorePattern": "^_", "argsIgnorePattern": "^_" }]
-	},
-	"overrides": [
-		{
-			"files": ["webview-ui/src/__tests__/utils/command-validation.test.ts"],
-			"rules": {
-				"no-template-curly-in-string": "off",
-				"no-useless-escape": "off"
-			}
-		}
-	]
-}

+ 18 - 0
webview-ui/eslint.config.mjs

@@ -0,0 +1,18 @@
+import { reactConfig } from "@roo-code/config-eslint/react"
+
+/** @type {import("eslint").Linter.Config} */
+export default [
+	...reactConfig,
+	{
+		rules: {
+			"@typescript-eslint/no-unused-vars": "off",
+			"@typescript-eslint/no-explicit-any": "off",
+		},
+	},
+	{
+		files: ["src/utils/context-mentions.ts", "src/utils/highlighter.ts"],
+		rules: {
+			"prefer-const": "off",
+		},
+	},
+]

+ 3 - 7
webview-ui/package.json

@@ -3,7 +3,7 @@
 	"private": true,
 	"type": "module",
 	"scripts": {
-		"lint": "eslint src --ext .ts,.tsx --max-warnings=0",
+		"lint": "eslint src/**/*.{ts,tsx} --max-warnings=0",
 		"check-types": "tsc",
 		"test": "jest -w=40%",
 		"format": "prettier --write src",
@@ -74,6 +74,8 @@
 	},
 	"devDependencies": {
 		"@jest/globals": "^29.7.0",
+		"@roo-code/config-eslint": "workspace:^",
+		"@roo-code/config-typescript": "workspace:^",
 		"@roo-code/build": "workspace:^",
 		"@storybook/addon-essentials": "^8.5.6",
 		"@storybook/blocks": "^8.5.6",
@@ -89,13 +91,7 @@
 		"@types/shell-quote": "^1.7.5",
 		"@types/testing-library__jest-dom": "^5.14.5",
 		"@types/vscode-webview": "^1.57.5",
-		"@typescript-eslint/eslint-plugin": "^6.21.0",
-		"@typescript-eslint/parser": "^6.21.0",
 		"@vitejs/plugin-react": "^4.3.4",
-		"eslint-config-react-app": "^7.0.1",
-		"eslint-plugin-react": "^7.33.2",
-		"eslint-plugin-react-hooks": "^4.6.0",
-		"eslint-plugin-storybook": "^0.12.0",
 		"identity-obj-proxy": "^3.0.0",
 		"jest": "^29.7.0",
 		"jest-environment-jsdom": "^29.7.0",

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio