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