@@ -85,6 +85,23 @@ function isRuleTesterConstruction (node) {
85
85
86
86
const INTERESTING_RULE_KEYS = new Set ( [ 'create' , 'meta' ] ) ;
87
87
88
+ /**
89
+ * Collect properties from an object that have interesting key names into a new object
90
+ * @param {Node[] } properties
91
+ * @param {Set<String> } interestingKeys
92
+ * @returns Object
93
+ */
94
+ function collectInterestingProperties ( properties , interestingKeys ) {
95
+ // eslint-disable-next-line unicorn/prefer-object-from-entries
96
+ return properties . reduce ( ( parsedProps , prop ) => {
97
+ const keyValue = module . exports . getKeyName ( prop ) ;
98
+ if ( interestingKeys . has ( keyValue ) ) {
99
+ parsedProps [ keyValue ] = prop . value ;
100
+ }
101
+ return parsedProps ;
102
+ } , { } ) ;
103
+ }
104
+
88
105
/**
89
106
* Helper for `getRuleInfo`. Handles ESM rules.
90
107
*/
@@ -95,16 +112,27 @@ function getRuleExportsESM (ast) {
95
112
// eslint-disable-next-line unicorn/prefer-object-from-entries
96
113
. reduce ( ( currentExports , node ) => {
97
114
if ( node . type === 'ObjectExpression' ) {
98
- // eslint-disable-next-line unicorn/prefer-object-from-entries
99
- return node . properties . reduce ( ( parsedProps , prop ) => {
100
- const keyValue = module . exports . getKeyName ( prop ) ;
101
- if ( INTERESTING_RULE_KEYS . has ( keyValue ) ) {
102
- parsedProps [ keyValue ] = prop . value ;
103
- }
104
- return parsedProps ;
105
- } , { } ) ;
115
+ // Check `export default { create() {}, meta: {} }`
116
+ return collectInterestingProperties ( node . properties , INTERESTING_RULE_KEYS ) ;
106
117
} else if ( isNormalFunctionExpression ( node ) ) {
118
+ // Check `export default function() {}`
107
119
return { create : node , meta : null , isNewStyle : false } ;
120
+ } else if (
121
+ node . type === 'CallExpression' &&
122
+ node . arguments . length === 1 &&
123
+ node . arguments [ 0 ] . type === 'ObjectExpression' &&
124
+ // Check various TypeScript rule helper formats.
125
+ (
126
+ // createESLintRule({ ... })
127
+ node . callee . type === 'Identifier' ||
128
+ // util.createRule({ ... })
129
+ ( node . callee . type === 'MemberExpression' && node . callee . object . type === 'Identifier' && node . callee . property . type === 'Identifier' ) ||
130
+ // ESLintUtils.RuleCreator(docsUrl)({ ... })
131
+ ( node . callee . type === 'CallExpression' && node . callee . callee . type === 'MemberExpression' && node . callee . callee . object . type === 'Identifier' && node . callee . callee . property . type === 'Identifier' )
132
+ )
133
+ ) {
134
+ // Check `export default someTypeScriptHelper({ create() {}, meta: {} });
135
+ return collectInterestingProperties ( node . arguments [ 0 ] . properties , INTERESTING_RULE_KEYS ) ;
108
136
}
109
137
return currentExports ;
110
138
} , { } ) ;
@@ -136,14 +164,7 @@ function getRuleExportsCJS (ast) {
136
164
} else if ( node . right . type === 'ObjectExpression' ) {
137
165
// Check `module.exports = { create: function () {}, meta: {} }`
138
166
139
- // eslint-disable-next-line unicorn/prefer-object-from-entries
140
- return node . right . properties . reduce ( ( parsedProps , prop ) => {
141
- const keyValue = module . exports . getKeyName ( prop ) ;
142
- if ( INTERESTING_RULE_KEYS . has ( keyValue ) ) {
143
- parsedProps [ keyValue ] = prop . value ;
144
- }
145
- return parsedProps ;
146
- } , { } ) ;
167
+ return collectInterestingProperties ( node . right . properties , INTERESTING_RULE_KEYS ) ;
147
168
}
148
169
return { } ;
149
170
} else if (
0 commit comments