@@ -11,7 +11,10 @@ import {
11
11
import { logger } from '../util/Logger.ts' ;
12
12
import { createTsProject } from './createTsProject.ts' ;
13
13
import type { DiffResult } from './DiffResult.ts' ;
14
- import { getExportedVariableNamesAndValues } from './getExportedVariableNamesAndValues.ts' ;
14
+ import {
15
+ getAllVariableNamesAndValuesInFile ,
16
+ getExportedVariableNamesAndValues ,
17
+ } from './getExportedVariableNamesAndValues.ts' ;
15
18
16
19
/**
17
20
Local function to unwrap AsExpressions and TypeAssertions
@@ -38,6 +41,8 @@ function findAndModify(
38
41
localDeclarations : Map < string , Expression > ,
39
42
) : boolean
40
43
{
44
+ objExpr = unwrapExpression ( objExpr ) ;
45
+
41
46
if ( path . length === 0 )
42
47
{
43
48
return false ;
@@ -64,7 +69,9 @@ function findAndModify(
64
69
if ( objExpr . getKind ( ) !== SyntaxKind . ObjectLiteralExpression )
65
70
{
66
71
throw new Error (
67
- `Expected an object literal or reference to a local variable, got: ${ SyntaxKind [ objExpr . getKind ( ) ] } ` ,
72
+ `Expected an object literal or reference to a local variable, got: ${
73
+ SyntaxKind [ objExpr . getKind ( ) ]
74
+ } after unwrapping`,
68
75
) ;
69
76
}
70
77
@@ -79,49 +86,67 @@ function findAndModify(
79
86
let modifiedInSpread = false ;
80
87
for ( const child of objectLiteral . getChildrenOfKind ( SyntaxKind . SpreadAssignment ) )
81
88
{
82
- const spreadExpr = child . getExpression ( ) ;
89
+ const spreadExpr = unwrapExpression ( child . getExpression ( ) ) ; // Ensure spread expression itself is unwrapped
83
90
// We expect the spread expression to be an identifier referencing a known local declaration
84
91
if ( spreadExpr . getKind ( ) === SyntaxKind . Identifier )
85
92
{
86
93
const identifierName = spreadExpr . getText ( ) ;
87
94
const localValue = localDeclarations . get ( identifierName ) ;
88
95
if ( localValue )
89
96
{
90
- // Try to find and modify within the spread source object.
91
- // IMPORTANT: Pass the original 'path', not 'remainingPath', because the currentKey
92
- // is expected to be a property within the spread source object.
93
- if ( findAndModify ( localValue , path , newValue , localDeclarations ) )
97
+ try
98
+ {
99
+ logger . debug ( 'AST' , `[Spread Try] Searching for path '${ path . join ( '.' ) } ' in spread '${ identifierName } '` ) ;
100
+ // localValue will be unwrapped at the start of the recursive findAndModify call
101
+ if ( findAndModify ( localValue , path , newValue , localDeclarations ) )
102
+ {
103
+ modifiedInSpread = true ;
104
+ break ; // Found in this spread for the current path, no need to check other spreads.
105
+ }
106
+ }
107
+ catch ( error )
94
108
{
95
- modifiedInSpread = true ;
96
- break ; // Found and modified, stop searching other spreads
109
+ if ( error instanceof Error )
110
+ {
111
+ logger . debug ( 'AST' ,
112
+ `[Spread Catch] Path '${
113
+ path . join ( '.' )
114
+ } ' not found in spread '${ identifierName } ' (or other error during its processing): ${ error . message } `) ;
115
+ }
116
+ else
117
+ {
118
+ logger . debug ( 'AST' ,
119
+ `[Spread Catch] Path '${
120
+ path . join ( '.' )
121
+ } ' not found in spread '${ identifierName } ' (or other error during its processing): Unknown error type`) ;
122
+ }
123
+ // Continue to the next spread assignment
97
124
}
98
125
}
99
126
else
100
127
{
101
- // This might indicate an issue if a spread identifier isn't resolvable,
102
- // but we'll allow the search to continue in other spreads or properties.
103
- console . warn ( `Spread identifier '${ identifierName } ' not found in local declarations.` ) ;
128
+ logger . warn ( 'AST' , `Spread identifier '${ identifierName } ' not found in local declarations.` ) ;
104
129
}
105
130
}
106
131
else
107
132
{
108
- // Log if the spread expression isn't a simple identifier, as we don't handle complex spreads yet.
109
- console . warn ( `Spread assignment expression is not an identifier: ${ SyntaxKind [ spreadExpr . getKind ( ) ] } ` ) ;
133
+ logger . warn ( 'AST' ,
134
+ `Spread assignment expression is not an identifier or simple expression: ${
135
+ SyntaxKind [ spreadExpr . getKind ( ) ]
136
+ } `) ;
110
137
}
111
138
}
112
139
113
140
if ( modifiedInSpread )
114
141
{
115
- return true ; // Modification was successful within a spread assignment
142
+ return true ; // Modification was successful within a spread assignment for the current path
116
143
}
117
144
118
- // If not found in direct properties or any spread assignments, then it's truly not found.
145
+ // If not found in direct properties or any spread assignments, then it's truly not found for this object literal .
119
146
throw new Error (
120
- `Property '${ currentKey } ' not found in object literal or its spread assignments. Path: ${
121
- path . join (
122
- '.' ,
123
- )
124
- } . Object text: ${ objectLiteral . getText ( ) . substring ( 0 , 100 ) } ...`, // Added object text for context
147
+ `Property '${ currentKey } ' not found in object literal (or its spreads). Path: ${ path . join ( '.' ) } . Object text: ${
148
+ objectLiteral . getText ( ) . substring ( 0 , 200 )
149
+ } ...`,
125
150
) ;
126
151
}
127
152
@@ -242,52 +267,30 @@ export function applyDifferencesUsingASTOrThrow(
242
267
243
268
const appliedKeypaths : string [ ] = [ ] ;
244
269
270
+ const allVarsInScope = getAllVariableNamesAndValuesInFile ( sourceFile ) ;
245
271
const localDeclarations = new Map < string , Expression > ( ) ;
246
- sourceFile . getVariableDeclarations ( ) . forEach ( decl =>
272
+ for ( const { name , value } of allVarsInScope )
247
273
{
248
- const name = decl . getName ( ) ;
249
- const initializer = decl . getInitializer ( ) ;
250
- if ( initializer )
274
+ if ( value )
251
275
{
252
- localDeclarations . set ( name , unwrapExpression ( initializer ) ) ;
276
+ localDeclarations . set ( name , value ) ;
253
277
}
254
- } ) ;
255
-
256
- // Find the exported constants
257
- const exportedConsts = sourceFile . getVariableStatements ( ) . filter ( stmt => stmt . isExported ( ) ) ;
258
-
259
- const exportedNamesAndValues = getExportedVariableNamesAndValues ( sourceFile ) ;
260
-
261
- logger . info ( 'AST' , 'EXPORTED NAMES:' , exportedNamesAndValues . map ( e => e . name ) ) ;
262
-
263
- // HERE I NEED TO FIGURE OUT THE NAMES OF ALL EXPORTED VARIABLES
264
- // diff is like:
265
- // {
266
- // "foo.name.en": { left: "Mason", right: "Boatie McBoatface" },
267
- // "foo.name.ja": { left: "メイソン", right: "ボーティー マックボートフェイス" }
268
- // }
269
-
270
- // exportedNamesAndValues is like:
271
- // [{name: 'foo', value: AsExpression}]
278
+ }
272
279
273
- // 📖 OUTER LOOP: EXPORTED CONSTS
274
- //
275
- // We loop over the exported consts of the file, looking for a diff entry.
276
- //
277
- // This is not efficient, when you contemplate the diff being a huge diff generated by compating a combined JSON file for say, 500 files, with a single file (because we have the inner loops over every keyPath in the diff, below). However, we can fix that upstream of this method, because we can pare down the JSON to exclude unrelated translations. And it is actually desirable to be **able** to do the inefficient huge comparison of the "all translations vs one file", because that is useful for E2E tests of the entire system's integrity.
280
+ const exportedVarsForIteration = getExportedVariableNamesAndValues ( sourceFile ) ;
278
281
279
- for ( const exportedConst of exportedConsts )
282
+ // Iterate over each exported variable declaration found in the source file.
283
+ // For each keyPath in the diff, we check if it starts with the name of one of these exported variables.
284
+ for ( const exportedVar of exportedVarsForIteration )
280
285
{
281
- logger . debug ( 'AST' , 'exportedConst' , exportedConst . getText ( ) ) ;
282
-
283
- const declarations = exportedConst . getDeclarations ( ) ;
284
- logger . debug ( 'AST' , 'declarations' , declarations . map ( d => d . getText ( ) ) ) ;
286
+ const name = exportedVar . name ;
287
+ const declaration = sourceFile . getVariableDeclaration ( name ) ;
285
288
286
- const declaration = declarations [ 0 ] ;
287
- // logger.debug('AST', 'declaration', declaration);
288
-
289
- const name = declaration . getName ( ) ;
290
- logger . debug ( 'AST' , 'dec[0] name' , name ) ;
289
+ if ( ! declaration )
290
+ {
291
+ logger . warn ( 'AST' , `Could not find declaration for exported variable: ${ name } ` ) ;
292
+ continue ;
293
+ }
291
294
292
295
const initializer = declaration . getInitializer ( ) ;
293
296
logger . debug ( 'AST' , 'initializer' , initializer ?. getKindName ( ) ) ;
0 commit comments