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

fix: Use updated types from @eslint/core #66

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open

Conversation

nzakas
Copy link
Member

@nzakas nzakas commented Nov 21, 2024

Prerequisites checklist

What is the purpose of this pull request?

Update the plugin to use the latest types from @eslint/core.

What changes did you make? (Give an overview)

  • Added types.ts files to define types.
  • Updated rules to use RuleDefinition type
  • Updated JSONLanguage to use IJSONLanguage type
  • Updated JSONSourceCode to use IJSONSourceCode type

Related Issues

Is there anything you'd like reviewers to focus on?

The types test fails with this, and I don't understand why. The project builds just fine. Maybe @fasttime can take a look?

@eslint-github-bot eslint-github-bot bot added the bug Something isn't working label Nov 21, 2024

json satisfies ESLint.Plugin;
// json satisfies ESLint.Plugin;
Copy link
Member Author

Choose a reason for hiding this comment

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

RuleModule is eslint is not compatible with RuleDefinition, so need to comment this out for now. I'll work on updating the types in eslint next.

@fasttime
Copy link
Member

It looks like the type tests are failing because the strict option is not compatible with the @eslint/core types:

"strict": true

We could remove that option for the moment since it's only used in the tests. In the long term I think it would be good to make sure that the @eslint/core types are strict compliant, so they can be used by TS projects with that option enabled. As I said in a previous comment, I don't think it's necessary to enable strict mode for the whole rewrite repo.

@nzakas
Copy link
Member Author

nzakas commented Nov 22, 2024

It looks like the type tests are failing because the strict option is not compatible with the @eslint/core types

Can you explain what the compatibility issue is? And why does running tsc on the project build fine but the type tests fails?

@fasttime
Copy link
Member

Can you explain what the compatibility issue is?

The issue is in the definition of RuleVisitor in @eslint/core:

export interface RuleVisitor {
	/**
	 * Called for each node in the AST or at specific times during the traversal.
	 */
	[key: string]: (...args: any[]) => void;
}

from https://github.com/eslint/rewrite/blob/3591a7805a060cb130d40d61f200431b782431d8/packages/core/src/types.ts#L102-L107

When the TypeScript strict option is set (or strictNullChecks more specifically) it's no longer possible to assign null or undefined to a property of the RuleVisitorInterface, or to extend it with an optional method (where the value can be a function or undefined).

For example:

let ruleVisitor: RuleVisitor = {};
ruleVisitor.foo = undefined; // Error with strictNullChecks, else OK

interface Bar extends RuleVisitor {
    bar?(): void; // Error with strictNullChecks, else OK
}

The JSONRuleVisitor interface extends RuleVisitor but also defines optional methods, that's why it fails to compile with the strict option.

json/src/types.ts

Lines 58 to 84 in fdde59d

export interface JSONRuleVisitor extends RuleVisitor {
Document?(node: DocumentNode): void;
Member?(node: MemberNode, parent?: ObjectNode): void;
Element?(node: ElementNode, parent?: ArrayNode): void;
Object?(node: ObjectNode, parent?: ValueNodeParent): void;
Array?(node: ArrayNode, parent?: ValueNodeParent): void;
String?(node: StringNode, parent?: ValueNodeParent): void;
Null?(node: NullNode, parent?: ValueNodeParent): void;
Number?(node: NumberNode, parent?: ValueNodeParent): void;
Boolean?(node: BooleanNode, parent?: ValueNodeParent): void;
NaN?(node: NaNNode, parent?: ValueNodeParent): void;
Infinity?(node: InfinityNode, parent?: ValueNodeParent): void;
Identifier?(node: IdentifierNode, parent?: ValueNodeParent): void;
"Document:exit"?(node: DocumentNode): void;
"Member:exit"?(node: MemberNode, parent?: ObjectNode): void;
"Element:exit"?(node: ElementNode, parent?: ArrayNode): void;
"Object:exit"?(node: ObjectNode, parent?: ValueNodeParent): void;
"Array:exit"?(node: ArrayNode, parent?: ValueNodeParent): void;
"String:exit"?(node: StringNode, parent?: ValueNodeParent): void;
"Null:exit"?(node: NullNode, parent?: ValueNodeParent): void;
"Number:exit"?(node: NumberNode, parent?: ValueNodeParent): void;
"Boolean:exit"?(node: BooleanNode, parent?: ValueNodeParent): void;
"NaN:exit"?(node: NaNNode, parent?: ValueNodeParent): void;
"Infinity:exit"?(node: InfinityNode, parent?: ValueNodeParent): void;
"Identifier:exit"?(node: IdentifierNode, parent?: ValueNodeParent): void;
}

It's possible that there are more incompatibilities in the core types but in this is the only one that's causing troubles with this PR. I tried manually changing the RuleVisitor interface to accept optional methods and then all type tests passed:

export type RuleVisitor = {
    /**
     * Called for each node in the AST or at specific times during the traversal.
     */
-   [key: string]: (...args: any[]) => void;
+   [key in string]?: (...args: any[]) => void;
};

And why does running tsc on the project build fine but the type tests fails?

Because the strict option is only enabled in tests/types/tsconfig.json (the config for type tests), not in the root tsconfig.json which is used for building.

@nzakas
Copy link
Member Author

nzakas commented Nov 22, 2024

Ah! That is very helpful, thank you.

I think we should change RuleVisitor, then, as I've run into other problems caused by this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants