@@ -26,27 +26,81 @@ module.exports = {
26
26
} ,
27
27
28
28
create : function ( context ) {
29
+ const testingLibraryQueryUsage = [ ] ;
29
30
return {
30
31
[ `CallExpression > Identifier[name=${ ASYNC_QUERIES_REGEXP } ]` ] ( node ) {
31
- let hasError = true ;
32
- try {
33
- if ( VALID_PARENTS . includes ( node . parent . parent . type ) ) {
34
- hasError = false ;
35
- }
36
- } catch ( e ) {
37
- // not necessary to do anything
38
- }
39
-
40
- if ( hasError ) {
41
- context . report ( {
32
+ testingLibraryQueryUsage . push ( node ) ;
33
+ } ,
34
+ 'Program:exit' ( ) {
35
+ testingLibraryQueryUsage . forEach ( node => {
36
+ const variableDeclaratorParent = findParent (
42
37
node ,
43
- messageId : 'awaitAsyncQuery' ,
44
- data : {
45
- name : node . name ,
46
- } ,
47
- } ) ;
48
- }
38
+ parent => parent . type === 'VariableDeclarator'
39
+ ) ;
40
+
41
+ const references =
42
+ ( variableDeclaratorParent &&
43
+ context
44
+ . getDeclaredVariables ( variableDeclaratorParent ) [ 0 ]
45
+ . references . slice ( 1 ) ) ||
46
+ [ ] ;
47
+
48
+ if (
49
+ references . length === 0 &&
50
+ ! isAwaited ( node . parent . parent ) &&
51
+ ! isPromiseResolved ( node )
52
+ ) {
53
+ context . report ( {
54
+ node,
55
+ messageId : 'awaitAsyncQuery' ,
56
+ data : {
57
+ name : node . name ,
58
+ } ,
59
+ } ) ;
60
+ } else {
61
+ references . forEach ( reference => {
62
+ const node = reference . identifier ;
63
+ if ( ! isAwaited ( node . parent ) && ! isPromiseResolved ( node ) ) {
64
+ context . report ( {
65
+ node : reference . identifier ,
66
+ messageId : 'awaitAsyncQuery' ,
67
+ data : {
68
+ name : node . name ,
69
+ } ,
70
+ } ) ;
71
+ }
72
+ } ) ;
73
+ }
74
+ } ) ;
49
75
} ,
50
76
} ;
51
77
} ,
52
78
} ;
79
+
80
+ function isAwaited ( node ) {
81
+ return VALID_PARENTS . includes ( node . type ) ;
82
+ }
83
+
84
+ function isPromiseResolved ( node ) {
85
+ const parent = node . parent ;
86
+
87
+ const hasAThenProperty = node =>
88
+ node . type === 'MemberExpression' && node . property . name === 'then' ;
89
+
90
+ // findByText("foo").then(...)
91
+ if ( parent . type === 'CallExpression' ) {
92
+ return hasAThenProperty ( parent . parent ) ;
93
+ }
94
+
95
+ // promise.then(...)
96
+ return hasAThenProperty ( parent ) ;
97
+ }
98
+
99
+ function findParent ( node , test ) {
100
+ if ( test ( node ) ) {
101
+ return node ;
102
+ } else if ( node . parent ) {
103
+ return findParent ( node . parent , test ) ;
104
+ }
105
+ return null ;
106
+ }
0 commit comments