-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
feat(eslint-plugin): migrate to typescript #2568
feat(eslint-plugin): migrate to typescript #2568
Conversation
🦋 Changeset detectedLatest commit: f563b29 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
hmm haven't really used Rollup much before (but this could also be an ES modules thing):
Not quite sure how to tell rollup that |
Looks like DTSLint is failing for a bunch of packages, which I'd hope is unrelated - btw I've not set it up for this package because usually there's not a lot of reason to emit types for eslint plugins. |
emotion/packages/react/src/index.js Line 2 in 26ded61
Thank you very much for the PR. I'll try to review this soon. |
Ah right thanks - that isn't possible in TS without |
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. Latest deployment of this branch, based on commit f563b29:
|
Codecov Report
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { AST_NODE_TYPES } from '@typescript-eslint/experimental-utils' | ||
import { createRule } from '../utils' | ||
|
||
const simpleMappings = new Map<unknown, string>([ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not Map<string, string>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/* istanbul ignore if */ | ||
if (jsxImportSourcePragmaComment === null) { | ||
throw new Error( | ||
`Unexpected null when attempting to fix ${context.getFilename()} - please file a github issue at https://github.com/emotion-js/emotion` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nitpick: Use REPO_URL
constant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
tbh I could abstract this into an assertion function as well 🤔
@@ -0,0 +1,4 @@ | |||
export const espreeParser: string = require('resolve-from')( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why is this fancy require
stuff necessary? Would it be possible to do a normal import
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because resolve-from
uses a commonjs export (export =
) which @babel/plugin-transform-typescript
doesn't support out of the box, and this codebase doesn't have esModuleInterop
enabled.
I have written a babel plugin that adds support for export =
that could be used, but generally esModuleInterop
is the better way to go and since this is for tests I thought it would be simpler to just use require
here than to muck about with the babel config.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah we should eventually enable esModuleInterop
... I've added that to my personal todo list. What you did is totally fine for now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
would it be problematic to enable esModuleInterop
as part of this PR? if it is - then don't do it but if it's just a matter for using that option then this could be included here
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The trouble is that esModuleInterop
actually changes the emitted code so in theory it could result in a breaking change depending on the structure and usage, for users that are not using a transpiler like Babel or TypeScript.
It's unlikely, but I'd prefer to keep this PR to be focused on just eslint-plugin
if possible since enabling esModuleInterop
doesn't give a strong win here.
.changeset/modern-penguins-play.md
Outdated
'@emotion/eslint-plugin': minor | ||
--- | ||
|
||
Source code has been migrated to TypeScript. No changes should be required by users |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You said you fixed 3 bugs — could you add a changeset for each bug that was fixed? I think doing separate changesets for each is appropriate, but I'm not 100% sure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'm not super familiar with changesets myself, which is why I tried to get away with just one 😅
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@srmagura it's been a while so had a bit of trouble remembering the specifics for the bugs, but I believe two of them were the same bug just on different rules so are covered by the one changeset (the erroring when a component had a css
prop without a value), and have added a change set for the remaining bug.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
code: ` | ||
/** @jsx jsx */ | ||
import {jsx} from '@emotion/react' | ||
let ele = <div css /> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this one considered to be valid though? This is equivalent to css={true}
and that doesn't quite make sense
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you're right, but this PR is meant to be focusing on converting the existing code to TypeScript, so I prefer to do any behaviour changes like this in follow up PRs.
The reason this is here in the first place is because it covers a new condition I have to add in order to make the code valid with TypeScript, since it revealed an unchecked nullish value.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So I guess this is sort of valid for this particular rule - although not valid in the general sense. I'm not sure in which rule we should validate this though
@@ -162,6 +164,10 @@ ruleTester.run('syntax-preference (object)', rule, { | |||
{ | |||
code: `const Foo = () => <div css={css({ color: 'hotpink' })} />`, | |||
options: ['object'] | |||
}, | |||
{ | |||
code: `const Foo = () => <div css />`, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same doubt as here
], | ||
output: ` | ||
/** @jsx jsx */ | ||
/** @jsx emotion.jsx */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This one seems like a new test case. Was this a bug and it got fixed here? From what I understand the issue could be about the namespace import being used in a file with an invalid pragma for such an import. I've skimmed through the related code and I don't see any particular changes that would fix this - although I'm not super familiar with this code, so I could have missed the fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should have been for either an actual bug or to ensure coverage, but I can't get it to fail so happy to remove it if you like
By the way - thank you very much for this PR ❤️ |
What:
Migrates the
@emotion/eslint-plugin
to TypeScript, using standard practices and utilities; I've kept the changes to a minimal, but there are some follow-up optimisations that could be done (such as using optional chaining in a few places, turning on es module interop, and using some early returns to dedent some big blocks of code).This fixed three bugs which I've added tests for, and if I have the time will backport to
main
since they can be released without typescript being merged.This also highlighted that
jx-import
seems to have a bit of a broken/undocumented interface for it's option 😅It technically accepts a string, but acts (and is tested) as if it'll only ever be passed an object - I've left it as is for now, as changing that could arguably be breaking but I'm happy to help clean that if folks let me know their preferred direction for handling that :)
Why:
Part of #2358
How:
Rewrote the rules in TypeScript 😄
Checklist: