chakra-ui / eslint-plugin-panda

Official ESLint Plugin for Panda CSS
71 stars 5 forks source link

Plugin's unbearably slow #160

Open Faithfinder opened 5 days ago

Faithfinder commented 5 days ago

Here's the result of running linter with TIMING=1 on our codebase with panda recommended ruleset enabled

Rule                                            |  Time (ms) | Relative
:-----------------------------------------------|-----------:|--------:
@pandacss/no-invalid-token-paths                | 218124.183 |    27.8%
@pandacss/no-hardcoded-color                    | 167018.338 |    21.3%
@pandacss/no-unsafe-token-fn-usage              | 161571.479 |    20.6%
@pandacss/no-property-renaming                  | 126184.392 |    16.1%
@pandacss/no-dynamic-styling                    |  98082.907 |    12.5%
@typescript-eslint/no-confusing-void-expression |   2837.370 |     0.4%
@pandacss/file-not-included                     |   2297.380 |     0.3%
@typescript-eslint/no-misused-promises          |   1660.920 |     0.2%
@typescript-eslint/no-unused-vars               |   1032.843 |     0.1%
react/no-direct-mutation-state                  |    890.197 |     0.1%

Here's without, for comparison:

Rule                                            | Time (ms) | Relative
:-----------------------------------------------|----------:|--------:
@typescript-eslint/no-confusing-void-expression |  2371.804 |    29.4%
@typescript-eslint/no-misused-promises          |  1178.439 |    14.6%
@typescript-eslint/promise-function-async       |   673.703 |     8.4%
@typescript-eslint/no-unused-vars               |   634.428 |     7.9%
react/no-direct-mutation-state                  |   562.129 |     7.0%
react/prefer-stateless-function                 |   348.301 |     4.3%
react/require-render-return                     |   294.588 |     3.7%
no-redeclare                                    |   256.820 |     3.2%
react/no-unknown-property                       |   196.698 |     2.4%
react-hooks/rules-of-hooks                      |   113.093 |     1.4%
anubra266 commented 5 days ago

@Faithfinder Could you give more context on your project that might help reproduce. I've got something like:

1:

✖ 33 problems (13 errors, 20 warnings)

Rule                                   | Time (ms) | Relative
:--------------------------------------|----------:|--------:
@pandacss/file-not-included            |   498.770 |    85.9%
@pandacss/no-physical-properties       |    13.915 |     2.4%
@pandacss/no-margin-properties         |    13.809 |     2.4%
@pandacss/no-hardcoded-color           |    11.742 |     2.0%
@pandacss/no-invalid-token-paths       |     9.603 |     1.7%
@pandacss/no-unsafe-token-fn-usage     |     9.245 |     1.6%
@typescript-eslint/no-unused-vars      |     5.765 |     1.0%
@pandacss/no-dynamic-styling           |     4.017 |     0.7%
@pandacss/no-config-function-in-source |     3.321 |     0.6%

2:

Rule                                   | Time (ms) | Relative
:--------------------------------------|----------:|--------:
@pandacss/file-not-included            |   574.780 |    97.8%
@typescript-eslint/no-unused-vars      |     2.458 |     0.4%
@pandacss/no-margin-properties         |     1.336 |     0.2%
@pandacss/no-unsafe-token-fn-usage     |     1.277 |     0.2%
@pandacss/no-config-function-in-source |     0.996 |     0.2%
@pandacss/no-hardcoded-color           |     0.768 |     0.1%
@pandacss/no-invalid-token-paths       |     0.691 |     0.1%
no-control-regex                       |     0.544 |     0.1%
no-misleading-character-class          |     0.442 |     0.1%
Faithfinder commented 5 days ago

Huh. Well, I don't think I can give you a repro, as that's a closed-source project, but from a technical perspective, it's nothing too special.

import globals from "globals";
import pluginJs from "@eslint/js";
import comments from "@eslint-community/eslint-plugin-eslint-comments/configs";
import pluginTs from "typescript-eslint";
import pluginReact from "eslint-plugin-react";
import hooksPlugin from "eslint-plugin-react-hooks";
// import panda from "@pandacss/eslint-plugin";

export default pluginTs.config(
  {
    name: "settings",
    languageOptions: {
      globals: { ...globals.browser },
      parserOptions: {
        project: ["tsconfig.json", "tsconfig.test.json"],
        tsconfigRootDir: import.meta.dirname,
      },
    },
    settings: {
      react: {
        version: "detect",
      },
    },
  },
  pluginJs.configs.recommended,
  ...pluginTs.configs.recommendedTypeChecked,
  pluginReact.configs.flat.recommended,
  comments.recommended,
  // {
  //   name: "Panda CSS",
  //   plugins: {
  //     "@pandacss": panda,
  //   },
  //   rules: {
  //     ...panda.configs.recommended.rules,
  //   },
  // },
  {
    name: "React Hooks",
    plugins: {
      "react-hooks": hooksPlugin,
    },
    rules: hooksPlugin.configs.recommended.rules,
  },
  {
    name: "Disable bad recommendations, enable missing useful rules",
    rules: {
      "no-multi-assign": "error",
      "no-return-assign": ["error", "always"],
      "require-atomic-updates": "error",
      eqeqeq: ["error", "always", { null: "ignore" }],
      "no-console": "warn",
      "no-lonely-if": "warn",
      "no-sequences": "warn",
      "no-unneeded-ternary": "warn",
      "no-var": "error",
      "prefer-const": ["warn", { destructuring: "all" }],
      "prefer-object-has-own": "warn",
      "no-restricted-imports": [
        "error",
        {
          paths: [
            {
              name: "react-redux",
              importNames: ["useSelector", "useDispatch", "useStore"],
              message: "Please use version in `src/redux/hooks.ts` instead",
            },
          ],
        },
      ],

      "@typescript-eslint/no-unsafe-argument": "off",
      "@typescript-eslint/no-unsafe-return": "off",
      "@typescript-eslint/no-unsafe-member-access": "off",
      "@typescript-eslint/no-unsafe-call": "off",
      "@typescript-eslint/no-unsafe-assignment": "off",
      "@typescript-eslint/no-unused-expressions": [
        "error",
        { allowShortCircuit: true, allowTernary: true, enforceForJSX: true },
      ],
      "@typescript-eslint/no-misused-promises": [
        "error",
        {
          checksVoidReturn: {
            arguments: false,
            attributes: false,
          },
        },
      ],
      "@typescript-eslint/consistent-type-exports": ["error", { fixMixedExportsWithInlineTypeSpecifier: true }],
      "@typescript-eslint/consistent-type-imports": ["error", { fixStyle: "inline-type-imports" }],
      "@typescript-eslint/no-confusing-void-expression": [
        "warn",
        { ignoreArrowShorthand: true, ignoreVoidOperator: true },
      ],
      "@typescript-eslint/no-loop-func": "error",
      "@typescript-eslint/no-require-imports": "error",
      "@typescript-eslint/no-unnecessary-condition": "error",
      "@typescript-eslint/only-throw-error": [
        "error",
        {
          allowThrowingAny: true,
          allowThrowingUnknown: true,
        },
      ],
      "@typescript-eslint/prefer-find": "warn",
      "@typescript-eslint/prefer-includes": "warn",
      "@typescript-eslint/prefer-return-this-type": "error",
      "@typescript-eslint/prefer-ts-expect-error": "error",
      "@typescript-eslint/promise-function-async": "error",
      "@typescript-eslint/require-array-sort-compare": "error",
      "@typescript-eslint/return-await": ["error", "always"],
      "@typescript-eslint/no-empty-function": ["error", { allow: ["private-constructors", "protected-constructors"] }],
      "@typescript-eslint/no-unused-vars": ["warn", { ignoreRestSiblings: true }],
      "@typescript-eslint/no-use-before-define": [
        "error",
        { functions: false, typedefs: false, enums: false, variables: false },
      ],

      "react/prop-types": "off",
      "react/jsx-no-constructed-context-values": "warn",
      "react/jsx-key": [
        "error",
        {
          checkFragmentShorthand: true,
          checkKeyMustBeforeSpread: true,
          warnOnDuplicates: true,
        },
      ],
      "react/button-has-type": "error",
      "react/hook-use-state": "error",
      "react/jsx-fragments": "warn",
      "react/jsx-no-useless-fragment": ["warn", { allowExpressions: true }],
      "react/jsx-pascal-case": ["warn", { allowNamespace: true }],
      "react/react-in-jsx-scope": "off",
      "react/jsx-uses-react": "off",
      "react/no-unused-class-component-methods": "error",
      "react/prefer-stateless-function": "warn",

      "@eslint-community/eslint-comments/disable-enable-pair": ["error", { allowWholeFile: true }],
    },
  },
  {
    name: "Undesired disables",
    // Disabled during initial linting setup for violations, enable one by one
    // Comment out this section and run `pnpm eslint src -f summary`
    // to see a summary and choose with lower number for easier fixes
    rules: {
      "@typescript-eslint/no-empty-function": "off",
      "react/button-has-type": "off",
      "react/display-name": "off",
      "react/hook-use-state": "off",
      "react/jsx-no-constructed-context-values": "off",
      "react/jsx-pascal-case": "off",
      "react/no-children-prop": "off",
      "react/no-unescaped-entities": "off",
      "require-atomic-updates": "off",
    },
  },
  {
    files: ["src/**/*.js?(x)"],
    rules: {
      ...pluginTs.configs.disableTypeChecked.rules,
    },
  },
);

PC stats ```plaintext Model Name: MacBook Pro Model Identifier: Mac15,7 Model Number: MRW13LL/A Chip: Apple M3 Pro Total Number of Cores: 12 (6 performance and 6 efficiency) Memory: 18 GB ```

Anything in particular I can tell you that's not a repo dump?

anubra266 commented 5 days ago

@Faithfinder Didn't have anything particular in mind. Was just looking out for any major differences in your project

anubra266 commented 5 days ago

In the mean time @Faithfinder I'll look into some optimizations like memoization.

Faithfinder commented 5 days ago

I'm happy to share configs or run a diagnostic if you ask me to, but IMO just one rule @pandacss/no-invalid-token-paths taking 3 minutes when the whole build of the app is 1.5 minutes means there's something very wrong on a code path somewhere.

anubra266 commented 5 days ago

@Faithfinder Did some improvements. Let me know if this has any impact

https://github.com/chakra-ui/eslint-plugin-panda/releases/tag/%40pandacss/eslint-plugin%400.2.0

Faithfinder commented 4 days ago

Looks like a big improvement, but not enough for it to become usable:

Rule                                            |  Time (ms) | Relative
:-----------------------------------------------|-----------:|--------:
@pandacss/no-hardcoded-color                    | 111674.958 |    22.1%
@pandacss/no-unsafe-token-fn-usage              | 107499.765 |    21.2%
@pandacss/no-invalid-token-paths                | 102651.342 |    20.3%
@pandacss/no-dynamic-styling                    |  93657.633 |    18.5%
@pandacss/no-property-renaming                  |  77170.474 |    15.2%
@pandacss/file-not-included                     |   4092.441 |     0.8%
@typescript-eslint/no-confusing-void-expression |   2254.596 |     0.4%
@typescript-eslint/no-misused-promises          |   1457.956 |     0.3%
@typescript-eslint/no-unused-vars               |    737.505 |     0.1%
react/no-direct-mutation-state                  |    682.282 |     0.1%