gtx-cli 2.5.35 → 2.5.36

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ import * as t from '@babel/types';
5
5
  import fs from 'node:fs';
6
6
  import { parse } from '@babel/parser';
7
7
  import addGTIdentifierToSyntaxTree from './addGTIdentifierToSyntaxTree.js';
8
- import { warnHasUnwrappedExpressionSync, warnNestedTComponent, warnInvalidStaticChildSync, warnFunctionNotFoundSync, warnMissingReturnSync, warnDuplicateFunctionDefinitionSync, warnInvalidStaticInitSync, warnRecursiveFunctionCallSync, } from '../../../../console/index.js';
8
+ import { warnHasUnwrappedExpressionSync, warnNestedTComponent, warnFunctionNotFoundSync, warnMissingReturnSync, warnDuplicateFunctionDefinitionSync, warnInvalidStaticInitSync, warnRecursiveFunctionCallSync, } from '../../../../console/index.js';
9
9
  import { isAcceptedPluralForm } from 'generaltranslation/internal';
10
10
  import { isStaticExpression } from '../../evaluateJsx.js';
11
11
  import { STATIC_COMPONENT, TRANSLATION_COMPONENT, VARIABLE_COMPONENTS, } from '../constants.js';
@@ -16,7 +16,7 @@ import { buildImportMap } from '../buildImportMap.js';
16
16
  import { getPathsAndAliases } from '../getPathsAndAliases.js';
17
17
  import { parseTProps } from './parseTProps.js';
18
18
  import { handleChildrenWhitespace } from './handleChildrenWhitespace.js';
19
- import { isElementNode, } from './types.js';
19
+ import { isElementNode } from './types.js';
20
20
  import { multiplyJsxTree } from './multiplication/multiplyJsxTree.js';
21
21
  import { removeNullChildrenFields } from './removeNullChildrenFields.js';
22
22
  import path from 'node:path';
@@ -77,14 +77,31 @@ export function parseTranslationComponent({ originalName, importAliases, localNa
77
77
  * @param insideT - Whether the current node is inside a <T> component
78
78
  * @returns The built JSX tree
79
79
  */
80
- export function buildJSXTree({ importAliases, node, unwrappedExpressions, visited, callStack, updates, errors, warnings, file, insideT, parsingOptions, scopeNode, importedFunctionsMap, pkgs, }) {
80
+ export function buildJSXTree({ importAliases, node, unwrappedExpressions, inStatic, visited, callStack, updates, errors, warnings, file, insideT, parsingOptions, scopeNode, importedFunctionsMap, pkgs, helperPath, }) {
81
81
  if (t.isJSXExpressionContainer(node)) {
82
82
  // Skip JSX comments
83
83
  if (t.isJSXEmptyExpression(node.expression)) {
84
84
  return null;
85
85
  }
86
+ if (inStatic) {
87
+ return processStaticExpression({
88
+ unwrappedExpressions,
89
+ scopeNode,
90
+ expressionNodePath: helperPath.get('expression'),
91
+ importAliases,
92
+ visited: visited,
93
+ callStack,
94
+ updates,
95
+ errors,
96
+ warnings,
97
+ file,
98
+ parsingOptions,
99
+ importedFunctionsMap,
100
+ pkgs,
101
+ });
102
+ }
86
103
  const expr = node.expression;
87
- if (t.isJSXElement(expr)) {
104
+ if (t.isJSXElement(expr) || t.isJSXFragment(expr)) {
88
105
  return buildJSXTree({
89
106
  importAliases,
90
107
  node: expr,
@@ -92,14 +109,16 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
92
109
  visited,
93
110
  callStack,
94
111
  updates,
95
- errors: errors,
96
- warnings: warnings,
112
+ errors,
113
+ warnings,
97
114
  file,
98
115
  insideT,
99
116
  parsingOptions,
100
117
  scopeNode,
101
118
  importedFunctionsMap,
102
119
  pkgs,
120
+ inStatic,
121
+ helperPath: helperPath.get('expression'),
103
122
  });
104
123
  }
105
124
  const staticAnalysis = isStaticExpression(expr, true);
@@ -145,7 +164,10 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
145
164
  const props = {};
146
165
  const elementIsPlural = componentType === 'Plural';
147
166
  const elementIsBranch = componentType === 'Branch';
148
- element.openingElement.attributes.forEach((attr) => {
167
+ element.openingElement.attributes.forEach((attr, index) => {
168
+ const helperAttribute = helperPath
169
+ .get('openingElement')
170
+ .get('attributes')[index];
149
171
  if (t.isJSXAttribute(attr)) {
150
172
  const attrName = attr.name.name;
151
173
  let attrValue = null;
@@ -154,34 +176,24 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
154
176
  attrValue = attr.value.value;
155
177
  }
156
178
  else if (t.isJSXExpressionContainer(attr.value)) {
179
+ const helperValue = helperAttribute.get('value');
157
180
  // Check if this is an HTML content prop (title, placeholder, alt, etc.)
158
181
  const isHtmlContentProp = Object.values(HTML_CONTENT_PROPS).includes(attrName);
159
- if (isHtmlContentProp) {
160
- // For HTML content props, only accept static string expressions
161
- const staticAnalysis = isStaticExpression(attr.value.expression, true);
162
- if (staticAnalysis.isStatic &&
163
- staticAnalysis.value !== undefined) {
164
- attrValue = staticAnalysis.value;
182
+ // If its a plural or branch prop
183
+ if ((elementIsPlural && isAcceptedPluralForm(attrName)) ||
184
+ (elementIsBranch && attrName !== 'branch')) {
185
+ // Make sure that variable strings like {`I have ${count} book`} are invalid!
186
+ if (t.isTemplateLiteral(attr.value.expression) &&
187
+ !isStaticExpression(attr.value.expression, true).isStatic) {
188
+ unwrappedExpressions.push(generate(attr.value).code);
165
189
  }
166
- // Otherwise attrValue stays null and won't be included
167
- }
168
- else {
169
- // For non-HTML-content props, validate plural/branch then build tree
170
- if ((elementIsPlural && isAcceptedPluralForm(attrName)) ||
171
- (elementIsBranch && attrName !== 'branch')) {
172
- // Make sure that variable strings like {`I have ${count} book`} are invalid!
173
- if (t.isTemplateLiteral(attr.value.expression) &&
174
- !isStaticExpression(attr.value.expression, true).isStatic) {
175
- unwrappedExpressions.push(generate(attr.value).code);
176
- }
177
- // If it's an array, flag as an unwrapped expression
178
- if (t.isArrayExpression(attr.value.expression)) {
179
- unwrappedExpressions.push(generate(attr.value.expression).code);
180
- }
190
+ // If it's an array, flag as an unwrapped expression
191
+ if (t.isArrayExpression(attr.value.expression)) {
192
+ unwrappedExpressions.push(generate(attr.value.expression).code);
181
193
  }
182
194
  attrValue = buildJSXTree({
183
195
  importAliases,
184
- node: attr.value.expression,
196
+ node: attr.value,
185
197
  unwrappedExpressions,
186
198
  visited,
187
199
  callStack,
@@ -194,8 +206,19 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
194
206
  scopeNode,
195
207
  importedFunctionsMap,
196
208
  pkgs,
209
+ inStatic,
210
+ helperPath: helperValue,
197
211
  });
198
212
  }
213
+ // For HTML content props, only accept static string expressions
214
+ else if (isHtmlContentProp) {
215
+ const staticAnalysis = isStaticExpression(attr.value.expression, true);
216
+ if (staticAnalysis.isStatic &&
217
+ staticAnalysis.value !== undefined) {
218
+ attrValue = staticAnalysis.value;
219
+ }
220
+ // Otherwise attrValue stays null and won't be included
221
+ }
199
222
  }
200
223
  }
201
224
  props[attrName] = attrValue;
@@ -203,36 +226,43 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
203
226
  });
204
227
  if (elementIsVariable) {
205
228
  if (componentType === STATIC_COMPONENT) {
229
+ const helperElement = helperPath.get('children');
230
+ const results = {
231
+ nodeType: 'element',
232
+ type: STATIC_COMPONENT,
233
+ props,
234
+ };
235
+ // Create children array if necessary
236
+ if (element.children.length) {
237
+ results.props.children = [];
238
+ }
206
239
  if (visited === null) {
207
240
  visited = new Set();
208
241
  }
209
- return resolveStaticComponentChildren({
210
- importAliases,
211
- scopeNode,
212
- children: element.children,
213
- unwrappedExpressions,
214
- visited,
215
- updates,
216
- errors,
217
- warnings,
218
- file,
219
- callStack,
220
- parsingOptions,
221
- importedFunctionsMap,
222
- pkgs,
223
- props,
224
- });
242
+ for (let index = 0; index < element.children.length; index++) {
243
+ const helperChild = helperElement[index];
244
+ const result = buildJSXTree({
245
+ importAliases,
246
+ node: helperChild.node,
247
+ unwrappedExpressions,
248
+ visited,
249
+ callStack,
250
+ updates,
251
+ errors,
252
+ warnings,
253
+ file,
254
+ insideT: true,
255
+ parsingOptions,
256
+ scopeNode,
257
+ importedFunctionsMap,
258
+ pkgs,
259
+ inStatic: true,
260
+ helperPath: helperChild,
261
+ });
262
+ results.props.children.push(result);
263
+ }
264
+ return results;
225
265
  }
226
- // I do not see why this is being called, i am disabling this for now:
227
- // parseJSXElement({
228
- // importAliases,
229
- // node: element,
230
- // updates,
231
- // errors,
232
- // warnings,
233
- // file,
234
- // parsingOptions,
235
- // });
236
266
  return {
237
267
  nodeType: 'element',
238
268
  // if componentType is undefined, use typeName
@@ -242,7 +272,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
242
272
  };
243
273
  }
244
274
  const children = element.children
245
- .map((child) => buildJSXTree({
275
+ .map((child, index) => buildJSXTree({
246
276
  importAliases,
247
277
  node: child,
248
278
  unwrappedExpressions,
@@ -257,6 +287,8 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
257
287
  scopeNode,
258
288
  importedFunctionsMap,
259
289
  pkgs,
290
+ inStatic,
291
+ helperPath: helperPath.get('children')[index],
260
292
  }))
261
293
  .filter((child) => child !== null && child !== '');
262
294
  if (children.length === 1) {
@@ -276,7 +308,7 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
276
308
  // If it's a JSX fragment
277
309
  else if (t.isJSXFragment(node)) {
278
310
  const children = node.children
279
- .map((child) => buildJSXTree({
311
+ .map((child, index) => buildJSXTree({
280
312
  importAliases,
281
313
  node: child,
282
314
  unwrappedExpressions,
@@ -291,6 +323,8 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
291
323
  scopeNode,
292
324
  importedFunctionsMap,
293
325
  pkgs,
326
+ inStatic,
327
+ helperPath: helperPath.get('children')[index],
294
328
  }))
295
329
  .filter((child) => child !== null && child !== '');
296
330
  const props = {};
@@ -340,6 +374,59 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
340
374
  }
341
375
  return generate(node).code;
342
376
  }
377
+ else if ((t.isCallExpression(node) && t.isIdentifier(node.callee)) ||
378
+ (t.isAwaitExpression(node) &&
379
+ t.isCallExpression(node.argument) &&
380
+ t.isIdentifier(node.argument.callee))) {
381
+ if (inStatic) {
382
+ const callExpression = (node.type === 'AwaitExpression' ? node.argument : node);
383
+ const callee = callExpression.callee;
384
+ const calleeBinding = scopeNode.scope.getBinding(callee.name);
385
+ if (!calleeBinding) {
386
+ warnings.add(warnFunctionNotFoundSync(file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
387
+ return null;
388
+ }
389
+ return resolveStaticFunctionInvocationFromBinding({
390
+ importAliases,
391
+ calleeBinding,
392
+ callee,
393
+ visited: visited, // we know this is true bc of inStatic
394
+ callStack,
395
+ file,
396
+ updates,
397
+ errors,
398
+ warnings,
399
+ unwrappedExpressions,
400
+ pkgs,
401
+ parsingOptions,
402
+ importedFunctionsMap,
403
+ });
404
+ }
405
+ else {
406
+ unwrappedExpressions.push(generate(node).code);
407
+ }
408
+ }
409
+ else if (t.isParenthesizedExpression(node)) {
410
+ const child = node.expression;
411
+ return buildJSXTree({
412
+ importAliases,
413
+ node: child,
414
+ unwrappedExpressions,
415
+ visited,
416
+ callStack,
417
+ updates,
418
+ errors,
419
+ warnings,
420
+ file,
421
+ insideT,
422
+ parsingOptions,
423
+ scopeNode,
424
+ importedFunctionsMap,
425
+ pkgs,
426
+ inStatic,
427
+ helperPath: helperPath.get('expression'),
428
+ });
429
+ }
343
430
  // If it's some other JS expression
344
431
  else if (t.isIdentifier(node) ||
345
432
  t.isMemberExpression(node) ||
@@ -347,11 +434,17 @@ export function buildJSXTree({ importAliases, node, unwrappedExpressions, visite
347
434
  t.isBinaryExpression(node) ||
348
435
  t.isLogicalExpression(node) ||
349
436
  t.isConditionalExpression(node)) {
350
- return generate(node).code;
437
+ unwrappedExpressions.push(generate(node).code);
351
438
  }
352
439
  else {
353
- return generate(node).code;
440
+ if (node === undefined) {
441
+ unwrappedExpressions.push(node);
442
+ }
443
+ else {
444
+ unwrappedExpressions.push(generate(node).code);
445
+ }
354
446
  }
447
+ return null;
355
448
  }
356
449
  // end buildJSXTree
357
450
  // Parses a JSX element and adds it to the updates array
@@ -393,6 +486,8 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
393
486
  insideT: false,
394
487
  parsingOptions,
395
488
  importedFunctionsMap,
489
+ inStatic: false,
490
+ helperPath: scopeNode,
396
491
  });
397
492
  // Strip the outer <T> component if necessary
398
493
  const jsxTree = isElementNode(treeResult) && treeResult.props?.children
@@ -438,86 +533,6 @@ export function parseJSXElement({ importAliases, node, originalName, pkgs, updat
438
533
  });
439
534
  }
440
535
  }
441
- /**
442
- * Resolves an invocation inside of a <Static> component. It will resolve the function, and build
443
- * a jsx tree for each return inside of the function definition.
444
- *
445
- * function getOtherSubject() {
446
- * return <div>Jane</div>;
447
- * }
448
- *
449
- * function getSubject() {
450
- * if (condition) return getOtherSubject();
451
- * return <div>John</div>;
452
- * }
453
- * ...
454
- * <Static>
455
- * {getSubject()}
456
- * </Static>
457
- */
458
- function resolveStaticComponentChildren({ importAliases, scopeNode, children, unwrappedExpressions, visited, updates, errors, warnings, file, callStack, parsingOptions, importedFunctionsMap, pkgs, props, }) {
459
- const result = {
460
- nodeType: 'element',
461
- type: STATIC_COMPONENT,
462
- props,
463
- };
464
- let found = false;
465
- // Create children array if necessary
466
- if (children.length) {
467
- result.props.children = [];
468
- }
469
- for (const child of children) {
470
- // Ignore whitespace outside of jsx container
471
- if (t.isJSXText(child) && child.value.trim() === '') {
472
- result.props.children.push(child.value);
473
- continue;
474
- }
475
- // Must be an expression container with a function invocation
476
- if (!t.isJSXExpressionContainer(child) ||
477
- !((t.isCallExpression(child.expression) &&
478
- t.isIdentifier(child.expression.callee)) ||
479
- (t.isAwaitExpression(child.expression) &&
480
- t.isCallExpression(child.expression.argument) &&
481
- t.isIdentifier(child.expression.argument.callee))) ||
482
- found // There can only be one invocation inside of a <Static> component
483
- ) {
484
- errors.push(warnInvalidStaticChildSync(file, `${child.loc?.start?.line}:${child.loc?.start?.column}`));
485
- continue;
486
- }
487
- // Set found to true
488
- found = true;
489
- // Get callee and binding from scope
490
- const callee = (t.isAwaitExpression(child.expression)
491
- ? child.expression.argument.callee
492
- : child.expression.callee);
493
- const calleeBinding = scopeNode.scope.getBinding(callee.name);
494
- if (!calleeBinding) {
495
- warnings.add(warnFunctionNotFoundSync(file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
496
- continue;
497
- }
498
- // Function is found locally, return wrapped in an expression
499
- const staticFunctionInvocation = resolveStaticFunctionInvocationFromBinding({
500
- importAliases,
501
- calleeBinding,
502
- callee,
503
- visited,
504
- callStack,
505
- file,
506
- updates,
507
- errors,
508
- warnings,
509
- unwrappedExpressions,
510
- pkgs,
511
- parsingOptions,
512
- importedFunctionsMap,
513
- });
514
- result.props.children.push({
515
- nodeType: 'expression',
516
- result: staticFunctionInvocation,
517
- });
518
- }
519
- return result;
520
- }
521
536
  function resolveStaticFunctionInvocationFromBinding({ importAliases, calleeBinding, callee, unwrappedExpressions, visited, callStack, file, updates, errors, warnings, parsingOptions, importedFunctionsMap, pkgs, }) {
522
537
  function withRecusionGuard({ cb, filename, functionName, }) {
523
538
  const cacheKey = `${filename}::${functionName}`;
@@ -657,7 +672,7 @@ function processFunctionInFile({ filePath, functionName, visited, callStack, par
657
672
  });
658
673
  const { importAliases } = getPathsAndAliases(ast, pkgs);
659
674
  // Collect all imports in this file to track cross-file function calls
660
- let importedFunctionsMap;
675
+ let importedFunctionsMap = new Map();
661
676
  traverse(ast, {
662
677
  Program(path) {
663
678
  importedFunctionsMap = buildImportMap(path);
@@ -794,9 +809,8 @@ function processFunctionDeclarationNodePath({ functionName, path, importAliases,
794
809
  if (!returnNodePath.isExpression()) {
795
810
  return;
796
811
  }
797
- result.branches.push(processReturnExpression({
812
+ result.branches.push(processStaticExpression({
798
813
  unwrappedExpressions,
799
- functionName,
800
814
  pkgs,
801
815
  callStack,
802
816
  scopeNode: returnNodePath,
@@ -837,9 +851,8 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
837
851
  const bodyNodePath = arrowFunctionPath.get('body');
838
852
  if (bodyNodePath.isExpression()) {
839
853
  // process expression return
840
- result.branches.push(processReturnExpression({
854
+ result.branches.push(processStaticExpression({
841
855
  unwrappedExpressions,
842
- functionName,
843
856
  pkgs,
844
857
  scopeNode: arrowFunctionPath,
845
858
  expressionNodePath: bodyNodePath,
@@ -865,9 +878,8 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
865
878
  if (!returnNodePath.isExpression()) {
866
879
  return;
867
880
  }
868
- result.branches.push(processReturnExpression({
881
+ result.branches.push(processStaticExpression({
869
882
  unwrappedExpressions,
870
- functionName,
871
883
  pkgs,
872
884
  scopeNode: returnPath,
873
885
  expressionNodePath: returnNodePath,
@@ -891,15 +903,15 @@ function processVariableDeclarationNodePath({ functionName, path, importAliases,
891
903
  return result;
892
904
  }
893
905
  /**
894
- * Process a expression being returned from a function
906
+ * Process a <Static> expression
895
907
  */
896
- function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNodePath, importAliases, visited, callStack, updates, errors, warnings, file, parsingOptions, importedFunctionsMap, functionName, pkgs, }) {
908
+ function processStaticExpression({ unwrappedExpressions, scopeNode, expressionNodePath, importAliases, visited, callStack, updates, errors, warnings, file, parsingOptions, importedFunctionsMap, pkgs, }) {
897
909
  // // If the node is null, return
898
910
  // if (expressionNodePath == null) return null;
899
911
  // Remove parentheses if they exist
900
912
  if (t.isParenthesizedExpression(expressionNodePath.node)) {
901
913
  // ex: return (value)
902
- return processReturnExpression({
914
+ return processStaticExpression({
903
915
  unwrappedExpressions,
904
916
  importAliases,
905
917
  scopeNode,
@@ -911,7 +923,6 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
911
923
  warnings,
912
924
  file,
913
925
  parsingOptions,
914
- functionName,
915
926
  importedFunctionsMap,
916
927
  pkgs,
917
928
  });
@@ -925,7 +936,7 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
925
936
  warnings.add(warnFunctionNotFoundSync(file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
926
937
  return null;
927
938
  }
928
- // Function is found locally
939
+ // Function is found
929
940
  return resolveStaticFunctionInvocationFromBinding({
930
941
  importAliases,
931
942
  calleeBinding,
@@ -952,7 +963,7 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
952
963
  warnings.add(warnFunctionNotFoundSync(file, callee.name, `${callee.loc?.start?.line}:${callee.loc?.start?.column}`));
953
964
  return null;
954
965
  }
955
- // Function is found locally
966
+ // Function is found
956
967
  return resolveStaticFunctionInvocationFromBinding({
957
968
  importAliases,
958
969
  calleeBinding,
@@ -987,6 +998,8 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
987
998
  scopeNode,
988
999
  importedFunctionsMap,
989
1000
  pkgs,
1001
+ inStatic: true,
1002
+ helperPath: expressionNodePath,
990
1003
  });
991
1004
  }
992
1005
  else if (t.isConditionalExpression(expressionNodePath.node)) {
@@ -996,7 +1009,7 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
996
1009
  const alternateNodePath = expressionNodePath.get('alternate');
997
1010
  const result = {
998
1011
  nodeType: 'multiplication',
999
- branches: [consequentNodePath, alternateNodePath].map((expressionNodePath) => processReturnExpression({
1012
+ branches: [consequentNodePath, alternateNodePath].map((expressionNodePath) => processStaticExpression({
1000
1013
  unwrappedExpressions,
1001
1014
  importAliases,
1002
1015
  scopeNode,
@@ -1008,7 +1021,6 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
1008
1021
  warnings,
1009
1022
  file,
1010
1023
  parsingOptions,
1011
- functionName,
1012
1024
  importedFunctionsMap,
1013
1025
  pkgs,
1014
1026
  })),
@@ -1031,6 +1043,8 @@ function processReturnExpression({ unwrappedExpressions, scopeNode, expressionNo
1031
1043
  scopeNode,
1032
1044
  importedFunctionsMap,
1033
1045
  pkgs,
1046
+ inStatic: true,
1047
+ helperPath: expressionNodePath,
1034
1048
  });
1035
1049
  }
1036
1050
  }
@@ -0,0 +1,15 @@
1
+ import * as t from '@babel/types';
2
+ import { NodePath } from '@babel/traverse';
3
+ import { ParsingConfigOptions } from '../../../types/parsing.js';
4
+ import { StringNode } from './types.js';
5
+ export type StringTree = (string | StringTree)[];
6
+ /**
7
+ * Checks if an expression is static or uses declareStatic
8
+ * Returns a Node representing the parsed expression
9
+ * @param expr - The expression to check
10
+ * @param tPath - NodePath for scope resolution
11
+ * @param file - Current file path
12
+ * @param parsingOptions - Parsing configuration
13
+ * @returns Node | null - The parsed node, or null if invalid
14
+ */
15
+ export declare function handleStaticExpression(expr: t.Expression, tPath: NodePath, file: string, parsingOptions: ParsingConfigOptions, errors: string[]): StringNode | null;