Skip to content

Commit

Permalink
feat(packages/eslint-plugin-sui): Create rules for @deprecated() deco…
Browse files Browse the repository at this point in the history
…rator
  • Loading branch information
oriolpuig committed Jul 19, 2024
1 parent 9ebc5af commit aa22a8d
Show file tree
Hide file tree
Showing 3 changed files with 171 additions and 1 deletion.
6 changes: 5 additions & 1 deletion packages/eslint-plugin-sui/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ const FactoryPattern = require('./rules/factory-pattern.js')
const SerializeDeserialize = require('./rules/serialize-deserialize.js')
const CommonJS = require('./rules/commonjs.js')
const Decorators = require('./rules/decorators.js')
const DecoratorDeprecated = require('./rules/decorator-deprecated.js')
const DecoratorDeprecatedRemarkMethod = require('./rules/decorator-deprecated-remark-method.js')
const LayersArch = require('./rules/layers-architecture.js')

// ------------------------------------------------------------------------------
Expand All @@ -15,6 +17,8 @@ module.exports = {
'serialize-deserialize': SerializeDeserialize,
commonjs: CommonJS,
decorators: Decorators,
'layers-arch': LayersArch
'layers-arch': LayersArch,
'decorator-deprecated': DecoratorDeprecated,
'decorator-deprecated-remark-method': DecoratorDeprecatedRemarkMethod
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* @fileoverview Ensure that method using @Deprecated() displays a warning alert
*/
'use strict'

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Ensure that method using @Deprecated() displays a warning alert',
recommended: true,
url: 'https://github.mpi-internal.com/scmspain/es-td-agreements/blob/master/30-Frontend/00-agreements'
},
fixable: 'code',
schema: [],
messages: {}
},
create: function (context) {
// TODO: Check using decorator in a Class.

return {
MethodDefinition(node) {
// Method
const method = node

// Method decorators
const methodDecorators = method.decorators
const hasDecorators = methodDecorators?.length > 0

if (!hasDecorators) return

// Get the @Deprecated() decorator from method
const deprecatedDecoratorNode =
hasDecorators && methodDecorators?.find(decorator => decorator?.expression?.callee?.name === 'Deprecated')

if (!deprecatedDecoratorNode) return

// RULE: Mark method with a warning
context.report({
node: method.key,
message: 'This method is marked as a deprecated.'
})
}
}
}
}
115 changes: 115 additions & 0 deletions packages/eslint-plugin-sui/src/rules/decorator-deprecated.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/**
* @fileoverview Ensure that @Deprecated() decorator is used as expected
*/
'use strict'

const dedent = require('string-dedent')

// ------------------------------------------------------------------------------
// Rule Definition
// ------------------------------------------------------------------------------

/** @type {import('eslint').Rule.RuleModule} */
module.exports = {
meta: {
type: 'problem',
docs: {
description: 'Ensure that @Deprecated() decorator is used as expected',
recommended: true,
url: 'https://github.mpi-internal.com/scmspain/es-td-agreements/blob/master/30-Frontend/00-agreements'
},
fixable: 'code',
schema: [],
messages: {
notFoundDecoratorArgumentError: dedent`
The @Deprecated() decorator must have arguments.
`,
notFoundKeyDecoratorArgumentError: dedent`
The @Deprecated() decorator must have a key property.
`,
notFoundMessageDecoratorArgumentError: dedent`
The @Deprecated() decorator must have a message property.
`
}
},
create: function (context) {
// TODO: Check using decorator in a Class.
return {
MethodDefinition(node) {
// Method
const method = node
const methodName = method.key?.name

// Method decorators
const methodDecorators = method.decorators
const hasDecorators = methodDecorators?.length > 0

if (!hasDecorators) return

// Get the @Deprecated() decorator from method
const deprecatedDecoratorNode =
hasDecorators && methodDecorators?.find(decorator => decorator?.expression?.callee?.name === 'Deprecated')

if (!deprecatedDecoratorNode) return

const methodArguments = deprecatedDecoratorNode?.expression?.arguments
const hasArgument = methodArguments.length === 1
const argumentDecorator = hasArgument && methodArguments[0]
const isObjectExpression = hasArgument && argumentDecorator.type === 'ObjectExpression'
const argumentsAreInvalid = !hasArgument || !isObjectExpression

// Get decorator arguments: key and message
const keyProperty =
!argumentsAreInvalid && argumentDecorator.properties?.find(prop => prop?.key?.name === 'key')
const messageProperty =
!argumentsAreInvalid && argumentDecorator.properties?.find(prop => prop?.key?.name === 'message')

// RULE: Decorator must have 1 argument as an object with Key and Message properties
if (argumentsAreInvalid || (!keyProperty && !messageProperty)) {
context.report({
node: deprecatedDecoratorNode,
messageId: 'notFoundDecoratorArgumentError',
*fix(fixer) {
yield fixer.insertTextBefore(
deprecatedDecoratorNode,
`\n @Deprecated({key: '${methodName}', message: 'The ${methodName} function is deprecated.'})`
)
yield fixer.remove(deprecatedDecoratorNode)
}
})
return
}

// RULE: Decorator must have a key property and generates it if it doesn't exist
if (!keyProperty && messageProperty) {
context.report({
node: deprecatedDecoratorNode,
messageId: 'notFoundKeyDecoratorArgumentError',
*fix(fixer) {
yield fixer.insertTextBefore(
deprecatedDecoratorNode,
`\n @Deprecated({key: '${methodName}', message: '${messageProperty.value.value}'})`
)
yield fixer.remove(deprecatedDecoratorNode)
}
})
}

// RULE: Decorator must have a message property and generates it if it doesn't exist
if (keyProperty && !messageProperty) {
context.report({
node: deprecatedDecoratorNode,
messageId: 'notFoundMessageDecoratorArgumentError',
*fix(fixer) {
yield fixer.insertTextBefore(
deprecatedDecoratorNode,
`\n @Deprecated({key: '${keyProperty.value.value}', message: 'The ${methodName} function is deprecated.'})`
)
yield fixer.remove(deprecatedDecoratorNode)
}
})
}
}
}
}
}

0 comments on commit aa22a8d

Please sign in to comment.