Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Determine ESLint rules for TypeScript #1114

Closed
samreid opened this issue Oct 15, 2021 · 21 comments
Closed

Determine ESLint rules for TypeScript #1114

samreid opened this issue Oct 15, 2021 · 21 comments
Assignees

Comments

@samreid
Copy link
Member

samreid commented Oct 15, 2021

There are ESLint TypeScript rules defined at https://www.npmjs.com/package/@typescript-eslint/eslint-plugin. We should consider which ones we want to use. Note, they can be turned on via:

   plugins: [
     '@typescript-eslint'
   ],

as described in https://github.com/typescript-eslint/typescript-eslint/blob/master/docs/getting-started/linting/README.md

@samreid
Copy link
Member Author

samreid commented Oct 15, 2021

I tested and added a few rules for the plugin. I tried to enable more, but they required reference to tsconfig.json, so I left them commented out for now.

The error was:

Full Error details:
Error: Error while loading rule '@typescript-eslint/restrict-plus-operands': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Occurred while linting /Users/samreid/apache-document-root/main/gravity-and-orbits/Gruntfile.js

I tried:

Index: eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintrc.js b/eslint/.eslintrc.js
--- a/eslint/.eslintrc.js	(revision 1e25f714b57a09f6ee1bbf0a4552a0409595b43c)
+++ b/eslint/.eslintrc.js	(date 1634328326966)
@@ -168,7 +168,7 @@
     // Not yet enabled because they require tsconfig.json files
     // '@typescript-eslint/no-unnecessary-type-assertion':'error',
     // '@typescript-eslint/no-unsafe-member-access':'error',
-    // '@typescript-eslint/restrict-plus-operands':'error',
+    '@typescript-eslint/restrict-plus-operands':'error',
 
     ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
     // Best Practices
@@ -971,7 +971,8 @@
   },
   parserOptions: {
     ecmaVersion: 8,
-    sourceType: 'module'
+    sourceType: 'module',
+    project: '../chipper/tsconfig/all/tsconfig.json'
   },
   globals: {
 

but it failed with errors like:

/Users/samreid/apache-document-root/main/gravity-and-orbits/mipmaps/to_scale_icon_png.js
  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: mipmaps/to_scale_icon_png.js.
The file must be included in at least one of the projects provided

samreid added a commit to phetsims/bending-light that referenced this issue Oct 15, 2021
samreid added a commit to phetsims/circuit-construction-kit-common that referenced this issue Oct 15, 2021
@samreid samreid removed their assignment Oct 15, 2021
@zepumph
Copy link
Member

zepumph commented Feb 28, 2022

Today during our typescript dev meeting, we decided that we want to make this higher priority to get ts-related lint rules working on our project. This is currently blocking #1203.

@jessegreenberg volunteered to help move this forward. Thanks a million.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 2, 2022

I tried to work on this today but got about as far as #1114 (comment). Here are the changes I tried in .eslintrc.js

Index: package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/package.json	(date 1646195788679)
@@ -20,6 +20,7 @@
     "@types/qunit": "^2.11.2",
     "@types/three": "^0.137.0",
     "@typescript-eslint/parser": "5.4.0",
+    "@typescript-eslint/eslint-plugin": "^5.13.0",
     "archiver": "^5.3.0",
     "axios": "^0.21.4",
     "babel-eslint": "^10.1.0",
Index: tsconfig.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/tsconfig.json b/tsconfig.json
--- a/tsconfig.json	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/tsconfig.json	(date 1646197494006)
@@ -2,6 +2,8 @@
   "extends": "./tsconfig-core.json",
   "include": [
     // Just the code used in sim modules
-    "js/getStringModule.js"
+    "js/getStringModule.js",
+
+    "../../axon/js/Action.ts"
   ]
 }
Index: eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintrc.js b/eslint/.eslintrc.js
--- a/eslint/.eslintrc.js	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/eslint/.eslintrc.js	(date 1646197453836)
@@ -15,9 +15,9 @@
 
   parser: '@typescript-eslint/parser',
 
-  plugins: [
-    // '@typescript-eslint'
-  ],
+  // plugins: [
+  //   // '@typescript-eslint'
+  // ],
 
   // The rules are organized like they are in the list at https://eslint.org/docs/rules/
   // First by type, then alphabetically within type
@@ -967,6 +967,32 @@
     ecmaVersion: 8,
     sourceType: 'module'
   },
+  overrides: [
+    {
+      // for files matching this pattern
+      files: '*.ts',
+
+      // the following config will override .js config
+      parser: '@typescript-eslint/parser',
+      parserOptions: {
+        // sourceType: 'module',
+        // ecmaVersion: 2020,
+        project: [
+          '../chipper/tsconfig.json'
+        ]
+      },
+      extends: [ 'plugin:@typescript-eslint/recommended' ],
+      plugins: [
+        '@typescript-eslint'
+      ],
+      rules: {
+        //'@typescript-eslint/no-unnecessary-type-assertion': 'error'
+        '@typescript-eslint/no-unsafe-member-access': 'error'
+        // '@typescript-eslint/restrict-plus-operands':'error',
+      }
+    }
+  ],
+
   globals: {
 
     // globals that should never be accessed ---------------------------------

When I lint in a sim repo I see lots of

  0:0  error  Parsing error: "parserOptions.project" has been set for @typescript-eslint/parser.
The file does not match your project config: js\Action.ts.
The file must be included in at least one of the projects provided

And when I lint in chipper I see

Error: Error while loading rule '@typescript-eslint/no-unsafe-member-access': You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.
Occurred while linting C:\Users\Jesse\Documents\Development\phetsims\chipper\phet-types.d.ts
    at Object.getParserServices (C:\Users\Jesse\Documents\Development\phetsims\chipper\node_modules\@typescript-eslint\eslint-plugin\node_modules\@typescript-eslint\utils\dist\eslint-utils\getParserServices.js:16:15)

If the parserOptions.project entry is removed eslint errors go away and @typescript-eslint works. But the parserOptions.project is required for rules that use type information. I read in several places that rules that use type information are very slow. Maybe we won't want to use them. But I am going to try setting up a new TS project and seeing if I can get @typescript-eslint working there.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 2, 2022

I followed the instructions https://www.typescriptlang.org/docs/handbook/typescript-tooling-in-5-minutes.html and https://khalilstemmler.com/blogs/typescript/eslint-for-typescript/ to set up a basic TS project with @typescript-eslint and rules that require type information are working well.

Here is the .eslintrc

{
  "root": true,
  "parser": "@typescript-eslint/parser",
  "plugins": [
    "@typescript-eslint"
  ],
  "parserOptions": {
    "project": "./tsconfig.json"
  },
  "rules": {
     "@typescript-eslint/restrict-plus-operands":"error"
  }
}

I am going to try linting javascript and typescript together in this simple project.

I got js and ts files linting in the same project with rules that use type information with this eslintrc:

{
  "env": {
    "browser": true,
    "es6": true
  },
  "rules": {
    "quotes": [
      "error",
      "single"
    ],
    "semi": [
      "error",
      "always"
    ]
  },
  "overrides": [
    {
      // For .ts files, the following configuration will be used
      "files": [
        "**/*.ts"
      ],
      "parser": "@typescript-eslint/parser",
      "parserOptions": {
        "sourceType": "module",
        "project": "./tsconfig.json"
      },
      "plugins": [
        "@typescript-eslint"
      ],
      "rules": {
        "@typescript-eslint/restrict-plus-operands": "error"
      }
    }
  ]
}

I changed the tsconfig.json to extend a tsconfig-core.json like in chipper and it still works.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 2, 2022

Alright, I just got it working by following a recommendation in https://stackoverflow.com/questions/58510287/parseroptions-project-has-been-set-for-typescript-eslint-parser.

I added a file chipper/eslint/tsconfig.eslint.json that looks like

{
  "extends": "../../chipper/tsconfig/all/tsconfig.json",
  "include": [
    "../../axon/js/*.ts",
    "../../quadrilateral/js/**/*"
  ]
}

And made this file the value of parserOptions.project. Running lint in axon or quadrilateral will catch things like

// error  Operands of '+' operation must either be both strings or both numbers. Consider using a template literal  @typescript-eslint/restrict-plus-operands
const testVar = 5 + '1';

We would have to include all libraries in this new file.

In axon files I am also seeing an error from webstorm
image

@samreid
Copy link
Member Author

samreid commented Mar 2, 2022

Here is our patch so far:

Index: package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/package.json	(date 1646253547569)
@@ -20,6 +20,7 @@
     "@types/qunit": "^2.11.2",
     "@types/three": "^0.137.0",
     "@typescript-eslint/parser": "5.4.0",
+    "@typescript-eslint/eslint-plugin": "5.13.0",
     "archiver": "^5.3.0",
     "axios": "^0.21.4",
     "babel-eslint": "^10.1.0",
Index: eslint/tsconfig.eslint.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/tsconfig.eslint.json b/eslint/tsconfig.eslint.json
new file mode 100644
--- /dev/null	(date 1646253271750)
+++ b/eslint/tsconfig.eslint.json	(date 1646253271750)
@@ -0,0 +1,7 @@
+{
+  "extends": "../../chipper/tsconfig/all/tsconfig.json",
+  "include": [
+    "../../axon/js/*.ts",
+    "../../quadrilateral/js/**/*"
+  ]
+}
\ No newline at end of file
Index: eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintrc.js b/eslint/.eslintrc.js
--- a/eslint/.eslintrc.js	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/eslint/.eslintrc.js	(date 1646253667888)
@@ -19,6 +19,26 @@
     // '@typescript-eslint'
   ],
 
+  "overrides": [
+    {
+      // For .ts files, the following configuration will be used
+      "files": [
+        "**/*.ts"
+      ],
+      "parser": "@typescript-eslint/parser",
+      "parserOptions": {
+        "sourceType": "module",
+        "project": "../chipper/eslint/tsconfig.eslint.json"
+      },
+      "plugins": [
+        "@typescript-eslint"
+      ],
+      "rules": {
+        "@typescript-eslint/restrict-plus-operands": "error"
+      }
+    }
+  ],
+
   // The rules are organized like they are in the list at https://eslint.org/docs/rules/
   // First by type, then alphabetically within type
   // Explicitly list all rules so it is easy to see what's here and to keep organized

JT EDIT: SR and I met to discuss progress and turned #1114 (comment) into a patch. We are both a bit confused about why the new tsconfig file is necessary for the parser, it seems like we should be able to use existing tsconfig files. Together we also tried to move things out of the "overrides" section but hit the "You have used a rule which requires a generated parser..." error. Ill keep seeing if I can learn more.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 2, 2022

From https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/docs/rules/explicit-function-return-type.md#configuring-in-a-mixed-jsts-codebase

If you are working on a codebase within which you lint non-TypeScript code (i.e. .js/.jsx), you should ensure that you should use ESLint overrides to only enable the rule on .ts/.tsx files. If you don't, then you will get unfixable lint errors reported within .js/.jsx files.

Regarding the "failed to load plugin" outside of chipper, maybe this is what we need: https://eslint.org/docs/user-guide/command-line-interface#--resolve-plugins-relative-to. Also see https://eslint.org/docs/user-guide/migrating-to-6.0.0#-plugins-and-shareable-configs-are-no-longer-affected-by-eslints-location

EDIT: We already use resolvePluginsRelativeTo in lint.js. According to https://youtrack.jetbrains.com/issue/WEB-43692 it should be working with WebStorm. When I remove resolvePluginsRelativeTo from lint.js the error appears in the console. So maybe we need to put this in a config where WebStorm can find it.

EDIT: I got this error to go away by using this setting for eslint options.
image

EDIT: Regarding the chipper/eslint/tsconfig.eslint.json, I tried to use "../../**/js/*.ts" instead of listing each repo. It worked for axon, but when I ran lint in quadrilateral it took too long and I had to force quit (over five minutes).

EDIT: I tried modifying pacakge.json files to override the parserOptions.project entry in each repo. It worked for some repos but not others and I couldn't figure out why. I don't like modifying every package.json in the project, so not looking into this further.

EDIT; I found that this pattern in tsconfig.eslint.json for include is working in axon and quadrilateral: "../../*/**/*.ts"

EDIT: Patch where things are almost working well. I am worried about the increase in time from this, will test some of that.

Index: chipper/package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/chipper/package.json b/chipper/package.json
--- a/chipper/package.json	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/chipper/package.json	(date 1646255859875)
@@ -20,6 +20,7 @@
     "@types/qunit": "^2.11.2",
     "@types/three": "^0.137.0",
     "@typescript-eslint/parser": "5.4.0",
+    "@typescript-eslint/eslint-plugin": "5.13.0",
     "archiver": "^5.3.0",
     "axios": "^0.21.4",
     "babel-eslint": "^10.1.0",
Index: chipper/eslint/.eslintignore
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/chipper/eslint/.eslintignore b/chipper/eslint/.eslintignore
--- a/chipper/eslint/.eslintignore	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/chipper/eslint/.eslintignore	(date 1646316517876)
@@ -13,4 +13,5 @@
 ../phet-io-website/root/assets/js/QueryStringMachine_1.0.js
 ../phet-io-website/root/assets/js/QueryStringMachine_2.0.js
 ../phet-io-website/root/assets/js/phet-io-ga.js
-../chipper/dist
\ No newline at end of file
+../chipper/dist
+*.d.ts
\ No newline at end of file
Index: geometric-optics/js/lens/view/LensScreenView.ts
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/geometric-optics/js/lens/view/LensScreenView.ts b/geometric-optics/js/lens/view/LensScreenView.ts
--- a/geometric-optics/js/lens/view/LensScreenView.ts	(revision 6462dd2144a7b406fa7e93666d5bedd34c051780)
+++ b/geometric-optics/js/lens/view/LensScreenView.ts	(date 1646324631215)
@@ -29,6 +29,8 @@
    */
   constructor( model: LensModel, providedOptions: LensScreenViewOptions ) {
 
+    const x = 5 + '5';
+
     const options = optionize<LensScreenViewOptions, {}, GOScreenViewOptions,
       'getViewOrigin' | 'createOpticNode'>( {
 
Index: chipper/eslint/tsconfig.eslint.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/chipper/eslint/tsconfig.eslint.json b/chipper/eslint/tsconfig.eslint.json
new file mode 100644
--- /dev/null	(date 1646324956920)
+++ b/chipper/eslint/tsconfig.eslint.json	(date 1646324956920)
@@ -0,0 +1,6 @@
+{
+  "extends": "../../chipper/tsconfig/all/tsconfig.json",
+  "include": [
+    "../../*/**/*.ts"
+  ]
+}
\ No newline at end of file
Index: chipper/eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/chipper/eslint/.eslintrc.js b/chipper/eslint/.eslintrc.js
--- a/chipper/eslint/.eslintrc.js	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/chipper/eslint/.eslintrc.js	(date 1646325842049)
@@ -13,10 +13,31 @@
   // in a parent dir
   root: true,
 
-  parser: '@typescript-eslint/parser',
+  overrides: [
+    {
+
+      // For .ts files, the following configuration will be used
+      files: [
+        '**/*.ts'
+      ],
+      parser: '@typescript-eslint/parser',
+      parserOptions: {
+        sourceType: 'module',
 
-  plugins: [
-    // '@typescript-eslint'
+        // This will be the tsconfig of the repo where lint is being run. Alternatively
+        // a specific tsconfig could be specified in each repo's package.json. Seems to
+        // work for sims but not axon? Getting The file does not match your project config: js\stepTimer.ts.
+        // project: './tsconfig.json'
+        // project: '../chipper/tsconfig/all/tsconfig.json'
+        project: '../chipper/eslint/tsconfig.eslint.json'
+      },
+      plugins: [
+        '@typescript-eslint'
+      ],
+      rules: {
+        '@typescript-eslint/restrict-plus-operands': 'error'
+      }
+    }
   ],
 
   // The rules are organized like they are in the list at https://eslint.org/docs/rules/

EDIT: Timing impacts of the change:

Without @typescript-esilnt in geometric-optics

$ time grunt lint
Running "lint" task

Done.

real    0m1.866s
user    0m0.045s
sys     0m0.123s

$ time grunt lint --disable-eslint-cache
Running "lint" task

Done.

real    0m3.653s
user    0m0.030s
sys     0m0.122s

$ time grunt lint-everything
Running "lint-everything" task
(Forwarding task to perennial)
Running "lint-everything" task

Done.

Done.

real    1m35.876s
user    0m0.030s
sys     0m0.137s

With @typescript-eslint in geometric-optics

$ time grunt lint
Running "lint" task

Done.

real    0m2.170s
user    0m0.060s
sys     0m0.060s

$ time grunt lint --disable-eslint-cache
Running "lint" task

Done.

real    0m22.060s
user    0m0.090s
sys     0m0.046s

$ time grunt lint-everything
...
real    1m52.086s
user    0m0.045s
sys     0m0.152s

EDIT: I think we still need to use the @typescript-eslint/parser otherwise .js files get linted without es6 transpilation and we see errors like

C:\Users\Jesse\Documents\Development\phetsims\utterance-queue\js\AriaLiveAnnouncer.js
  46:17  error  Parsing error: Unexpected token =

For the assignment of POLITE in

// Possible supported values for the `aria-live` attributes created in AriaLiveAnnouncer.
class AriaLive extends EnumerationValue {
  static POLITE = new AriaLive();
  static ASSERTIVE = new AriaLive();

Maybe I should try moving settings out of overrides now.

EDIT: I tried to move all the overrides but I am getting some errors in .js files that are only relevant to .ts files. We still need the overrides to differentiate settings for each filetype.

Progress patch to apply:

Index: package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/package.json	(date 1646330986874)
@@ -20,6 +20,7 @@
     "@types/qunit": "^2.11.2",
     "@types/three": "^0.137.0",
     "@typescript-eslint/parser": "5.4.0",
+    "@typescript-eslint/eslint-plugin": "5.13.0",
     "archiver": "^5.3.0",
     "axios": "^0.21.4",
     "babel-eslint": "^10.1.0",
Index: eslint/.eslintignore
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintignore b/eslint/.eslintignore
--- a/eslint/.eslintignore	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/eslint/.eslintignore	(date 1646330986853)
@@ -13,4 +13,5 @@
 ../phet-io-website/root/assets/js/QueryStringMachine_1.0.js
 ../phet-io-website/root/assets/js/QueryStringMachine_2.0.js
 ../phet-io-website/root/assets/js/phet-io-ga.js
-../chipper/dist
\ No newline at end of file
+../chipper/dist
+*.d.ts
\ No newline at end of file
Index: eslint/tsconfig.eslint.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/tsconfig.eslint.json b/eslint/tsconfig.eslint.json
new file mode 100644
--- /dev/null	(date 1646330986867)
+++ b/eslint/tsconfig.eslint.json	(date 1646330986867)
@@ -0,0 +1,6 @@
+{
+  "extends": "../../chipper/tsconfig/all/tsconfig.json",
+  "include": [
+    "../../*/**/*.ts"
+  ]
+}
\ No newline at end of file
Index: eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintrc.js b/eslint/.eslintrc.js
--- a/eslint/.eslintrc.js	(revision 5ae7c8ee6b645bd171be5738a76edc7cad283ad3)
+++ b/eslint/.eslintrc.js	(date 1646342949339)
@@ -13,10 +13,33 @@
   // in a parent dir
   root: true,
 
+  // Without a parser, .js files are linted without es6 transpilation. Use the same parser that we use for TypeScript.
   parser: '@typescript-eslint/parser',
 
-  plugins: [
-    // '@typescript-eslint'
+  overrides: [
+    {
+
+      // For .ts files, the following configuration will be used
+      files: [
+        '**/*.ts'
+      ],
+      parser: '@typescript-eslint/parser',
+      parserOptions: {
+        sourceType: 'module',
+
+        // Provide a tsconfig so that we can use rules that require type information. tsconfig.eslint.json
+        // gives eslint project information without needing to our actual tsconfig setup.
+        project: '../chipper/eslint/tsconfig.eslint.json'
+      },
+      plugins: [
+        '@typescript-eslint'
+      ],
+      rules: {
+
+        // Put ts specific rules here
+        '@typescript-eslint/restrict-plus-operands': 'error'
+      }
+    }
   ],
 
   // The rules are organized like they are in the list at https://eslint.org/docs/rules/

Currently I can lint everything except chipper. In that repo I am getting

You have used a rule which requires parserServices to be generated. You must therefore provide a value for the "parserOptions.project" property for @typescript-eslint/parser.

I tried to add an override to chipper's package.json eslintconfig but it didn't do anything. But I copied the entire overrides section added to eslintrc into package.json and it is working well. Not seeing any failures to run lint when running grunt lint-everything. This is the block copied into chipper's package.json under eslintconfig

    "overrides": [
      {
        "files": [
          "**/*.ts"
        ],
        "parser": "@typescript-eslint/parser",
        "parserOptions": {
          "sourceType": "module",
          "project": [
            "../chipper/eslint/tsconfig.eslint.json"
          ]
        },
        "plugins": [
          "@typescript-eslint"
        ],
        "rules": {
          "@typescript-eslint/restrict-plus-operands": "error"
        }
      }
    ]

For some reason, that can be reduced to this to get typescript rules working in chipper

    "overrides": [
      {
        "files": [
          "**/*.ts"
        ],
        "parser": "@typescript-eslint/parser"
      }
    ]

I don't know why that portion has to be duplicated and why it doesn't need parserOptions.project since that is what the error indicates.

Final patch where I can use grunt lint-everything

Index: package.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/package.json b/package.json
--- a/package.json	(revision a304351ca438ae96a53614e83ee2c900c45c6270)
+++ b/package.json	(date 1646862574530)
@@ -20,6 +20,7 @@
     "@types/qunit": "^2.11.2",
     "@types/three": "^0.137.0",
     "@typescript-eslint/parser": "5.4.0",
+    "@typescript-eslint/eslint-plugin": "5.13.0",
     "archiver": "^5.3.0",
     "axios": "^0.21.4",
     "babel-eslint": "^10.1.0",
@@ -57,6 +58,14 @@
     "parserOptions": {
       "sourceType": "module",
       "allowImportExportEverywhere": true
-    }
+    },
+    "overrides": [
+      {
+        "files": [
+          "**/*.ts"
+        ],
+        "parser": "@typescript-eslint/parser"
+      }
+    ]
   }
 }
Index: eslint/tsconfig.eslint.json
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/tsconfig.eslint.json b/eslint/tsconfig.eslint.json
new file mode 100644
--- /dev/null	(date 1646850819065)
+++ b/eslint/tsconfig.eslint.json	(date 1646850819065)
@@ -0,0 +1,7 @@
+{
+  "extends": "../../chipper/tsconfig/all/tsconfig.json",
+  "include": [
+    "../../*/**/*.ts",
+    "*.ts"
+  ]
+}
\ No newline at end of file
Index: eslint/.eslintrc.js
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
diff --git a/eslint/.eslintrc.js b/eslint/.eslintrc.js
--- a/eslint/.eslintrc.js	(revision a304351ca438ae96a53614e83ee2c900c45c6270)
+++ b/eslint/.eslintrc.js	(date 1646858933586)
@@ -13,10 +13,33 @@
   // in a parent dir
   root: true,
 
+  // Without a parser, .js files are linted without es6 transpilation. Use the same parser that we use for TypeScript.
   parser: '@typescript-eslint/parser',
 
-  plugins: [
-    // '@typescript-eslint'
+  overrides: [
+    {
+
+      // For .ts files, the following configuration will be used
+      files: [
+        '**/*.ts'
+      ],
+      parser: '@typescript-eslint/parser',
+      parserOptions: {
+        sourceType: 'module',
+
+        // Provide a tsconfig so that we can use rules that require type information. tsconfig.eslint.json
+        // gives eslint project information without needing to modify our actual tsconfig setup.
+        project: [ '../chipper/eslint/tsconfig.eslint.json' ]
+      },
+      plugins: [
+        '@typescript-eslint'
+      ],
+      rules: {
+
+        // Put ts specific rules here
+        '@typescript-eslint/restrict-plus-operands': 'error'
+      }
+    }
   ],
 
   // The rules are organized like they are in the list at https://eslint.org/docs/rules/

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 3, 2022

Ready to bring back to the team. Things that people would have to be aware of before we enable this.

  • You will have to set a new option in your IDE settings for the plugin to work. "--resolve-plugins-relative-to=../chipper/" in "Extra eslint options".
  • Linting will often take longer. Without cache, a lint in a single repo on my machine that took 3.6 seconds now takes 22 seconds. With a cache time spent is equivalent, about 3.5 seconds with and without @typescript-eslint.
  • An npm install will be required in chipper after this change after @typescript-eslint/eslint-plugin is added.
  • If we are OK with this, what rules do we want to use? https://github.com/typescript-eslint/typescript-eslint/tree/main/packages/eslint-plugin/docs/rules

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 10, 2022

Discussed during meeting - We will add the plugin and enable linting of TypeScript. By next week all devs can have that much working. Then in following weeks we will go through as a team (or sub-team) and decide which lint rules to enable.

In general we think it is worth the extra time it takes to lint. But we could also only use the slower "type checking" lint rules when requested with a flag to speed things up generally.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 10, 2022

I committed the change but @samreid reported that it isn't working well with WebStorm because WebStorm reports
"Failed to load plugin @typescript-eslint declared in '..SIM\package.json". I tried to use it on a second Windows 10 machine but found the same error so I am going to revert until I understand why it works on my primary machine but not others.

UPDATE: I got it working on both my Windows machines by updating WebStorm to 2021.3. I tried out WebStorm on my mac and doing the steps in #1114 (comment) worked. It did take ~20 seconds or so for WebStorm to recognize --resolve-plugins-relative-to.

UPDATE 2: @zepumph and I saw the patch working well for his machine. I am going to reapply changes.

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 11, 2022

The change has been added back and I put out a PSA on slack channels. I also updated phet-info/ide/setup.md with this info. Next step is to decide which lint rules to begin applying,

@jessegreenberg
Copy link
Contributor

jessegreenberg commented Mar 12, 2022

Devs are reporting that WebStorm errors with "ESLint: No results for {{file}} after 20 seconds." The recommendation in https://youtrack.jetbrains.com/issue/WEB-38004 is to disable eslint rules that require type information and remove parserOptions.project from the eslint config. Ive done that for now.

Maybe we can make eslint faster by restricting the files it searches for in tsconfig.eslint.json. Or maybe we can get it to share some tsc cache? Or maybe we can use these rules and parserOptions.project only when running from the command line. Or just not use rules that need type information.

samreid added a commit to phetsims/center-and-variability that referenced this issue Mar 15, 2022
@samreid
Copy link
Member Author

samreid commented Mar 15, 2022

Could we improve this process by having each repo point to its own tsconfig in parserOptions.project? That way, the type checker only has to check the one sim instead of all 160+ sims?

Also, I tested with:

      extends: [
        'plugin:@typescript-eslint/eslint-recommended',
        'plugin:@typescript-eslint/recommended'
      ],

and found errors like:

  • Don't use {} as a type. {} actually means "any non-nullish value".
  • Unexpected empty method

@samreid
Copy link
Member Author

samreid commented Mar 15, 2022

Specifying this in package.json for center-and-spread:

  "eslintConfig": {
    "extends": "../chipper/eslint/sim_eslintrc.js",
    "parserOptions": {
      "project": [
        "./tsconfig.json"
      ]
    }
  }

Changes the time of time grunt lint --disable-eslint-cache from 12 seconds to 2 seconds. With caching and no code changes it is 0.6sec whether you use the full tsconfig or the sim-specific one.

@zepumph
Copy link
Member

zepumph commented Apr 7, 2022

Looking more into this right now.

@zepumph
Copy link
Member

zepumph commented Apr 7, 2022

I went through all the rules in https://typescript-eslint.io/rules/ and added the rules that were recommended to our eslintrc. Basically this is the same format @samreid did for #814.

We should probably do this same criteria for all rules in the plugin, just to see if there are others that we want to add in.

When all non-type-checking rules were added in, we had 2942 Problems. There were just a handful of rules with the vast majority of issues.

@samreid samreid self-assigned this Apr 8, 2022
@jessegreenberg
Copy link
Contributor

jessegreenberg commented Apr 14, 2022

Some discussion 4/14/22

The no-non-null-assertion - We do not think we can turn this on, we use this operator pervasively.

@zepumph collected rules that would be good to enable. Some could be enabled immediately others could not and warrant more discussion. Next time we are going to go through the list and decide which ones we want to enable (and do the work to get the project free of that lint error).

@pixelzoom
Copy link
Contributor

Investigating 'no-this-alias' errors in #1223.

@zepumph
Copy link
Member

zepumph commented May 19, 2022

@jessegreenberg will create the rest of the issues per rule. Then we are ready to close because type-checking lint rules should be decided on based on the outcome of #1238. Please close when those are made. Thanks @jessegreenberg!

@jessegreenberg
Copy link
Contributor

Great, issues have been made we will continue there. Closing this one.

@idemax
Copy link

idemax commented Apr 10, 2023

so whats the fix at the end?!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants