Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/wicked-cooks-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@naverpay/eslint-plugin": patch
---

Support eslint 9 for eslint-plugin

PR: [Support eslint 9 for eslint-plugin](https://github.com/NaverPayDev/code-style/pull/79)
3 changes: 2 additions & 1 deletion packages/eslint-plugin/lib/rules/import-server-only.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ export default {
(statement) => statement.type === 'ImportDeclaration' && statement.source.value === 'server-only',
)

const sourceCode = context.getSourceCode()
const sourceCode = context.sourceCode ?? context.getSourceCode()

if (!hasServerOnlyImport) {
context.report({
node,
Expand Down
39 changes: 28 additions & 11 deletions packages/eslint-plugin/lib/rules/memo-react-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,19 @@ export default {
},
create: function (context) {
const filename = context.filename.replace(context.cwd, '')
const isFileInPath = context.options[0].path.some((pattern) => minimatch(filename, pattern))
if (!isFileInPath) {
return {}
}

const isMatched = context.options[0].path.some((pattern) => minimatch(filename, pattern))
let isAlreadyMemoized = false

const globalScope = context.getScope()
const sourceCode = context.sourceCode ?? context.getSourceCode()

/**
* @type {import('eslint').Scope.Scope | undefined}
*/
let globalScope

function importReactMemo(fixer) {
let i = 0
Expand Down Expand Up @@ -77,18 +86,22 @@ export default {
return result
}

if (!isMatched) {
return {}
}

const exportDefaultDeclaration = getExportDefaultDeclaration(globalScope.block).declaration
if (exportDefaultDeclaration.type === 'CallExpression' && exportDefaultDeclaration.callee.name === 'memo') {
return {}
}

return {
Program: function (node) {
globalScope = sourceCode.getScope ? sourceCode.getScope(node) : context.getScope()

const exportDefaultDeclaration = getExportDefaultDeclaration(globalScope.block).declaration
if (
exportDefaultDeclaration.type === 'CallExpression' &&
exportDefaultDeclaration.callee.name === 'memo'
) {
isAlreadyMemoized = true
}
},
// const res = function getAssets({width, height, color}) ... 에 대응
FunctionExpression: function (node) {
if (isAlreadyMemoized) return

const hasJSXBody = node.body.body.some(
(item) => item.type === 'ReturnStatement' && item.argument.type === 'JSXElement',
)
Expand All @@ -114,6 +127,8 @@ export default {
},
// function getAssets({width, height, color}) ... 에 대응
FunctionDeclaration: function (node) {
if (isAlreadyMemoized) return

// JSX를 리턴하는 함수인지 체크
const hasJSXBody = node.body.body.some(
(item) => item.type === 'ReturnStatement' && item.argument.type === 'JSXElement',
Expand Down Expand Up @@ -159,6 +174,8 @@ export default {
},
// const getAssets = ({width, height, color}) => ... 에 대응
VariableDeclaration: function (node) {
if (isAlreadyMemoized) return

if (node.declarations.length === 1) {
const nodeDeclaration = node.declarations[0]

Expand Down
24 changes: 15 additions & 9 deletions packages/eslint-plugin/lib/rules/optimize-svg-components.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@ import {
/**
*
* @param {import('eslint').Rule.RuleContext} context
* @param {import('eslint').Scope.Scope} globalScope
* @returns {boolean}
*/
const svgValidator = (context) => {
const globalScope = context.getScope()
const svgValidator = (context, globalScope) => {
const importDeclarations = getImportDeclarations(globalScope.block)
const hasClassNames =
findSpecificImportDeclaration(importDeclarations, {
Expand Down Expand Up @@ -141,16 +141,22 @@ export default {
return {}
}

const globalScope = context.getScope()
const sourceCode = context.getSourceCode()
const canOptimize = svgValidator(context)
const sourceCode = context.sourceCode ?? context.getSourceCode()

if (!canOptimize) {
return {}
}
/**
* @type {import('eslint').Scope.Scope | undefined}
*/
let globalScope
let canOptimize

return {
onCodePathEnd: function (codePath, code) {
Program: function (node) {
globalScope = sourceCode.getScope ? sourceCode.getScope(node) : context.getScope()
canOptimize = svgValidator(context, globalScope)
},
onCodePathEnd: function (_, code) {
if (!canOptimize) return

try {
// 변수타입, 함수타입 모두 GET
const node = getTargetNode(code)
Expand Down
53 changes: 27 additions & 26 deletions packages/eslint-plugin/lib/rules/svg-unique-id.js
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ function insertCustomImport({fixer, scope}) {
}

/**
*
* @param {ReturnType<import ('@pie/ast-parser').extractComponentProps>} props
*/
function getIdProps(props) {
Expand Down Expand Up @@ -72,28 +71,32 @@ function insertIdProps(props, globalScope, fixer) {
return []
}

/**
* @param {JSXElement|undefined} node
*/
function isSvgElement(node) {
return node && node.openingElement.name.type === 'JSXIdentifier' && node.openingElement.name.name === 'svg'
}
/**
* @type {import('eslint').Rule.RuleModule}
*/
export default {
meta: {
type: 'suggestion',

docs: {
description: 'set a unique id to svg component',
recommended: true,
},
fixable: 'code',
schema: [
{
properties: [
{
paths: {
type: 'array',
items: [{type: 'string'}],
},
type: 'object',
properties: {
paths: {
type: 'array',
items: {type: 'string'},
},
],
},
},
],
},
Expand All @@ -115,26 +118,24 @@ export default {
return {}
}

const globalScope = context.getScope()

const svgElement = getJSXReturnStatement(globalScope)

if (
!svgElement ||
svgElement.openingElement.name.type !== 'JSXIdentifier' ||
svgElement.openingElement.name.name !== 'svg'
) {
return {}
}

const props = extractComponentProps(globalScope.block)

const idPropsValue = getIdProps(props)

const propsDefinition = idPropsValue ? ` id={${idPropsValue}}` : ''
/**
* @type {import('eslint').Scope.Scope | undefined}
*/
let globalScope
const sourceCode = context.sourceCode ?? context.getSourceCode()

return {
Program: function (node) {
globalScope = sourceCode.getScope ? sourceCode.getScope(node) : context.getScope()
},
onCodePathEnd: function (_, code) {
const svgElement = getJSXReturnStatement(globalScope)
if (!isSvgElement(svgElement)) return

const props = extractComponentProps(globalScope.block)
const idPropsValue = getIdProps(props)
const propsDefinition = idPropsValue ? ` id={${idPropsValue}}` : ''

try {
context.report({
node: code,
Expand Down
25 changes: 2 additions & 23 deletions packages/eslint-plugin/lib/utils/astParser.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {getReactComponentDeclaration, getImportDeclarations} from '@naverpay/ast-parser'
import {getReactComponentDeclaration} from '@naverpay/ast-parser'

export const ReactComponentDeclarationType = {
VariableDeclaration: 'VariableDeclaration',
Expand Down Expand Up @@ -113,33 +113,12 @@ export function hasSpecificReturnStatement(functionDeclaration, returnType) {
)
}

/**
*
* @param {import('eslint').Rule.RuleContext} context
*/
export const getCommentsBeforeImportDeclaration = (context, {name, from}) => {
const globalScope = context.getScope()
const importDeclarations = getImportDeclarations(globalScope.block)
const styleImportDeclaration = findSpecificImportDeclaration(importDeclarations, {
name,
from,
})

const sourceCode = context.getSourceCode()

if (styleImportDeclaration) {
return sourceCode.getCommentsBefore(styleImportDeclaration)
} else {
sourceCode.getAllComments()
}
}

/**
*
* @param {import('eslint').Rule.RuleContext} context
*/
export const getAllComments = (context) => {
const sourceCode = context.getSourceCode()
const sourceCode = context.sourceCode ?? context.getSourceCode()
return sourceCode.getAllComments()
}

Expand Down