@@ -47,13 +47,15 @@ function mergeUsedPropTypes(propsList, newPropsList) {
4747}
4848
4949const Lists = new WeakMap ( ) ;
50+ const ReactImports = new WeakMap ( ) ;
5051
5152/**
5253 * Components
5354 */
5455class Components {
5556 constructor ( ) {
5657 Lists . set ( this , { } ) ;
58+ ReactImports . set ( this , { } ) ;
5759 }
5860
5961 /**
@@ -179,6 +181,52 @@ class Components {
179181 const list = Lists . get ( this ) ;
180182 return Object . keys ( list ) . filter ( ( i ) => list [ i ] . confidence >= 2 ) . length ;
181183 }
184+
185+ /**
186+ * Return the node naming the default React import
187+ * It can be used to determine the local name of import, even if it's imported
188+ * with an unusual name.
189+ *
190+ * @returns {ASTNode } React default import node
191+ */
192+ getDefaultReactImports ( ) {
193+ return ReactImports . get ( this ) . defaultReactImports ;
194+ }
195+
196+ /**
197+ * Return the nodes of all React named imports
198+ *
199+ * @returns {Object } The list of React named imports
200+ */
201+ getNamedReactImports ( ) {
202+ return ReactImports . get ( this ) . namedReactImports ;
203+ }
204+
205+ /**
206+ * Add the default React import specifier to the scope
207+ *
208+ * @param {ASTNode } specifier The AST Node of the default React import
209+ * @returns {void }
210+ */
211+ addDefaultReactImport ( specifier ) {
212+ const info = ReactImports . get ( this ) ;
213+ ReactImports . set ( this , Object . assign ( { } , info , {
214+ defaultReactImports : ( info . defaultReactImports || [ ] ) . concat ( specifier ) ,
215+ } ) ) ;
216+ }
217+
218+ /**
219+ * Add a named React import specifier to the scope
220+ *
221+ * @param {ASTNode } specifier The AST Node of a named React import
222+ * @returns {void }
223+ */
224+ addNamedReactImport ( specifier ) {
225+ const info = ReactImports . get ( this ) ;
226+ ReactImports . set ( this , Object . assign ( { } , info , {
227+ namedReactImports : ( info . namedReactImports || [ ] ) . concat ( specifier ) ,
228+ } ) ) ;
229+ }
182230}
183231
184232function getWrapperFunctions ( context , pragma ) {
@@ -857,6 +905,25 @@ function componentRule(rule, context) {
857905 } ,
858906 } ;
859907
908+ // Detect React import specifiers
909+ const reactImportInstructions = {
910+ ImportDeclaration ( node ) {
911+ const isReactImported = node . source . type === 'Literal' && node . source . value === 'react' ;
912+ if ( ! isReactImported ) {
913+ return ;
914+ }
915+
916+ node . specifiers . forEach ( ( specifier ) => {
917+ if ( specifier . type === 'ImportDefaultSpecifier' ) {
918+ components . addDefaultReactImport ( specifier ) ;
919+ }
920+ if ( specifier . type === 'ImportSpecifier' ) {
921+ components . addNamedReactImport ( specifier ) ;
922+ }
923+ } ) ;
924+ } ,
925+ } ;
926+
860927 // Update the provided rule instructions to add the component detection
861928 const ruleInstructions = rule ( context , components , utils ) ;
862929 const updatedRuleInstructions = Object . assign ( { } , ruleInstructions ) ;
@@ -866,7 +933,8 @@ function componentRule(rule, context) {
866933 const allKeys = new Set ( Object . keys ( detectionInstructions ) . concat (
867934 Object . keys ( propTypesInstructions ) ,
868935 Object . keys ( usedPropTypesInstructions ) ,
869- Object . keys ( defaultPropsInstructions )
936+ Object . keys ( defaultPropsInstructions ) ,
937+ Object . keys ( reactImportInstructions )
870938 ) ) ;
871939
872940 allKeys . forEach ( ( instruction ) => {
@@ -883,6 +951,9 @@ function componentRule(rule, context) {
883951 if ( instruction in defaultPropsInstructions ) {
884952 defaultPropsInstructions [ instruction ] ( node ) ;
885953 }
954+ if ( instruction in reactImportInstructions ) {
955+ reactImportInstructions [ instruction ] ( node ) ;
956+ }
886957 if ( ruleInstructions [ instruction ] ) {
887958 return ruleInstructions [ instruction ] ( node ) ;
888959 }
0 commit comments