Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feat(eslint-plugin): [strict-enums] new rule#4864

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Closed
Zamiell wants to merge74 commits intotypescript-eslint:mainfromZamiell:strict-enums
Closed

feat(eslint-plugin): [strict-enums] new rule#4864

Zamiell wants to merge74 commits intotypescript-eslint:mainfromZamiell:strict-enums

Conversation

Zamiell
Copy link
Contributor

@ZamiellZamiell commentedApr 26, 2022
edited by Josh-Cena
Loading

PR Checklist

Overview

Makes working with enums not suck. See thedocs that I wrote for the rule.

This PR is a draft; I am still working on it but I will start a PR for now in case anyone wants to give me early feedback.

@nx-cloud
Copy link

nx-cloudbot commentedApr 26, 2022
edited
Loading

☁️ Nx Cloud Report

CI is running/has finished running commands for commit871e9ca. As they complete they will appear below. Click to see the status, the terminal output, and the build insights.

📂 See all runs for this branch


✅ Successfully ran 43 targets

Sent with 💌 fromNxCloud.

@typescript-eslint
Copy link
Contributor

Thanks for the PR,@Zamiell!

typescript-eslint is a 100% community driven project, and we are incredibly grateful that you are contributing to that community.

The core maintainers work on this in their personal time, so please understand that it may not be possible for them to review your work immediately.

Thanks again!


🙏Please, if you or your company is finding typescript-eslint valuable, help us sustain the project by sponsoring it transparently onhttps://opencollective.com/typescript-eslint. As a thank you, your profile/company logo will be added to our main README which receives thousands of unique visitorsper day.

@netlify
Copy link

netlifybot commentedApr 26, 2022
edited
Loading

Deploy Preview fortypescript-eslint ready!

NameLink
🔨 Latest commit871e9ca
🔍 Latest deploy loghttps://app.netlify.com/sites/typescript-eslint/deploys/6296c3849d15340008441833
😎 Deploy Previewhttps://deploy-preview-4864--typescript-eslint.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to yourNetlify site settings.

@codecov
Copy link

codecovbot commentedApr 26, 2022
edited
Loading

Codecov Report

Merging#4864 (a50f6e1) intomain (7275977) willdecrease coverage by2.72%.
The diff coverage is81.85%.

❗ Current heada50f6e1 differs from pull request most recent head871e9ca. Consider uploading reports for the commit871e9ca to get more accurate results

@@            Coverage Diff             @@##             main    #4864      +/-   ##==========================================- Coverage   94.25%   91.53%   -2.73%==========================================  Files         153      228      +75       Lines        8305    10856    +2551       Branches     2702     3351     +649     ==========================================+ Hits         7828     9937    +2109- Misses        263      637     +374- Partials      214      282      +68
FlagCoverage Δ
unittest91.53% <81.85%> (-2.73%)⬇️

Flags with carried forward coverage won't be shown.Click here to find out more.

Impacted FilesCoverage Δ
packages/eslint-plugin/src/configs/all.ts100.00% <ø> (ø)
...ackages/eslint-plugin/src/rules/no-implied-eval.ts97.01% <ø> (-0.05%)⬇️
packages/eslint-plugin/src/rules/return-await.ts99.05% <ø> (ø)
packages/eslint-plugin/src/rules/unbound-method.ts92.13% <0.00%> (ø)
packages/eslint-plugin/src/util/misc.ts93.75% <ø> (-0.25%)⬇️
packages/type-utils/src/getEnum.ts14.28% <14.28%> (ø)
...s/eslint-plugin/src/util/collectUnusedVariables.ts93.16% <50.00%> (ø)
packages/type-utils/src/typeFlagUtils.ts65.38% <55.55%> (ø)
packages/eslint-plugin/src/rules/strict-enums.ts84.43% <84.43%> (ø)
...t-plugin/src/rules/no-confusing-void-expression.ts98.83% <100.00%> (-0.02%)⬇️
... and86 more

@Zamiell
Copy link
ContributorAuthor

Zamiell commentedApr 26, 2022
edited
Loading

No idea why linting is failing in CI. It passes locally when I donpm run lint.

@ZamiellZamiell marked this pull request as ready for reviewApril 27, 2022 16:27
@Zamiell
Copy link
ContributorAuthor

Zamiell commentedApr 28, 2022
edited
Loading

I also found a bug with thetypeChecker.getTypeAtLocation method while writing this PR.
If you pass itts.VariableDeclaration instead ofts.BindingName, it will cause a run-time error.

Which means that the function signature of this method needs to be updated in the TypeScript repository.
This is over my pay grade to fix, but someone should look into this.

@ZamiellZamiell mentioned this pull requestApr 29, 2022
3 tasks
@Zamiell
Copy link
ContributorAuthor

Zamiell commentedApr 29, 2022
edited
Loading

Some notes:

  • I fixed a few bad JSDoc comments (@return -->@returns). You should add a lint rule for this to the project, I recommend:https://github.com/gajus/eslint-plugin-jsdoc
  • As per Josh's recommendation, I fixed some bugs in the rest of the codebase that this lint rule caught, which is why there are seemingly unrelated code changes in this PR.
  • I converted alltsutils.isTypeFlagSet toutil.isTypeFlagSet, as the former is an unmaintained 3rd-party API, and the latter is a (presumably-still-maintained) internal function. I also fixed the definition for this function, as it really takes an integer instead of an enum.
  • I madeutil.isSymbolFlagSet, then converted alltsutils.isSymbolFlagSet toutil.isSymbolFlagSet for similar reasons, and did some small refactoring in "typeFlagUtils.ts" to make things more clear.

Needs to still be addressed:

  1. CUSTOM_RULES.md

The documentation here recommends usingtsutils.isTypeFlagSet, but this code won't work because the type signature for that function is bugged and the library is no longer maintained. Thus, I thinkutil.isTypeFlagSet should be moved to the@typescript-eslint/utils or something, because right now it isn't exported for end-users to use (I think?). And then this file should be updated to use the new exported function.

Here's a list of errors that I ignored:

  1. semi.ts

This file has code that uses a reducer on an enum array, but with a starting value of{} to compose a new record. This is a non-standard way to build a record (I think?), since normally thereduce function is supposed to operate on the array elements themselves.

Thus, thestrict-enums rule rightly complains that thereduce function is being used incorrectly.

  1. no-redundant-type-constituents.ts

This uses a complex type oftype PrimitiveTypeFlag = typeof primitiveTypeFlags[number], and I'm not sure what that even means.

  1. no-implied-eval.ts

My first thought was to change this toInternalSymbolName.Function, but that doesn't actually match the value that is being used here, so I don't know what to do. I assume that should be a corresponding enum to use, I just don't know what it is.

The comment for the___String type gives more information about this:

/**     * This represents a string whose leading underscore have been escaped by adding extra leading underscores.     * The shape of this brand is rather unique compared to others we've used.     * Instead of just an intersection of a string and an object, it is that union-ed     * with an intersection of void and an object. This makes it wholly incompatible     * with a normal string (which is good, it cannot be misused on assignment or on usage),     * while still being comparable with a normal string via === (also good) and castable from a string.     */exporttype__String=(string&{__escapedIdentifier:void;})|(void&{__escapedIdentifier:void;})|InternalSymbolName;

So I guess it's just weird and I should just put// eslint-disable-line?

  1. isTypeReadonly.ts

Same as "no-implied-eval.ts".

  1. no-implied-eval.ts

Same as "no-implied-eval.ts".

  1. consistent-type-exports.ts

Same as "no-implied-eval.ts".

This monorepo is a good test case for finding bugs in the rule. For example, it caught a bug with variadic functions, which I didn't have a test case for originally. Still working on some of the other errors.

@bradzacherbradzacher removed the awaiting responseIssues waiting for a reply from the OP or another party labelMay 16, 2022
Copy link
Member

@bradzacherbradzacher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is looking really good to me as it currently stands.

HOWEVER, I do see a large DevX problem in terms of "flags" enums. Now, flags enums are known to be unsafe.
Personally, I think in JS you should be using aSet or array to store the a list of possible values, but I get why one might use a "flags" enum.:

  • they're often used is for memory efficiency.
    • for example - this is why TS went with a "flags" enum for its fields - saves a lot of memory across an entire project's ASTs.
  • some would argue that there's a nice DevX to using bitwise-ops on flag enums.
    • personally I think that they're a bit confusing to think about, though I can understand how they're familiar for someone comfortable with lower-level languages.

The point is though, this may be something we need to solve for in terms of devx.
Right now the answer is "too bad, so sad - union innumber", but I don't think this is a good answer for those users because it destroys the type documentation for the usecases, for example:
image
image
image

Whilst I understand that in these cases it is "technically correct" for the type to benumber, it's also not truly correct as it suggests things like "it's valid to pass 100 to this function", when it's not - because 100 satisfies neitherFoo.A, norFoo.B.

So with all that said, I think we need to determine a means for people to "opt out" of the rule for flags enums.

Perhaps it's something as simple as adding an option with an "allow flags naming pattern" similar totheno-unused-vars rule'svarsIgnorePattern option:

{"@typescript-eslint/strict-enums":["error",// treats any enum with name ending in "Flags" as a flags enum{"flagsEnumPattern":"Flags^"},],}

This way users can have the rule on for strict usecase, and opt-out (with a clear naming pattern) known "unsafe" usecases.

I know we'd certainly find value within this very codebase thinks to the TS flag enums!

WDYT?

@@ -65,7 +65,7 @@ class Reference {
/**
* In some cases, a reference may be a type, value or both a type and value reference.
*/
readonly #referenceType: ReferenceTypeFlag;
readonly #referenceType:number |ReferenceTypeFlag;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

instead of unioning in number here, could we defineTypeOrNumber as an enum member, and remove the bitwise operations on the enum?

*/
export function getTypeFlags(type: ts.Type): ts.TypeFlags {
let flags: ts.TypeFlags = 0;
export function getTypeFlags(type: ts.Type): number | ts.TypeFlags {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

@JoshuaKGoldberg the point@Zamiell was making was that the code is written like this:

getTypeFlags(flag.one|flag.two| ...);

when could be written like this:

getTypeFlags(newSet([flag.one,flag.two, ...]);

Comment on lines 762 to 763
VariableDeclaration(node): void {
for (const declaration of node.declarations) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

nitpick - we don't care about the declaration itself, just the declarators.

Suggested change
VariableDeclaration(node):void{
for(constdeclarationofnode.declarations){
VariableDeclarator(node):void{

This is good because it saves you manually iterating and it means your report will be cleaner.

I.e. instead of:

const x = 1,^^^^^^^^^^^^      y: Foo = 99;^^^^^^^^^^^^^^^^^

(where^ is the report underline)

you'll instead have:

const x = 1,      y: Foo = 99;      ^^^^^^^^^^^

Which is clearer and more accurate!

Zamielland others added3 commitsMay 30, 2022 03:41
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
Co-authored-by: Brad Zacher <brad.zacher@gmail.com>
@bradzacherbradzacher added the awaiting responseIssues waiting for a reply from the OP or another party labelMay 31, 2022
@Zamiell
Copy link
ContributorAuthor

Zamiell commentedMay 31, 2022
edited
Loading

There are branch conflicts in thre README.md files.

  1. Why are there 2 duplicated README.md files? That doesn't make any sense.
  2. Is there a script to generate the README.md tables?

@Zamiell
Copy link
ContributorAuthor

Also, after Brad's updates, I get the following errors when building:

james@1qaz MINGW64 /d/Repositories/typescript-eslint/packages/eslint-plugin (strict-enums)$ yarn buildyarn run v1.22.19$ tsc -b tsconfig.build.json../types/src/ts-estree.ts:1:27 - error TS2307: Cannot find module './generated/ast-spec' or its corresponding type declarations.1 import * as TSESTree from './generated/ast-spec';                            ~~~~~~~~~~~~~~~~~~~~~~../types/src/ts-estree.ts:4:16 - error TS2664: Invalid module name in augmentation, module './generated/ast-spec' cannot be found.4 declare module './generated/ast-spec' {                 ~~~~~~~~~~~~~~~~~~~~~~../types/src/ts-estree.ts:21:27 - error TS2307: Cannot find module './generated/ast-spec' or its corresponding type declarations.21 export * as TSESTree from './generated/ast-spec';                             ~~~~~~~~~~~~~~~~~~~~~~../types/src/index.ts:1:49 - error TS2307: Cannot find module './generated/ast-spec' or its corresponding type declarations.1 export { AST_NODE_TYPES, AST_TOKEN_TYPES } from './generated/ast-spec';                                                  ~~~~~~~~~~~~~~~~~~~~~~../visitor-keys/src/get-keys.ts:1:26 - error TS2307: Cannot find module '@typescript-eslint/types' or its corresponding type declarations.1 import { TSESTree } from '@typescript-eslint/types';                           ~~~~~~~~~~~~~~~~~~~~~~~~~~../visitor-keys/src/visitor-keys.ts:1:42 - error TS2307: Cannot find module '@typescript-eslint/types' or its corresponding type declarations.1 import { AST_NODE_TYPES, TSESTree } from '@typescript-eslint/types';                                           ~~~~~~~~~~~~~~~~~~~~~~~~~~../visitor-keys/src/visitor-keys.ts:152:62 - error TS2345: Argument of type 'AdditionalKeys' is not assignable to parameter of type 'VisitorKeys'.  'string' index signatures are incompatible.    Type 'readonly GetNodeTypeKeys<T>[] | undefined' is not assignable to type 'readonly string[]'.      Type 'undefined' is not assignable to type 'readonly string[]'.152 const visitorKeys: VisitorKeys = eslintVisitorKeys.unionWith(additionalKeys);                                                                 ~~~~~~~~~~~~~~Found 7 errors.

Anyone know why that is? I'm unable to work on the branch until that is resolved.

@bradzacherbradzacher removed the awaiting responseIssues waiting for a reply from the OP or another party labelJun 13, 2022
Copy link
Member

@bradzacherbradzacher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

I think this is looking good so far.
I'm happy if we want to get this in and out to people to play with.

Fix the merge conflicts and we can get to it!

Comment on lines +27 to +34
## Banned Patterns

This rule bans:

1. Enum incrementing/decrementing - `incorrectIncrement`
1. Mismatched enum declarations/assignments - `mismatchedAssignment`
1. Mismatched enum comparisons - `mismatchedComparison`
1. Mismatched enum function arguments - `mismatchedFunctionArgument`
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

this is just a less-verbose duplicate of "Error Information" below - so let's remove this.

@bradzacherbradzacher added the awaiting responseIssues waiting for a reply from the OP or another party labelJul 18, 2022
@Zamiell
Copy link
ContributorAuthor

Brad can you respond to my messages on May 31st?

@bradzacher
Copy link
Member

bradzacher commentedAug 7, 2022
edited
Loading

@Zamiell - bothpackages/eslint-plugin/README.md andpackages/eslint-plugin/docs/rules/README.md no longer have rules table in them.

At the time the "canonical" table was the former (root readme), and the latter was added as part of the website build.

However the rules table is now no longer generated in source files - instead they are generated as part of the website build.

@JoshuaKGoldberg
Copy link
Member

👋@Zamiell, just checking in - do you still have time to work on this? And if so, are there still open questions you're waiting on answers to?

@JoshuaKGoldberg
Copy link
Member

Closing this PR as it's been stale for a few months without activity. Feel free to reopen@Zamiell if you have time - but no worries if not! If anybody wants to drive it forward, please do post your own PR - and if you use this as a start, consider addingCo-authored-by: Zamiell at the end of your PR description. Thanks! 😊

@github-actionsgithub-actionsbot locked asresolvedand limited conversation to collaboratorsNov 24, 2022
@JoshuaKGoldberg
Copy link
Member

Moving to#6091. I want these checks to exist 😄

@ZamiellZamiell deleted the strict-enums branchSeptember 17, 2023 13:30
Sign up for freeto subscribe to this conversation on GitHub. Already have an account?Sign in.
Reviewers

@JoshuaKGoldbergJoshuaKGoldbergJoshuaKGoldberg requested changes

@Josh-CenaJosh-CenaJosh-Cena left review comments

@bradzacherbradzacherbradzacher approved these changes

Assignees
No one assigned
Labels
awaiting responseIssues waiting for a reply from the OP or another partyenhancement: new plugin ruleNew rule request for eslint-plugin
Projects
None yet
Milestone
No milestone
Development

Successfully merging this pull request may close these issues.

4 participants
@Zamiell@bradzacher@JoshuaKGoldberg@Josh-Cena

[8]ページ先頭

©2009-2025 Movatter.jp