5
5
* LICENSE file in the root directory of this source tree.
6
6
*/
7
7
8
- import { effect } from 'zod' ;
9
8
import { CompilerError , Effect , ErrorSeverity , SourceLocation } from '..' ;
10
9
import { ErrorCategory } from '../CompilerError' ;
11
10
import {
12
11
ArrayExpression ,
13
12
BasicBlock ,
14
13
BlockId ,
15
- Identifier ,
16
14
FunctionExpression ,
17
15
HIRFunction ,
18
16
IdentifierId ,
@@ -21,15 +19,12 @@ import {
21
19
isSetStateType ,
22
20
isUseEffectHookType ,
23
21
isUseStateType ,
24
- IdentifierName ,
25
22
GeneratedSource ,
26
23
} from '../HIR' ;
27
- import { printInstruction } from '../HIR/PrintHIR' ;
28
24
import {
29
25
eachInstructionOperand ,
30
26
eachTerminalOperand ,
31
27
eachInstructionLValue ,
32
- eachPatternOperand ,
33
28
} from '../HIR/visitors' ;
34
29
import { isMutable } from '../ReactiveScopes/InferReactiveScopeVariables' ;
35
30
import { assertExhaustive } from '../Utils/utils' ;
@@ -47,12 +42,10 @@ type SetStateName = string | undefined | null;
47
42
48
43
type DerivationMetadata = {
49
44
typeOfValue : TypeOfValue ;
50
- // TODO: Rename to place
51
- identifierPlace : Place ;
52
- sources : Place [ ] ;
45
+ place : Place ;
46
+ sources : Array < Place > ;
53
47
} ;
54
48
55
- // TODO: This needs refining
56
49
type ErrorMetadata = {
57
50
errorType : TypeOfValue ;
58
51
invalidDepInfo : string | undefined ;
@@ -72,20 +65,22 @@ function joinValue(
72
65
73
66
function updateDerivationMetadata (
74
67
target : Place ,
75
- sources : DerivationMetadata [ ] ,
68
+ sources : Array < DerivationMetadata > ,
76
69
typeOfValue : TypeOfValue ,
77
70
derivedTuple : Map < IdentifierId , DerivationMetadata > ,
78
71
) : void {
79
72
let newValue : DerivationMetadata = {
80
- identifierPlace : target ,
73
+ place : target ,
81
74
sources : [ ] ,
82
75
typeOfValue : typeOfValue ,
83
76
} ;
84
77
85
78
for ( const source of sources ) {
86
- // If the identifier of the source is a promoted identifier, then
87
- // we should set the target as the source.
88
- if ( source . identifierPlace . identifier . name ?. kind === 'promoted' ) {
79
+ /*
80
+ * If the identifier of the source is a promoted identifier, then
81
+ * we should set the target as the source.
82
+ */
83
+ if ( source . place . identifier . name ?. kind === 'promoted' ) {
89
84
newValue . sources . push ( target ) ;
90
85
} else {
91
86
newValue . sources . push ( ...source . sources ) ;
@@ -97,10 +92,8 @@ function updateDerivationMetadata(
97
92
function parseInstr (
98
93
instr : Instruction ,
99
94
derivedTuple : Map < IdentifierId , DerivationMetadata > ,
100
- setStateCalls : Map < SetStateName , Place [ ] > ,
101
- ) {
102
- // console.log(printInstruction(instr));
103
- // console.log(instr);
95
+ setStateCalls : Map < SetStateName , Array < Place > > ,
96
+ ) : void {
104
97
let typeOfValue : TypeOfValue = 'ignored' ;
105
98
106
99
// TODO: Not sure if this will catch every time we create a new useState
@@ -112,7 +105,7 @@ function parseInstr(
112
105
const value = instr . value . lvalue . pattern . items [ 0 ] ;
113
106
if ( value . kind === 'Identifier' ) {
114
107
derivedTuple . set ( value . identifier . id , {
115
- identifierPlace : value ,
108
+ place : value ,
116
109
sources : [ value ] ,
117
110
typeOfValue : 'fromState' ,
118
111
} ) ;
@@ -137,7 +130,7 @@ function parseInstr(
137
130
}
138
131
}
139
132
140
- let sources : DerivationMetadata [ ] = [ ] ;
133
+ let sources : Array < DerivationMetadata > = [ ] ;
141
134
for ( const operand of eachInstructionOperand ( instr ) ) {
142
135
const opSource = derivedTuple . get ( operand . identifier . id ) ;
143
136
if ( opSource === undefined ) {
@@ -197,23 +190,23 @@ function parseInstr(
197
190
function parseBlockPhi (
198
191
block : BasicBlock ,
199
192
derivedTuple : Map < IdentifierId , DerivationMetadata > ,
200
- ) {
193
+ ) : void {
201
194
for ( const phi of block . phis ) {
202
195
for ( const operand of phi . operands . values ( ) ) {
203
196
const source = derivedTuple . get ( operand . identifier . id ) ;
204
197
if ( source !== undefined && source . typeOfValue === 'fromProps' ) {
205
198
if (
206
- source . identifierPlace . identifier . name === null ||
207
- source . identifierPlace . identifier . name ?. kind === 'promoted'
199
+ source . place . identifier . name === null ||
200
+ source . place . identifier . name ?. kind === 'promoted'
208
201
) {
209
202
derivedTuple . set ( phi . place . identifier . id , {
210
- identifierPlace : phi . place ,
203
+ place : phi . place ,
211
204
sources : [ phi . place ] ,
212
205
typeOfValue : 'fromProps' ,
213
206
} ) ;
214
207
} else {
215
208
derivedTuple . set ( phi . place . identifier . id , {
216
- identifierPlace : phi . place ,
209
+ place : phi . place ,
217
210
sources : source . sources ,
218
211
typeOfValue : 'fromProps' ,
219
212
} ) ;
@@ -252,16 +245,16 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void {
252
245
const locals : Map < IdentifierId , IdentifierId > = new Map ( ) ;
253
246
const derivedTuple : Map < IdentifierId , DerivationMetadata > = new Map ( ) ;
254
247
255
- const effectSetStates : Map < SetStateName , Place [ ] > = new Map ( ) ;
256
- const setStateCalls : Map < SetStateName , Place [ ] > = new Map ( ) ;
248
+ const effectSetStates : Map < SetStateName , Array < Place > > = new Map ( ) ;
249
+ const setStateCalls : Map < SetStateName , Array < Place > > = new Map ( ) ;
257
250
258
- const errors : ErrorMetadata [ ] = [ ] ;
251
+ const errors : Array < ErrorMetadata > = [ ] ;
259
252
260
253
if ( fn . fnType === 'Hook' ) {
261
254
for ( const param of fn . params ) {
262
255
if ( param . kind === 'Identifier' ) {
263
256
derivedTuple . set ( param . identifier . id , {
264
- identifierPlace : param ,
257
+ place : param ,
265
258
sources : [ param ] ,
266
259
typeOfValue : 'fromProps' ,
267
260
} ) ;
@@ -271,7 +264,7 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void {
271
264
const props = fn . params [ 0 ] ;
272
265
if ( props != null && props . kind === 'Identifier' ) {
273
266
derivedTuple . set ( props . identifier . id , {
274
- identifierPlace : props ,
267
+ place : props ,
275
268
sources : [ props ] ,
276
269
typeOfValue : 'fromProps' ,
277
270
} ) ;
@@ -348,7 +341,6 @@ export function validateNoDerivedComputationsInEffects(fn: HIRFunction): void {
348
341
const throwableErrors = new CompilerError ( ) ;
349
342
for ( const error of errors ) {
350
343
let reason ;
351
- let description = '' ;
352
344
// TODO: Not sure if this is robust enough.
353
345
/*
354
346
* If we use a setState from an invalid useEffect elsewhere then we probably have to
@@ -383,8 +375,8 @@ function validateEffect(
383
375
effectFunction : HIRFunction ,
384
376
effectDeps : Array < IdentifierId > ,
385
377
derivedTuple : Map < IdentifierId , DerivationMetadata > ,
386
- effectSetStates : Map < SetStateName , Place [ ] > ,
387
- errors : ErrorMetadata [ ] ,
378
+ effectSetStates : Map < SetStateName , Array < Place > > ,
379
+ errors : Array < ErrorMetadata > ,
388
380
) : void {
389
381
/*
390
382
* TODO: This makes it so we only capture single line useEffects.
@@ -554,6 +546,12 @@ function validateEffect(
554
546
invalidDepInfo = sourceNames
555
547
? `Invalid deps from local state: ${ sourceNames } `
556
548
: '' ;
549
+ } else {
550
+ sourceNames += `[${ placeNames } ], ` ;
551
+ sourceNames = sourceNames . slice ( 0 , - 2 ) ;
552
+ invalidDepInfo = sourceNames
553
+ ? `Invalid deps from both props and local state: ${ sourceNames } `
554
+ : '' ;
557
555
}
558
556
559
557
errors . push ( {
0 commit comments