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

feat: add no-unused eslint rule to find unused styles #767

Merged
merged 4 commits into from
Nov 11, 2024

Conversation

Samantha-Zhan
Copy link
Contributor

What changed / motivation ?

Addresses task ESLint: find unused styles #702.

Identify all styles that 1) not used; 2) not exported. The feature also allow auto fix by removing fields that are unused.

import stylex from 'stylex';
// exported, considered all used
const styles = stylex.create({
  main: {
    borderColor: {
      default: 'green',
      ':hover': 'red',
      '@media (min-width: 1540px)': 1366,
    },
    borderRadius: 10,
    display: 'flex',
  },
  dynamic: (color) => ({
    backgroundColor: color,
  })
});
// not exported, not used, will report warning `Unused style detected: stylesUnused.maxDimensionsModal`
const stylesUnused = stylex.create({
    maxDimensionsModal: {
      maxWidth: '90%',
      maxHeight: '90%',
    },
});
export default styles;

Linked PR/Issues

fixes #702.

Additional Context

Created sets of tests in stylex-no-unused-test.js, all 5 tests passed; also conducted manual testing in apps/docs/ folder.

Pre-flight checklist

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Nov 6, 2024
Copy link

github-actions bot commented Nov 6, 2024

workflow: benchmarks/size

Comparison of minified (terser) and compressed (brotli) size results, measured in bytes. Smaller is better.

@stylexjs/scripts@0.9.3 size:compare
./size-compare.js /tmp/tmp.hFJyaM6NWc /tmp/tmp.nBqv2OHADI

Results Base Patch Ratio
stylex/lib/stylex.js
· compressed 729 729 1.00
· minified 2,541 2,541 1.00
stylex/lib/StyleXSheet.js
· compressed 1,266 1,266 1.00
· minified 3,776 3,776 1.00
rollup-example/.build/bundle.js
· compressed 563,025 563,025 1.00
· minified 10,185,368 10,185,368 1.00
rollup-example/.build/stylex.css
· compressed 99,154 99,154 1.00
· minified 745,649 745,649 1.00

@@ -13,6 +13,7 @@ module.exports = {
// The Eslint rule still needs work, but you can
// enable it to test things out.
'@stylexjs/valid-styles': 'error',
// '@stylexjs/no-unused' : 'warn',
Copy link
Contributor

Choose a reason for hiding this comment

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

you can leave this enabled.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

[update] after uncommenting, I notice the eslint error Definition for rule '@stylexjs/no-unused' was not found. starting appearing again, but I am certain it was working before as I was able to test the rule&auto-fix inside the docs folder. I attempted to rebuild multiple times but currently still doesn't work...

Copy link
Contributor

@nmn nmn left a comment

Choose a reason for hiding this comment

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

Great start so far!

Left a bunch of comments to complete the PR.

packages/eslint-plugin/__tests__/stylex-no-unused-test.js Outdated Show resolved Hide resolved
packages/eslint-plugin/__tests__/stylex-no-unused-test.js Outdated Show resolved Hide resolved
packages/eslint-plugin/__tests__/stylex-no-unused-test.js Outdated Show resolved Hide resolved
packages/eslint-plugin/src/stylex-no-unused.js Outdated Show resolved Hide resolved
// of the file so we can look directly on Program and populate our set.
node.body
.filter(({ type }) => type === 'VariableDeclaration')
.map(({ declarations }) =>
Copy link
Contributor

Choose a reason for hiding this comment

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

You should also look for any top level consts so you can resolve objects passed into stylex.create that uses a local const.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I don't think I understand you completely, do you mean something like:

const field = {
  backgroundColor: 'white',
};

const styles = stylex.create({
  main: {
    height: 4,
  },
  field,
});

Copy link
Contributor

Choose a reason for hiding this comment

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

Yes. Something like that.

Or even the entire object that's passed into stylex.create.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, however, when testing it out inside doc folder, I realize both of the format are actually illegal:
Screenshot 2024-11-07 at 12 32 40 PM
image
image

Copy link
Contributor

Choose a reason for hiding this comment

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

Yeah, we need to fix that rule too. We can punt on this for now.

…; added features: non-default export, used style as return, full import pattern support
@@ -13,6 +13,7 @@ module.exports = {
// The Eslint rule still needs work, but you can
// enable it to test things out.
'@stylexjs/valid-styles': 'error',
// '@stylexjs/no-unused': 'warn',
Copy link
Member

Choose a reason for hiding this comment

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

do we want to use warn or error here?

Copy link
Contributor Author

@Samantha-Zhan Samantha-Zhan Nov 8, 2024

Choose a reason for hiding this comment

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

If we follow the behavior in internal codebase, then this should be error; i agree we should change it to error(will update this after figuring out the definition not found error, @nmn is helping investigating this)

Copy link
Contributor

Choose a reason for hiding this comment

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

I will enable this after this PR lands. There are some issues with dependencies where this doesn't always work consistently.


'Program:exit'() {
// Fallback to legacy `getSourceCode()` for compatibility with older ESLint versions
const sourceCode =
Copy link
Member

Choose a reason for hiding this comment

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

since this is repeated across a few rules, maybe we can extract this logic out into a utils

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I think extracting getting sourcecode make sense, I will push up a PR after this PR is resolved

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Copy link
Contributor

@nmn nmn left a comment

Choose a reason for hiding this comment

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

This looks almost good enough to land. It needs one tiny change. I'll see if I can patch that and merge it if you can't update it in time.

package.json Outdated Show resolved Hide resolved
@nmn nmn merged commit ec13602 into main Nov 11, 2024
8 checks passed
@nmn nmn deleted the feat/eslint-no-unused branch November 11, 2024 20:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ESLint: find unused styles
4 participants