3
3
const emberUtils = require ( '../utils/ember' ) ;
4
4
const types = require ( '../utils/types' ) ;
5
5
const decoratorUtils = require ( '../utils/decorators' ) ;
6
- const javascriptUtils = require ( '../utils/javascript' ) ;
7
6
const propertySetterUtils = require ( '../utils/property-setter' ) ;
8
- const assert = require ( 'assert' ) ;
9
7
const { getImportIdentifier } = require ( '../utils/import' ) ;
8
+ const { getMacros } = require ( '../utils/computed-property-macros' ) ;
10
9
const {
11
- expandKeys ,
10
+ findComputedPropertyDependentKeys ,
12
11
keyExistsAsPrefixInList,
13
12
} = require ( '../utils/computed-property-dependent-keys' ) ;
14
13
15
14
const ERROR_MESSAGE =
16
15
"Use `set(this, 'propertyName', 'value')` instead of assignment for untracked properties that are used as computed property dependencies (or convert to using tracked properties)." ;
17
16
18
17
/**
19
- * Gets the list of string dependent keys from a computed property.
20
- *
21
- * @param {Node } node - the computed property node
22
- * @returns {String[] } - the list of string dependent keys from this computed property
23
- */
24
- function getComputedPropertyDependentKeys ( node ) {
25
- if ( ! node . arguments ) {
26
- return [ ] ;
27
- }
28
-
29
- return expandKeys (
30
- node . arguments
31
- . filter ( ( arg ) => arg . type === 'Literal' && typeof arg . value === 'string' )
32
- . map ( ( node ) => node . value )
33
- ) ;
34
- }
35
-
36
- /**
37
- * Gets a list of computed property dependency keys used inside a class.
18
+ * Gets a set of tracked properties used inside a class.
38
19
*
39
20
* @param {Node } nodeClass - Node for the class
40
- * @returns {String[] } - list of dependent keys used inside the class
41
- */
42
- function findComputedPropertyDependentKeys ( nodeClass , computedImportName ) {
43
- if ( types . isClassDeclaration ( nodeClass ) ) {
44
- // Native JS class.
45
- return javascriptUtils . flatMap ( nodeClass . body . body , ( node ) => {
46
- const computedDecorator = decoratorUtils . findDecorator ( node , computedImportName ) ;
47
- if ( computedDecorator ) {
48
- return getComputedPropertyDependentKeys ( computedDecorator . expression ) ;
49
- } else {
50
- return [ ] ;
51
- }
52
- } ) ;
53
- } else if ( types . isCallExpression ( nodeClass ) ) {
54
- // Classic class.
55
- return javascriptUtils . flatMap (
56
- nodeClass . arguments . filter ( types . isObjectExpression ) ,
57
- ( classObject ) => {
58
- return javascriptUtils . flatMap ( classObject . properties , ( node ) => {
59
- if (
60
- types . isProperty ( node ) &&
61
- emberUtils . isComputedProp ( node . value ) &&
62
- node . value . arguments
63
- ) {
64
- return getComputedPropertyDependentKeys ( node . value ) ;
65
- } else {
66
- return [ ] ;
67
- }
68
- } ) ;
69
- }
70
- ) ;
71
- } else {
72
- assert ( false , 'Unexpected node type for a class.' ) ;
73
- }
74
-
75
- return [ ] ;
76
- }
77
-
78
- /**
79
- * Gets a list of tracked properties used inside a class.
80
- *
81
- * @param {Node } nodeClass - Node for the class
82
- * @returns {String[] } - list of tracked properties used inside the class
21
+ * @returns {Set<string> } - set of tracked properties used inside the class
83
22
*/
84
23
function findTrackedProperties ( nodeClassDeclaration , trackedImportName ) {
85
- return nodeClassDeclaration . body . body
86
- . filter (
87
- ( node ) =>
88
- types . isClassProperty ( node ) &&
89
- decoratorUtils . hasDecorator ( node , trackedImportName ) &&
90
- types . isIdentifier ( node . key )
91
- )
92
- . map ( ( node ) => node . key . name ) ;
24
+ return new Set (
25
+ nodeClassDeclaration . body . body
26
+ . filter (
27
+ ( node ) =>
28
+ types . isClassProperty ( node ) &&
29
+ decoratorUtils . hasDecorator ( node , trackedImportName ) &&
30
+ types . isIdentifier ( node . key )
31
+ )
32
+ . map ( ( node ) => node . key . name )
33
+ ) ;
93
34
}
94
35
95
36
class Stack {
@@ -137,6 +78,7 @@ module.exports = {
137
78
let computedImportName = undefined ;
138
79
let trackedImportName = undefined ;
139
80
let setImportName = undefined ;
81
+ let macroImportNames = new Map ( ) ;
140
82
141
83
// State being tracked for the current class we're inside.
142
84
const classStack = new Stack ( ) ;
@@ -147,6 +89,14 @@ module.exports = {
147
89
computedImportName =
148
90
computedImportName || getImportIdentifier ( node , '@ember/object' , 'computed' ) ;
149
91
setImportName = setImportName || getImportIdentifier ( node , '@ember/object' , 'set' ) ;
92
+ } else if ( node . source . value === '@ember/object/computed' ) {
93
+ macroImportNames = new Map (
94
+ getMacros ( ) . map ( ( macro ) => [
95
+ macro ,
96
+ macroImportNames . get ( macro ) ||
97
+ getImportIdentifier ( node , '@ember/object/computed' , macro ) ,
98
+ ] )
99
+ ) ;
150
100
} else if ( node . source . value === '@glimmer/tracking' ) {
151
101
trackedImportName =
152
102
trackedImportName || getImportIdentifier ( node , '@glimmer/tracking' , 'tracked' ) ;
@@ -156,12 +106,14 @@ module.exports = {
156
106
// Native JS class:
157
107
ClassDeclaration ( node ) {
158
108
// Gather computed property dependent keys from this class.
159
- const computedPropertyDependentKeys = new Set (
160
- findComputedPropertyDependentKeys ( node , computedImportName )
109
+ const computedPropertyDependentKeys = findComputedPropertyDependentKeys (
110
+ node ,
111
+ computedImportName ,
112
+ macroImportNames
161
113
) ;
162
114
163
115
// Gather tracked properties from this class.
164
- const trackedProperties = new Set ( findTrackedProperties ( node , trackedImportName ) ) ;
116
+ const trackedProperties = findTrackedProperties ( node , trackedImportName ) ;
165
117
166
118
// Keep track of whether we're inside a Glimmer component.
167
119
const isGlimmerComponent = emberUtils . isGlimmerComponent ( context , node ) ;
@@ -178,8 +130,10 @@ module.exports = {
178
130
// Classic class:
179
131
if ( emberUtils . isAnyEmberCoreModule ( context , node ) ) {
180
132
// Gather computed property dependent keys from this class.
181
- const computedPropertyDependentKeys = new Set (
182
- findComputedPropertyDependentKeys ( node , computedImportName )
133
+ const computedPropertyDependentKeys = findComputedPropertyDependentKeys (
134
+ node ,
135
+ computedImportName ,
136
+ macroImportNames
183
137
) ;
184
138
185
139
// No tracked properties in classic classes.
0 commit comments