@@ -83,8 +83,93 @@ function isRuleTesterConstruction (node) {
83
83
) ;
84
84
}
85
85
86
- module . exports = {
86
+ const INTERESTING_RULE_KEYS = new Set ( [ 'create' , 'meta' ] ) ;
87
+
88
+ /**
89
+ * Helper for `getRuleInfo`. Handles ESM rules.
90
+ */
91
+ function getRuleExportsESM ( ast ) {
92
+ return ast . body
93
+ . filter ( statement => statement . type === 'ExportDefaultDeclaration' )
94
+ . map ( statement => statement . declaration )
95
+ // eslint-disable-next-line unicorn/prefer-object-from-entries
96
+ . reduce ( ( currentExports , node ) => {
97
+ 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
+ } , { } ) ;
106
+ } else if ( isNormalFunctionExpression ( node ) ) {
107
+ return { create : node , meta : null , isNewStyle : false } ;
108
+ }
109
+ return currentExports ;
110
+ } , { } ) ;
111
+ }
112
+
113
+ /**
114
+ * Helper for `getRuleInfo`. Handles CJS rules.
115
+ */
116
+ function getRuleExportsCJS ( ast ) {
117
+ let exportsVarOverridden = false ;
118
+ let exportsIsFunction = false ;
119
+ return ast . body
120
+ . filter ( statement => statement . type === 'ExpressionStatement' )
121
+ . map ( statement => statement . expression )
122
+ . filter ( expression => expression . type === 'AssignmentExpression' )
123
+ . filter ( expression => expression . left . type === 'MemberExpression' )
124
+ // eslint-disable-next-line unicorn/prefer-object-from-entries
125
+ . reduce ( ( currentExports , node ) => {
126
+ if (
127
+ node . left . object . type === 'Identifier' && node . left . object . name === 'module' &&
128
+ node . left . property . type === 'Identifier' && node . left . property . name === 'exports'
129
+ ) {
130
+ exportsVarOverridden = true ;
131
+ if ( isNormalFunctionExpression ( node . right ) ) {
132
+ // Check `module.exports = function () {}`
133
+
134
+ exportsIsFunction = true ;
135
+ return { create : node . right , meta : null , isNewStyle : false } ;
136
+ } else if ( node . right . type === 'ObjectExpression' ) {
137
+ // Check `module.exports = { create: function () {}, meta: {} }`
138
+
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
+ } , { } ) ;
147
+ }
148
+ return { } ;
149
+ } else if (
150
+ ! exportsIsFunction &&
151
+ node . left . object . type === 'MemberExpression' &&
152
+ node . left . object . object . type === 'Identifier' && node . left . object . object . name === 'module' &&
153
+ node . left . object . property . type === 'Identifier' && node . left . object . property . name === 'exports' &&
154
+ node . left . property . type === 'Identifier' && INTERESTING_RULE_KEYS . has ( node . left . property . name )
155
+ ) {
156
+ // Check `module.exports.create = () => {}`
87
157
158
+ currentExports [ node . left . property . name ] = node . right ;
159
+ } else if (
160
+ ! exportsVarOverridden &&
161
+ node . left . object . type === 'Identifier' && node . left . object . name === 'exports' &&
162
+ node . left . property . type === 'Identifier' && INTERESTING_RULE_KEYS . has ( node . left . property . name )
163
+ ) {
164
+ // Check `exports.create = () => {}`
165
+
166
+ currentExports [ node . left . property . name ] = node . right ;
167
+ }
168
+ return currentExports ;
169
+ } , { } ) ;
170
+ }
171
+
172
+ module . exports = {
88
173
/**
89
174
* Performs static analysis on an AST to try to determine the final value of `module.exports`.
90
175
* @param {{ast: ASTNode, scopeManager?: ScopeManager} } sourceCode The object contains `Program` AST node, and optional `scopeManager`
@@ -94,63 +179,7 @@ module.exports = {
94
179
from the file, the return value will be `null`.
95
180
*/
96
181
getRuleInfo ( { ast, scopeManager } ) {
97
- const INTERESTING_KEYS = new Set ( [ 'create' , 'meta' ] ) ;
98
- let exportsVarOverridden = false ;
99
- let exportsIsFunction = false ;
100
-
101
- const exportNodes = ast . body
102
- . filter ( statement => statement . type === 'ExpressionStatement' )
103
- . map ( statement => statement . expression )
104
- . filter ( expression => expression . type === 'AssignmentExpression' )
105
- . filter ( expression => expression . left . type === 'MemberExpression' )
106
- // eslint-disable-next-line unicorn/prefer-object-from-entries
107
- . reduce ( ( currentExports , node ) => {
108
- if (
109
- node . left . object . type === 'Identifier' && node . left . object . name === 'module' &&
110
- node . left . property . type === 'Identifier' && node . left . property . name === 'exports'
111
- ) {
112
- exportsVarOverridden = true ;
113
-
114
- if ( isNormalFunctionExpression ( node . right ) ) {
115
- // Check `module.exports = function () {}`
116
-
117
- exportsIsFunction = true ;
118
- return { create : node . right , meta : null } ;
119
- } else if ( node . right . type === 'ObjectExpression' ) {
120
- // Check `module.exports = { create: function () {}, meta: {} }`
121
-
122
- exportsIsFunction = false ;
123
- // eslint-disable-next-line unicorn/prefer-object-from-entries
124
- return node . right . properties . reduce ( ( parsedProps , prop ) => {
125
- const keyValue = module . exports . getKeyName ( prop ) ;
126
- if ( INTERESTING_KEYS . has ( keyValue ) ) {
127
- parsedProps [ keyValue ] = prop . value ;
128
- }
129
- return parsedProps ;
130
- } , { } ) ;
131
- }
132
- return { } ;
133
- } else if (
134
- ! exportsIsFunction &&
135
- node . left . object . type === 'MemberExpression' &&
136
- node . left . object . object . type === 'Identifier' && node . left . object . object . name === 'module' &&
137
- node . left . object . property . type === 'Identifier' && node . left . object . property . name === 'exports' &&
138
- node . left . property . type === 'Identifier' && INTERESTING_KEYS . has ( node . left . property . name )
139
- ) {
140
- // Check `module.exports.create = () => {}`
141
-
142
- currentExports [ node . left . property . name ] = node . right ;
143
- } else if (
144
- ! exportsVarOverridden &&
145
- node . left . object . type === 'Identifier' && node . left . object . name === 'exports' &&
146
- node . left . property . type === 'Identifier' && INTERESTING_KEYS . has ( node . left . property . name )
147
- ) {
148
- // Check `exports.create = () => {}`
149
-
150
- currentExports [ node . left . property . name ] = node . right ;
151
- }
152
- return currentExports ;
153
- } , { } ) ;
182
+ const exportNodes = ast . sourceType === 'module' ? getRuleExportsESM ( ast ) : getRuleExportsCJS ( ast ) ;
154
183
155
184
const createExists = Object . prototype . hasOwnProperty . call ( exportNodes , 'create' ) ;
156
185
if ( ! createExists ) {
@@ -164,7 +193,7 @@ module.exports = {
164
193
return null ;
165
194
}
166
195
167
- return Object . assign ( { isNewStyle : ! exportsIsFunction , meta : null } , exportNodes ) ;
196
+ return Object . assign ( { isNewStyle : true , meta : null } , exportNodes ) ;
168
197
} ,
169
198
170
199
/**
0 commit comments