Skip to content

Commit

Permalink
feat(eslint-plugin): add support for eslint v9 (#1760)
Browse files Browse the repository at this point in the history
* feat(eslint-plugin): add support for eslint v9

This change adds a set of compatibility functions to bridge the gap between the legacy context api and the new context api, allowing projects using this plugin to upgrade their version of eslint to v9.

* docs(eslint-plugin): changeset

* build(eslint-plugin): add engines to explicitly declare supported node versions

This change updates the versions of nodes we're running the test workflow again to v16, v18, v20, and v22 (the new LTS)

* docs(eslint-plugin): add changeset

* Fix shorthand-property-sorting crashing when styles not initialised (#1765)

* Fix shorthand-property-sorting crashing when styles not initialised

* Add changeset

* Added changeset reminder

* Version Packages (#1766)

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>

---------

Co-authored-by: Grant Wong <2908767+dddlr@users.noreply.github.com>
Co-authored-by: atlas-dst-bot <81662413+atlas-dst-bot@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
  • Loading branch information
4 people authored Dec 19, 2024
1 parent 7254b42 commit e6d57ea
Show file tree
Hide file tree
Showing 23 changed files with 471 additions and 131 deletions.
5 changes: 5 additions & 0 deletions .changeset/five-dolphins-taste.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@compiled/eslint-plugin': minor
---

add engines to formalize supported node versions - ^16.0.0 || >= 18.0.0
5 changes: 5 additions & 0 deletions .changeset/five-pigs-explain.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@compiled/eslint-plugin': minor
---

support eslint v9
4 changes: 3 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
ecmaFeatures: {
jsx: true,
},
ecmaVersion: 2018,
ecmaVersion: 2020,
sourceType: 'module',
},
plugins: ['react-hooks'],
Expand Down Expand Up @@ -48,6 +48,8 @@ module.exports = {
},
],
'import/no-unresolved': 'off',
// TypeScript takes care of this for us (https://github.com/import-js/eslint-plugin-import/blob/main/docs/rules/namespace.md)
'import/namespace': 'off',
'import/order': [
'error',
{
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:

strategy:
matrix:
node-version: [14.x, 16.x, 18.x]
node-version: [16.x, 18.x, 20.x, 22.x]

steps:
- uses: actions/checkout@v3
Expand Down
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,9 @@
"@types/react": "^17.0.69",
"@types/react-dom": "^17.0.22",
"@types/svgo": "^2.6.4",
"@typescript-eslint/eslint-plugin": "^5.59.8",
"@typescript-eslint/parser": "^5.59.8",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"@typescript-eslint/utils": "^6.21.0",
"babel-loader": "^9.1.2",
"eslint": "^8.44.0",
"eslint-plugin-import": "^2.27.5",
Expand Down
8 changes: 6 additions & 2 deletions packages/eslint-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@
"@types/estraverse": "^5.1.7",
"@types/estree": "^1.0.3",
"@types/estree-jsx": "^1.0.2",
"@typescript-eslint/parser": "^5.59.8",
"@typescript-eslint/parser": "^6.21.0",
"@typescript-eslint/utils": "^6.21.0",
"eslint": "^8.41.0",
"outdent": "^0.8.0",
"typescript": "^4.9.5"
"typescript": "~4.9.5"
},
"engines": {
"node": "^16.0.0 || >=18.0.0"
},
"publishConfig": {
"registry": "https://registry.npmjs.org/"
Expand Down
5 changes: 3 additions & 2 deletions packages/eslint-plugin/src/rules/jsx-pragma/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
usesCompiledAPI,
} from '../../utils/ast';
import { addImportToDeclaration, removeImportFromDeclaration } from '../../utils/ast-to-string';
import { getDeclaredVariables, getSourceCode } from '../../utils/context-compat';
import {
findJsxImportSourcePragma,
findJsxPragma,
Expand Down Expand Up @@ -75,7 +76,7 @@ function createFixer(context: Rule.RuleContext, source: SourceCode, options: Opt
const reactImport = findReactDeclarationWithDefaultImport(source);
if (reactImport) {
const [declaration, defaultImport] = reactImport;
const [defaultImportVariable] = context.getDeclaredVariables(defaultImport);
const [defaultImportVariable] = getDeclaredVariables(context, defaultImport);

if (defaultImportVariable && defaultImportVariable.references.length === 0) {
if (declaration.specifiers.length === 1) {
Expand Down Expand Up @@ -166,7 +167,7 @@ export const jsxPragmaRule: Rule.RuleModule = {
importSources: [...DEFAULT_IMPORT_SOURCES, ...(optionsRaw.importSources ?? [])],
};

const source = context.getSourceCode();
const source = getSourceCode(context);
const comments = source.getAllComments();

const compiledImports = findLibraryImportDeclarations(context, options.importSources);
Expand Down
3 changes: 2 additions & 1 deletion packages/eslint-plugin/src/rules/local-cx-xcss/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Rule } from 'eslint';

import { isCxFunction } from '../../utils';
import { getScope } from '../../utils/context-compat';

function getParentJSXAttribute(node: Rule.Node) {
let parent: Rule.Node | null = node.parent;
Expand Down Expand Up @@ -34,7 +35,7 @@ export const localCXXCSSRule: Rule.RuleModule = {
'CallExpression[callee.name="cx"]': (node: Rule.Node) => {
if (
node.type === 'CallExpression' &&
isCxFunction(node.callee as Rule.Node, context.getScope().references)
isCxFunction(node.callee as Rule.Node, getScope(context, node).references)
) {
const parentJSXAttribute = getParentJSXAttribute(node);
const propName = parentJSXAttribute?.name.name.toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
buildImportDeclaration,
getImportedName,
} from '../../utils/ast-to-string';
import { getScope, getSourceCode } from '../../utils/context-compat';

type Q<T> = T extends TSESLint.Scope.Definition
? T['type'] extends 'Variable'
Expand Down Expand Up @@ -39,7 +40,7 @@ class NoCssPropWithoutCssFunctionRunner {

constructor(private baseNode: TSESTree.JSXExpressionContainer, private context: Context) {
this.jsxElement = traverseUpToJSXOpeningElement(this.baseNode);
this.references = context.getScope().references;
this.references = getScope(context, baseNode).references;

this.ignoreIfImported = [];
this.excludeReactComponents = false;
Expand Down Expand Up @@ -125,7 +126,7 @@ class NoCssPropWithoutCssFunctionRunner {
private fixWrapper(node: CSSValue, context: Context) {
function* fix(fixer: TSESLint.RuleFixer) {
const compiledImports = findTSLibraryImportDeclarations(context);
const source = context.getSourceCode();
const source = getSourceCode(context);

// The string that `css` from `@compiled/css` is imported as
const cssImportName = getImportedName(compiledImports, 'css');
Expand Down Expand Up @@ -220,7 +221,6 @@ export const noCssPropWithoutCssFunctionRule: TSESLint.RuleModule<string> = {
meta: {
docs: {
url: 'https://github.com/atlassian-labs/compiled/tree/master/packages/eslint-plugin/src/rules/no-css-prop-without-css-function',
recommended: 'error',
description:
'Disallows `css` prop usages where it is either not wrapped in the `css` import from `@compiled/react` or where `@compiled` cannot determine whether the `css` import is included at build time.',
},
Expand Down
7 changes: 3 additions & 4 deletions packages/eslint-plugin/src/rules/no-emotion-css/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Rule } from 'eslint';
import type { ImportSpecifier, ImportDeclaration } from 'estree';

import { buildImportDeclaration, buildNamedImport } from '../../utils/ast-to-string';
import { getSourceCode } from '../../utils/context-compat';

const ALLOWED_EMOTION_IMPORTS = ['css', 'keyframes', 'ClassNames', 'jsx'];

Expand All @@ -18,8 +19,7 @@ const isEmotionImport = (node: ImportDeclaration) =>
* @returns {Rule.Node} The `@compiled/react` node or undefined
*/
const getCompiledNode = (context: Rule.RuleContext) => {
return context
.getSourceCode()
return getSourceCode(context)
.ast.body.filter((node): node is ImportDeclaration => node.type === 'ImportDeclaration')
.find((node) => node.source.value === COMPILED_IMPORT);
};
Expand All @@ -39,8 +39,7 @@ export const noEmotionCssRule: Rule.RuleModule = {
create(context) {
return {
Program() {
const pragma = context
.getSourceCode()
const pragma = getSourceCode(context)
.getAllComments()
.find((n) => n.value.includes('@jsxImportSource @emotion/react'));

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import type { Rule } from 'eslint';
import type { CallExpression, MemberExpression } from 'estree';

import { getScope } from '../../utils/context-compat';
import { isStyledImportSpecifier } from '../../utils/styled-import';

type RuleModule = Rule.RuleModule;
Expand All @@ -25,7 +26,7 @@ const createNoEmptyStyledExpressionRule =
return {
'CallExpression[callee.type="MemberExpression"]': (node: CallExpression) => {
const membEx: MemberExpression = node.callee as MemberExpression;
const { references } = context.getScope();
const { references } = getScope(context, node);

const isStyledImported =
membEx.object.type === 'Identifier' &&
Expand Down
5 changes: 3 additions & 2 deletions packages/eslint-plugin/src/rules/no-invalid-css-map/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { Rule } from 'eslint';
import type { CallExpression as ESCallExpression } from 'estree';

import { CssMapObjectChecker, getCssMapObject, isCssMap, validateDefinition } from '../../utils';
import { getScope, getSourceCode } from '../../utils/context-compat';

type CallExpression = ESCallExpression & Rule.NodeParentExtension;

Expand Down Expand Up @@ -39,7 +40,7 @@ const reportIfNotTopLevelScope = (node: CallExpression, context: Rule.RuleContex
};

const createCssMapRule = (context: Rule.RuleContext): Rule.RuleListener => {
const { text } = context.getSourceCode();
const { text } = getSourceCode(context);

// Bail out if this is not one of the imports we care about (eg. not from @compiled/react)
if (DEFAULT_IMPORT_SOURCES.every((source) => !text.includes(source))) {
Expand All @@ -48,7 +49,7 @@ const createCssMapRule = (context: Rule.RuleContext): Rule.RuleListener => {

return {
CallExpression(node) {
const references = context.getScope().references;
const references = getScope(context, node).references;

if (!isCssMap(node.callee as Rule.Node, references)) {
return;
Expand Down
4 changes: 3 additions & 1 deletion packages/eslint-plugin/src/rules/no-js-xcss/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { Rule } from 'eslint';

import { getFilename } from '../../utils/context-compat';

export const noJavaScriptXCSSRule: Rule.RuleModule = {
meta: {
docs: {
Expand All @@ -17,7 +19,7 @@ export const noJavaScriptXCSSRule: Rule.RuleModule = {
create(context) {
return {
'JSXAttribute[name.name=/[xX]css$/]': (node: Rule.Node) => {
if (node.type === 'JSXAttribute' && !context.getFilename().endsWith('.tsx')) {
if (node.type === 'JSXAttribute' && !getFilename(context).endsWith('.tsx')) {
context.report({
node: node.name,
messageId: 'no-js-xcss',
Expand Down
4 changes: 3 additions & 1 deletion packages/eslint-plugin/src/rules/no-suppress-xcss/index.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Rule } from 'eslint';

import { getSourceCode } from '../../utils/context-compat';

function nodeIsTypeSuppressed(context: Rule.RuleContext, node: Rule.Node) {
if (!node.loc) {
return;
}

const comments = context.getSourceCode().getAllComments();
const comments = getSourceCode(context).getAllComments();

for (const comment of comments) {
if (!comment.loc) {
Expand Down
Loading

0 comments on commit e6d57ea

Please sign in to comment.