gt 2.11.3 → 2.12.0
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.
- package/CHANGELOG.md +11 -0
- package/dist/console/index.d.ts +5 -0
- package/dist/console/index.js +5 -0
- package/dist/generated/version.d.ts +1 -1
- package/dist/generated/version.js +1 -1
- package/dist/react/jsx/utils/parseString.d.ts +1 -1
- package/dist/react/jsx/utils/parseString.js +651 -67
- package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.d.ts +2 -1
- package/dist/react/jsx/utils/stringParsing/derivation/handleDerivation.js +24 -18
- package/dist/react/jsx/utils/stringParsing/derivation/index.js +1 -0
- package/package.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,16 @@
|
|
|
1
1
|
# gtx-cli
|
|
2
2
|
|
|
3
|
+
## 2.12.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#1137](https://github.com/generaltranslation/gt/pull/1137) [`f8993aa`](https://github.com/generaltranslation/gt/commit/f8993aabe07acdfaf8a97177f038c408a8fc4c45) Thanks [@ErnestM1234](https://github.com/ErnestM1234)! - feat: object derivation
|
|
8
|
+
|
|
9
|
+
### Patch Changes
|
|
10
|
+
|
|
11
|
+
- Updated dependencies [[`f8993aa`](https://github.com/generaltranslation/gt/commit/f8993aabe07acdfaf8a97177f038c408a8fc4c45)]:
|
|
12
|
+
- @generaltranslation/python-extractor@0.2.0
|
|
13
|
+
|
|
3
14
|
## 2.11.3
|
|
4
15
|
|
|
5
16
|
### Patch Changes
|
package/dist/console/index.d.ts
CHANGED
|
@@ -21,7 +21,12 @@ export declare const warnInvalidDeriveInitSync: (file: string, functionName: str
|
|
|
21
21
|
export declare const warnDataAttrOnBranch: (file: string, attrName: string, location?: string) => string;
|
|
22
22
|
export declare const warnRecursiveFunctionCallSync: (file: string, functionName: string, location?: string) => string;
|
|
23
23
|
export declare const warnDeriveFunctionNotWrappedSync: (file: string, functionName: string, location?: string) => string;
|
|
24
|
+
export declare const warnDeriveNonConstVariableSync: (file: string, varName: string, kind: string, location?: string) => string;
|
|
24
25
|
export declare const warnDeriveFunctionNoResultsSync: (file: string, functionName: string, location?: string) => string;
|
|
26
|
+
export declare const warnDeriveUnresolvableValueSync: (file: string, key: string, location?: string) => string;
|
|
27
|
+
export declare const warnDeriveCircularSpreadSync: (file: string, varName: string, location?: string) => string;
|
|
28
|
+
export declare const warnDeriveDestructuringSync: (file: string, varName: string, location?: string) => string;
|
|
29
|
+
export declare const warnDeriveOptionalChainingSync: (file: string, code: string, location?: string) => string;
|
|
25
30
|
export declare const noLocalesError = "No locales found! Provide a list of locales for translation, or specify them in your gt.config.json file.";
|
|
26
31
|
export declare const noDefaultLocaleError = "No default locale found! Provide a default locale, or specify it in your gt.config.json file.";
|
|
27
32
|
export declare const noFilesError = "Incorrect or missing files configuration! Make sure your files are configured correctly in your gt.config.json file.";
|
package/dist/console/index.js
CHANGED
|
@@ -32,7 +32,12 @@ Invalid: ${colorizeContent(`const ${colorizeFunctionName(functionName)} = [() =>
|
|
|
32
32
|
export const warnDataAttrOnBranch = (file, attrName, location) => withLocation(file, `${colorizeComponent(`<${BRANCH_COMPONENT}>`)} component ignores attributes prefixed with ${colorizeIdString('"data-"')}. Found ${colorizeIdString(attrName)}. Remove it or use a different attribute name.`, location);
|
|
33
33
|
export const warnRecursiveFunctionCallSync = (file, functionName, location) => withLocation(file, withDeriveComponentError(`Recursive function call detected: ${colorizeFunctionName(functionName)}. A derivable (statically analyzable) function cannot use recursive calls to construct its result.`), location);
|
|
34
34
|
export const warnDeriveFunctionNotWrappedSync = (file, functionName, location) => withLocation(file, withDeriveFunctionError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. This call is not wrapped in derive() (formerly declareStatic()). Ensure the function is properly wrapped with derive() and does not have circular import dependencies.`), location);
|
|
35
|
+
export const warnDeriveNonConstVariableSync = (file, varName, kind, location) => withLocation(file, withDeriveFunctionError(`Variable ${colorizeFunctionName(varName)} is declared with '${kind}' but only 'const' declarations can be resolved statically. Change it to 'const'.`), location);
|
|
35
36
|
export const warnDeriveFunctionNoResultsSync = (file, functionName, location) => withLocation(file, withDeriveFunctionError(`Could not resolve ${colorizeFunctionName(formatCodeClamp(functionName))}. derive() (formerly declareStatic()) can only receive function invocations and cannot use undefined values or looped calls to construct its result.`), location);
|
|
37
|
+
export const warnDeriveUnresolvableValueSync = (file, key, location) => withLocation(file, withDeriveFunctionError(`Object property ${colorizeFunctionName(formatCodeClamp(key))} could not be resolved to a static string value. Only string literals, template literals, conditionals, and function calls returning strings are supported.`), location);
|
|
38
|
+
export const warnDeriveCircularSpreadSync = (file, varName, location) => withLocation(file, withDeriveFunctionError(`Circular spread detected involving ${colorizeFunctionName(varName)}. Spread references that form a cycle cannot be resolved statically.`), location);
|
|
39
|
+
export const warnDeriveDestructuringSync = (file, varName, location) => withLocation(file, withDeriveFunctionError(`Variable ${colorizeFunctionName(varName)} uses destructuring syntax, which is not yet supported in derive(). Assign the value to a const variable directly instead.`), location);
|
|
40
|
+
export const warnDeriveOptionalChainingSync = (file, code, location) => withLocation(file, withDeriveFunctionError(`Optional chaining (${colorizeFunctionName(formatCodeClamp(code))}) is not supported in derive(). Optional chaining implies the value could be undefined, which cannot be resolved statically. Use a non-optional access instead.`), location);
|
|
36
41
|
// Re-export error messages
|
|
37
42
|
export const noLocalesError = `No locales found! Provide a list of locales for translation, or specify them in your gt.config.json file.`;
|
|
38
43
|
export const noDefaultLocaleError = `No default locale found! Provide a default locale, or specify it in your gt.config.json file.`;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const PACKAGE_VERSION = "2.
|
|
1
|
+
export declare const PACKAGE_VERSION = "2.12.0";
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// This file is auto-generated. Do not edit manually.
|
|
2
|
-
export const PACKAGE_VERSION = '2.
|
|
2
|
+
export const PACKAGE_VERSION = '2.12.0';
|
|
@@ -17,7 +17,7 @@ import { StringNode } from './types.js';
|
|
|
17
17
|
* @param warnings - Set to collect warning messages
|
|
18
18
|
* @returns Node | null
|
|
19
19
|
*/
|
|
20
|
-
export declare function parseStringExpression(node: t.Node, tPath: NodePath, file: string, parsingOptions: ParsingConfigOptions, warnings
|
|
20
|
+
export declare function parseStringExpression(node: t.Node, tPath: NodePath, file: string, parsingOptions: ParsingConfigOptions, warnings: Set<string>, errors: string[]): StringNode | null;
|
|
21
21
|
/**
|
|
22
22
|
* Converts a Node tree to an array of all possible string combinations
|
|
23
23
|
* This is a helper function for compatibility with existing code
|
|
@@ -3,7 +3,7 @@ import { buildImportMap } from './buildImportMap.js';
|
|
|
3
3
|
import { resolveImportPath } from './resolveImportPath.js';
|
|
4
4
|
import { parse } from '@babel/parser';
|
|
5
5
|
import fs from 'node:fs';
|
|
6
|
-
import { warnDeriveFunctionNoResultsSync, warnFunctionNotFoundSync, warnInvalidDeclareVarNameSync, } from '../../../console/index.js';
|
|
6
|
+
import { warnDeriveFunctionNoResultsSync, warnFunctionNotFoundSync, warnInvalidDeclareVarNameSync, warnDeriveNonConstVariableSync, warnDeriveUnresolvableValueSync, warnDeriveOptionalChainingSync, warnDeriveDestructuringSync, warnDeriveCircularSpreadSync, } from '../../../console/index.js';
|
|
7
7
|
import traverseModule from '@babel/traverse';
|
|
8
8
|
import { DECLARE_VAR_FUNCTION } from '../../jsx/utils/constants.js';
|
|
9
9
|
import { GT_LIBRARIES } from '../../../types/libraries.js';
|
|
@@ -21,6 +21,419 @@ const resolveImportPathCache = new Map();
|
|
|
21
21
|
* Cache for processed functions to avoid re-parsing the same files.
|
|
22
22
|
*/
|
|
23
23
|
const processFunctionCache = new Map();
|
|
24
|
+
/**
|
|
25
|
+
* Cache for resolved object nodes to avoid re-parsing the same files.
|
|
26
|
+
*/
|
|
27
|
+
const resolveObjectNodeCache = new Map();
|
|
28
|
+
/**
|
|
29
|
+
* Guard against infinite recursion when resolving identifier chains.
|
|
30
|
+
* Tracks AST nodes currently being resolved to detect circular references.
|
|
31
|
+
*/
|
|
32
|
+
const resolvingIdentifiers = new Set();
|
|
33
|
+
/**
|
|
34
|
+
* Unwraps TypeScript type annotations to get the underlying expression.
|
|
35
|
+
* Handles: as, satisfies, non-null assertion (!), and angle-bracket assertions.
|
|
36
|
+
*/
|
|
37
|
+
function unwrapTypeAnnotation(node) {
|
|
38
|
+
if (t.isTSAsExpression(node))
|
|
39
|
+
return node.expression;
|
|
40
|
+
if (t.isTSSatisfiesExpression(node))
|
|
41
|
+
return node.expression;
|
|
42
|
+
if (t.isTSNonNullExpression(node))
|
|
43
|
+
return node.expression;
|
|
44
|
+
if (t.isTSTypeAssertion(node))
|
|
45
|
+
return node.expression;
|
|
46
|
+
return node;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Collects all resolvable property entries from an ObjectExpression,
|
|
50
|
+
* including entries from spread sources.
|
|
51
|
+
*/
|
|
52
|
+
function collectObjectProperties(objExpr, tPath, file, parsingOptions, warnings, errors = []) {
|
|
53
|
+
const entries = [];
|
|
54
|
+
for (const prop of objExpr.properties) {
|
|
55
|
+
if (t.isObjectProperty(prop)) {
|
|
56
|
+
const key = !prop.computed && t.isIdentifier(prop.key)
|
|
57
|
+
? prop.key.name
|
|
58
|
+
: t.isStringLiteral(prop.key)
|
|
59
|
+
? prop.key.value
|
|
60
|
+
: t.isNumericLiteral(prop.key)
|
|
61
|
+
? String(prop.key.value)
|
|
62
|
+
: null;
|
|
63
|
+
if (t.isExpression(prop.value)) {
|
|
64
|
+
entries.push({ key, value: prop.value });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (t.isSpreadElement(prop)) {
|
|
68
|
+
// Handle inline ObjectExpression spread: { ...({ a: 'x' }) }
|
|
69
|
+
const spreadArg = unwrapTypeAnnotation(prop.argument);
|
|
70
|
+
if (t.isObjectExpression(spreadArg)) {
|
|
71
|
+
entries.push(...collectObjectProperties(spreadArg, tPath, file, parsingOptions, warnings, errors));
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
if (!t.isIdentifier(prop.argument))
|
|
75
|
+
continue;
|
|
76
|
+
const spreadBinding = tPath.scope.getBinding(prop.argument.name);
|
|
77
|
+
if (!spreadBinding)
|
|
78
|
+
continue;
|
|
79
|
+
// Same-file: VariableDeclarator
|
|
80
|
+
if (spreadBinding.path.isVariableDeclarator()) {
|
|
81
|
+
const spreadDecl = spreadBinding.path.parentPath;
|
|
82
|
+
if (spreadDecl?.isVariableDeclaration() &&
|
|
83
|
+
spreadDecl.node.kind !== 'const')
|
|
84
|
+
continue;
|
|
85
|
+
const spreadInit = spreadBinding.path.node.init;
|
|
86
|
+
if (!spreadInit)
|
|
87
|
+
continue;
|
|
88
|
+
// Guard against circular spreads
|
|
89
|
+
if (resolvingIdentifiers.has(spreadInit)) {
|
|
90
|
+
errors.push(warnDeriveCircularSpreadSync(file, prop.argument.name, `${prop.loc?.start?.line}:${prop.loc?.start?.column}`));
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
resolvingIdentifiers.add(spreadInit);
|
|
94
|
+
const spreadObj = unwrapTypeAnnotation(spreadInit);
|
|
95
|
+
if (!t.isObjectExpression(spreadObj)) {
|
|
96
|
+
resolvingIdentifiers.delete(spreadInit);
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
entries.push(...collectObjectProperties(spreadObj, spreadBinding.path, file, parsingOptions, warnings, errors));
|
|
100
|
+
resolvingIdentifiers.delete(spreadInit);
|
|
101
|
+
}
|
|
102
|
+
// Cross-file: ImportSpecifier or ImportDefaultSpecifier
|
|
103
|
+
else if (spreadBinding.path.isImportSpecifier() ||
|
|
104
|
+
spreadBinding.path.isImportDefaultSpecifier()) {
|
|
105
|
+
const programPath = tPath.scope.getProgramParent().path;
|
|
106
|
+
const importMap = buildImportMap(programPath);
|
|
107
|
+
const importPath = importMap.get(prop.argument.name);
|
|
108
|
+
if (!importPath)
|
|
109
|
+
continue;
|
|
110
|
+
let originalName = prop.argument.name;
|
|
111
|
+
if (spreadBinding.path.isImportSpecifier()) {
|
|
112
|
+
const imported = spreadBinding.path.node.imported;
|
|
113
|
+
originalName = t.isIdentifier(imported)
|
|
114
|
+
? imported.name
|
|
115
|
+
: imported.value;
|
|
116
|
+
}
|
|
117
|
+
const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
|
|
118
|
+
if (!resolvedFilePath)
|
|
119
|
+
continue;
|
|
120
|
+
const crossFileObjects = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions, warnings);
|
|
121
|
+
for (const crossObj of crossFileObjects) {
|
|
122
|
+
const crossEntries = t.isArrayExpression(crossObj.objExpr)
|
|
123
|
+
? collectArrayElements(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions, warnings)
|
|
124
|
+
: collectObjectProperties(crossObj.objExpr, crossObj.tPath, crossObj.file, parsingOptions, warnings, errors);
|
|
125
|
+
entries.push(...crossEntries);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// Skip ObjectMethod (getters, setters, methods)
|
|
130
|
+
}
|
|
131
|
+
return entries;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Collects elements from an ArrayExpression as ObjectEntry[] with index as key.
|
|
135
|
+
* Handles spread elements by resolving the source array.
|
|
136
|
+
*/
|
|
137
|
+
function collectArrayElements(arrExpr, tPath, file, parsingOptions, warnings, errors = []) {
|
|
138
|
+
const entries = [];
|
|
139
|
+
let index = 0;
|
|
140
|
+
for (const el of arrExpr.elements) {
|
|
141
|
+
if (!el) {
|
|
142
|
+
index++;
|
|
143
|
+
continue;
|
|
144
|
+
} // sparse hole
|
|
145
|
+
if (t.isSpreadElement(el)) {
|
|
146
|
+
if (!t.isIdentifier(el.argument)) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
const spreadBinding = tPath.scope.getBinding(el.argument.name);
|
|
150
|
+
if (!spreadBinding)
|
|
151
|
+
continue;
|
|
152
|
+
// Same-file spread
|
|
153
|
+
if (spreadBinding.path.isVariableDeclarator()) {
|
|
154
|
+
const spreadDecl = spreadBinding.path.parentPath;
|
|
155
|
+
if (spreadDecl?.isVariableDeclaration() &&
|
|
156
|
+
spreadDecl.node.kind !== 'const') {
|
|
157
|
+
errors.push(warnDeriveNonConstVariableSync(file, el.argument.name, spreadDecl.node.kind, `${el.loc?.start?.line}:${el.loc?.start?.column}`));
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
const spreadInit = spreadBinding.path.node.init;
|
|
161
|
+
if (!spreadInit)
|
|
162
|
+
continue;
|
|
163
|
+
const spreadUnwrapped = unwrapTypeAnnotation(spreadInit);
|
|
164
|
+
if (t.isArrayExpression(spreadUnwrapped)) {
|
|
165
|
+
const spreadEntries = collectArrayElements(spreadUnwrapped, spreadBinding.path, file, parsingOptions, warnings);
|
|
166
|
+
for (const e of spreadEntries) {
|
|
167
|
+
entries.push({ key: String(index++), value: e.value });
|
|
168
|
+
}
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
// Cross-file spread
|
|
173
|
+
else if (spreadBinding.path.isImportSpecifier() ||
|
|
174
|
+
spreadBinding.path.isImportDefaultSpecifier()) {
|
|
175
|
+
const programPath = tPath.scope.getProgramParent().path;
|
|
176
|
+
const importMap = buildImportMap(programPath);
|
|
177
|
+
const importPath = importMap.get(el.argument.name);
|
|
178
|
+
if (!importPath)
|
|
179
|
+
continue;
|
|
180
|
+
let originalName = el.argument.name;
|
|
181
|
+
if (spreadBinding.path.isImportSpecifier()) {
|
|
182
|
+
const imported = spreadBinding.path.node.imported;
|
|
183
|
+
originalName = t.isIdentifier(imported)
|
|
184
|
+
? imported.name
|
|
185
|
+
: imported.value;
|
|
186
|
+
}
|
|
187
|
+
const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
|
|
188
|
+
if (!resolvedFilePath)
|
|
189
|
+
continue;
|
|
190
|
+
const crossFileNodes = resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions, warnings);
|
|
191
|
+
for (const crossNode of crossFileNodes) {
|
|
192
|
+
if (t.isArrayExpression(crossNode.objExpr)) {
|
|
193
|
+
const spreadEntries = collectArrayElements(crossNode.objExpr, crossNode.tPath, crossNode.file, parsingOptions, warnings);
|
|
194
|
+
for (const e of spreadEntries) {
|
|
195
|
+
entries.push({ key: String(index++), value: e.value });
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
continue;
|
|
201
|
+
}
|
|
202
|
+
if (t.isExpression(el)) {
|
|
203
|
+
entries.push({ key: String(index), value: unwrapTypeAnnotation(el) });
|
|
204
|
+
}
|
|
205
|
+
index++;
|
|
206
|
+
}
|
|
207
|
+
return entries;
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Resolves an expression to ObjectExpression or ArrayExpression AST node(s).
|
|
211
|
+
* Handles Identifier (local + imported) and MemberExpression (nested access chains).
|
|
212
|
+
*/
|
|
213
|
+
function resolveToObjectNodes(node, tPath, file, parsingOptions, warnings, errors = []) {
|
|
214
|
+
// Case 1: Identifier — base case
|
|
215
|
+
if (t.isIdentifier(node)) {
|
|
216
|
+
const binding = tPath.scope.getBinding(node.name);
|
|
217
|
+
if (!binding)
|
|
218
|
+
return [];
|
|
219
|
+
// Local variable
|
|
220
|
+
if (binding.path.isVariableDeclarator()) {
|
|
221
|
+
const declaration = binding.path.parentPath;
|
|
222
|
+
if (declaration?.isVariableDeclaration() &&
|
|
223
|
+
declaration.node.kind !== 'const') {
|
|
224
|
+
warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
225
|
+
return [];
|
|
226
|
+
}
|
|
227
|
+
const init = binding.path.node.init;
|
|
228
|
+
if (!init)
|
|
229
|
+
return [];
|
|
230
|
+
const unwrapped = unwrapTypeAnnotation(init);
|
|
231
|
+
if (t.isObjectExpression(unwrapped) || t.isArrayExpression(unwrapped)) {
|
|
232
|
+
return [{ objExpr: unwrapped, tPath: binding.path, file }];
|
|
233
|
+
}
|
|
234
|
+
// Handle identifier chain: const A = B; const B = { ... }
|
|
235
|
+
if (t.isIdentifier(unwrapped)) {
|
|
236
|
+
return resolveToObjectNodes(unwrapped, binding.path, file, parsingOptions, warnings, errors);
|
|
237
|
+
}
|
|
238
|
+
// Handle conditional: cond ? { ... } : { ... } (including nested ternaries)
|
|
239
|
+
if (t.isConditionalExpression(unwrapped)) {
|
|
240
|
+
const collectConditionalLeaves = (expr) => {
|
|
241
|
+
const inner = unwrapTypeAnnotation(expr);
|
|
242
|
+
if (t.isConditionalExpression(inner)) {
|
|
243
|
+
return [
|
|
244
|
+
...collectConditionalLeaves(inner.consequent),
|
|
245
|
+
...collectConditionalLeaves(inner.alternate),
|
|
246
|
+
];
|
|
247
|
+
}
|
|
248
|
+
if (t.isObjectExpression(inner) || t.isArrayExpression(inner)) {
|
|
249
|
+
return [{ objExpr: inner, tPath: binding.path, file }];
|
|
250
|
+
}
|
|
251
|
+
return [];
|
|
252
|
+
};
|
|
253
|
+
return [
|
|
254
|
+
...collectConditionalLeaves(unwrapped.consequent),
|
|
255
|
+
...collectConditionalLeaves(unwrapped.alternate),
|
|
256
|
+
];
|
|
257
|
+
}
|
|
258
|
+
return [];
|
|
259
|
+
}
|
|
260
|
+
// Imported
|
|
261
|
+
if (binding.path.isImportSpecifier() ||
|
|
262
|
+
binding.path.isImportDefaultSpecifier()) {
|
|
263
|
+
const programPath = tPath.scope.getProgramParent().path;
|
|
264
|
+
const importMap = buildImportMap(programPath);
|
|
265
|
+
const importPath = importMap.get(node.name);
|
|
266
|
+
if (!importPath)
|
|
267
|
+
return [];
|
|
268
|
+
let originalName = node.name;
|
|
269
|
+
if (binding.path.isImportSpecifier()) {
|
|
270
|
+
const imported = binding.path.node.imported;
|
|
271
|
+
originalName = t.isIdentifier(imported)
|
|
272
|
+
? imported.name
|
|
273
|
+
: imported.value;
|
|
274
|
+
}
|
|
275
|
+
const resolvedFilePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
|
|
276
|
+
if (!resolvedFilePath)
|
|
277
|
+
return [];
|
|
278
|
+
return resolveObjectNodesInFile(resolvedFilePath, originalName, parsingOptions, warnings);
|
|
279
|
+
}
|
|
280
|
+
return [];
|
|
281
|
+
}
|
|
282
|
+
// Case 2: MemberExpression — recursive
|
|
283
|
+
if (t.isMemberExpression(node)) {
|
|
284
|
+
if (!t.isExpression(node.object))
|
|
285
|
+
return [];
|
|
286
|
+
const parentObjects = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
|
|
287
|
+
if (parentObjects.length === 0)
|
|
288
|
+
return [];
|
|
289
|
+
const results = [];
|
|
290
|
+
for (const parent of parentObjects) {
|
|
291
|
+
const entries = t.isArrayExpression(parent.objExpr)
|
|
292
|
+
? collectArrayElements(parent.objExpr, parent.tPath, parent.file, parsingOptions, warnings)
|
|
293
|
+
: collectObjectProperties(parent.objExpr, parent.tPath, parent.file, parsingOptions, warnings, errors);
|
|
294
|
+
// Determine if this is a static access (known key)
|
|
295
|
+
let staticKey = null;
|
|
296
|
+
if (!node.computed && t.isIdentifier(node.property)) {
|
|
297
|
+
staticKey = node.property.name;
|
|
298
|
+
}
|
|
299
|
+
else if (node.computed && t.isStringLiteral(node.property)) {
|
|
300
|
+
staticKey = node.property.value;
|
|
301
|
+
}
|
|
302
|
+
else if (node.computed && t.isNumericLiteral(node.property)) {
|
|
303
|
+
staticKey = String(node.property.value);
|
|
304
|
+
}
|
|
305
|
+
if (staticKey !== null) {
|
|
306
|
+
// Static: narrow to matching key(s) — don't break, spreads may duplicate keys
|
|
307
|
+
for (const entry of entries) {
|
|
308
|
+
if (entry.key === staticKey) {
|
|
309
|
+
const unwrapped = unwrapTypeAnnotation(entry.value);
|
|
310
|
+
if (t.isObjectExpression(unwrapped) ||
|
|
311
|
+
t.isArrayExpression(unwrapped)) {
|
|
312
|
+
results.push({
|
|
313
|
+
objExpr: unwrapped,
|
|
314
|
+
tPath: parent.tPath,
|
|
315
|
+
file: parent.file,
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
else {
|
|
322
|
+
// Dynamic: collect ALL entries whose values are ObjectExpressions or ArrayExpressions
|
|
323
|
+
for (const entry of entries) {
|
|
324
|
+
const unwrapped = unwrapTypeAnnotation(entry.value);
|
|
325
|
+
if (t.isObjectExpression(unwrapped) ||
|
|
326
|
+
t.isArrayExpression(unwrapped)) {
|
|
327
|
+
results.push({
|
|
328
|
+
objExpr: unwrapped,
|
|
329
|
+
tPath: parent.tPath,
|
|
330
|
+
file: parent.file,
|
|
331
|
+
});
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
return results;
|
|
337
|
+
}
|
|
338
|
+
return [];
|
|
339
|
+
}
|
|
340
|
+
/**
|
|
341
|
+
* Resolves an object declaration from an external file.
|
|
342
|
+
* Finds a const VariableDeclarator with ObjectExpression init.
|
|
343
|
+
* Follows re-export chains.
|
|
344
|
+
*/
|
|
345
|
+
function resolveObjectNodesInFile(filePath, name, parsingOptions, warnings) {
|
|
346
|
+
const cacheKey = `${filePath}::${name}`;
|
|
347
|
+
if (resolveObjectNodeCache.has(cacheKey)) {
|
|
348
|
+
return resolveObjectNodeCache.get(cacheKey);
|
|
349
|
+
}
|
|
350
|
+
try {
|
|
351
|
+
const code = fs.readFileSync(filePath, 'utf8');
|
|
352
|
+
const ast = parse(code, {
|
|
353
|
+
sourceType: 'module',
|
|
354
|
+
plugins: ['jsx', 'typescript'],
|
|
355
|
+
});
|
|
356
|
+
const results = [];
|
|
357
|
+
traverse(ast, {
|
|
358
|
+
VariableDeclarator(path) {
|
|
359
|
+
if (t.isIdentifier(path.node.id) &&
|
|
360
|
+
path.node.id.name === name &&
|
|
361
|
+
results.length === 0) {
|
|
362
|
+
const init = path.node.init;
|
|
363
|
+
if (!init)
|
|
364
|
+
return;
|
|
365
|
+
const declaration = path.parentPath;
|
|
366
|
+
if (declaration?.isVariableDeclaration() &&
|
|
367
|
+
declaration.node.kind !== 'const')
|
|
368
|
+
return;
|
|
369
|
+
const unwrapped = unwrapTypeAnnotation(init);
|
|
370
|
+
if (t.isObjectExpression(unwrapped) ||
|
|
371
|
+
t.isArrayExpression(unwrapped)) {
|
|
372
|
+
results.push({
|
|
373
|
+
objExpr: unwrapped,
|
|
374
|
+
tPath: path,
|
|
375
|
+
file: filePath,
|
|
376
|
+
});
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
},
|
|
380
|
+
ExportAllDeclaration(path) {
|
|
381
|
+
if (results.length > 0)
|
|
382
|
+
return;
|
|
383
|
+
if (t.isStringLiteral(path.node.source)) {
|
|
384
|
+
const reexportPath = path.node.source.value;
|
|
385
|
+
const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
|
|
386
|
+
if (resolvedPath) {
|
|
387
|
+
results.push(...resolveObjectNodesInFile(resolvedPath, name, parsingOptions, warnings));
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
ExportNamedDeclaration(path) {
|
|
392
|
+
if (results.length > 0)
|
|
393
|
+
return;
|
|
394
|
+
if (path.node.source && t.isStringLiteral(path.node.source)) {
|
|
395
|
+
const hasMatch = path.node.specifiers.some((spec) => {
|
|
396
|
+
if (t.isExportSpecifier(spec)) {
|
|
397
|
+
const exportedName = t.isIdentifier(spec.exported)
|
|
398
|
+
? spec.exported.name
|
|
399
|
+
: spec.exported.value;
|
|
400
|
+
return exportedName === name;
|
|
401
|
+
}
|
|
402
|
+
return false;
|
|
403
|
+
});
|
|
404
|
+
if (hasMatch) {
|
|
405
|
+
const reexportPath = path.node.source.value;
|
|
406
|
+
const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
|
|
407
|
+
if (resolvedPath) {
|
|
408
|
+
const specifier = path.node.specifiers.find((spec) => {
|
|
409
|
+
if (t.isExportSpecifier(spec)) {
|
|
410
|
+
const exportedName = t.isIdentifier(spec.exported)
|
|
411
|
+
? spec.exported.name
|
|
412
|
+
: spec.exported.value;
|
|
413
|
+
return exportedName === name;
|
|
414
|
+
}
|
|
415
|
+
return false;
|
|
416
|
+
});
|
|
417
|
+
let originalName = name;
|
|
418
|
+
if (specifier &&
|
|
419
|
+
t.isExportSpecifier(specifier) &&
|
|
420
|
+
t.isIdentifier(specifier.local)) {
|
|
421
|
+
originalName = specifier.local.name;
|
|
422
|
+
}
|
|
423
|
+
results.push(...resolveObjectNodesInFile(resolvedPath, originalName, parsingOptions, warnings));
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
});
|
|
429
|
+
resolveObjectNodeCache.set(cacheKey, results);
|
|
430
|
+
return results;
|
|
431
|
+
}
|
|
432
|
+
catch {
|
|
433
|
+
resolveObjectNodeCache.set(cacheKey, []);
|
|
434
|
+
return [];
|
|
435
|
+
}
|
|
436
|
+
}
|
|
24
437
|
/**
|
|
25
438
|
* Processes a string expression node and resolves any function calls within it
|
|
26
439
|
* This handles cases like:
|
|
@@ -36,7 +449,14 @@ const processFunctionCache = new Map();
|
|
|
36
449
|
* @param warnings - Set to collect warning messages
|
|
37
450
|
* @returns Node | null
|
|
38
451
|
*/
|
|
39
|
-
export function parseStringExpression(node, tPath, file, parsingOptions, warnings
|
|
452
|
+
export function parseStringExpression(node, tPath, file, parsingOptions, warnings, errors) {
|
|
453
|
+
// Unwrap TypeScript type annotations (as, satisfies, !, <Type>)
|
|
454
|
+
if (t.isTSAsExpression(node) ||
|
|
455
|
+
t.isTSSatisfiesExpression(node) ||
|
|
456
|
+
t.isTSNonNullExpression(node) ||
|
|
457
|
+
t.isTSTypeAssertion(node)) {
|
|
458
|
+
return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
|
|
459
|
+
}
|
|
40
460
|
// Handle string literals
|
|
41
461
|
if (t.isStringLiteral(node)) {
|
|
42
462
|
return { type: 'text', text: node.value };
|
|
@@ -64,7 +484,7 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
64
484
|
}
|
|
65
485
|
const exprNode = node.expressions[index];
|
|
66
486
|
if (exprNode && t.isExpression(exprNode)) {
|
|
67
|
-
const result = parseStringExpression(exprNode, tPath, file, parsingOptions, warnings);
|
|
487
|
+
const result = parseStringExpression(exprNode, tPath, file, parsingOptions, warnings, errors);
|
|
68
488
|
if (result === null) {
|
|
69
489
|
return null;
|
|
70
490
|
}
|
|
@@ -84,8 +504,8 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
84
504
|
if (!t.isExpression(node.left) || !t.isExpression(node.right)) {
|
|
85
505
|
return null;
|
|
86
506
|
}
|
|
87
|
-
const leftResult = parseStringExpression(node.left, tPath, file, parsingOptions, warnings);
|
|
88
|
-
const rightResult = parseStringExpression(node.right, tPath, file, parsingOptions, warnings);
|
|
507
|
+
const leftResult = parseStringExpression(node.left, tPath, file, parsingOptions, warnings, errors);
|
|
508
|
+
const rightResult = parseStringExpression(node.right, tPath, file, parsingOptions, warnings, errors);
|
|
89
509
|
if (leftResult === null || rightResult === null) {
|
|
90
510
|
return null;
|
|
91
511
|
}
|
|
@@ -96,8 +516,8 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
96
516
|
if (!t.isExpression(node.consequent) || !t.isExpression(node.alternate)) {
|
|
97
517
|
return null;
|
|
98
518
|
}
|
|
99
|
-
const consequentResult = parseStringExpression(node.consequent, tPath, file, parsingOptions, warnings);
|
|
100
|
-
const alternateResult = parseStringExpression(node.alternate, tPath, file, parsingOptions, warnings);
|
|
519
|
+
const consequentResult = parseStringExpression(node.consequent, tPath, file, parsingOptions, warnings, errors);
|
|
520
|
+
const alternateResult = parseStringExpression(node.alternate, tPath, file, parsingOptions, warnings, errors);
|
|
101
521
|
if (consequentResult === null || alternateResult === null) {
|
|
102
522
|
return null;
|
|
103
523
|
}
|
|
@@ -116,15 +536,116 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
116
536
|
}
|
|
117
537
|
// Check if it's a const/let/var with an initializer
|
|
118
538
|
if (binding.path.isVariableDeclarator() && binding.path.node.init) {
|
|
539
|
+
// Check for destructuring patterns (not yet supported)
|
|
540
|
+
if (t.isObjectPattern(binding.path.node.id) ||
|
|
541
|
+
t.isArrayPattern(binding.path.node.id)) {
|
|
542
|
+
errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
543
|
+
return null;
|
|
544
|
+
}
|
|
545
|
+
// Guard against circular references (e.g., const A = B; const B = A)
|
|
119
546
|
const init = binding.path.node.init;
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
547
|
+
if (resolvingIdentifiers.has(init)) {
|
|
548
|
+
return null;
|
|
549
|
+
}
|
|
550
|
+
// Enforce const-only
|
|
551
|
+
const declaration = binding.path.parentPath;
|
|
552
|
+
if (declaration?.isVariableDeclaration() &&
|
|
553
|
+
declaration.node.kind !== 'const') {
|
|
554
|
+
warnings.add(warnDeriveNonConstVariableSync(file, node.name, declaration.node.kind, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
555
|
+
return null;
|
|
123
556
|
}
|
|
557
|
+
// Unwrap TSAsExpression (for `as const`)
|
|
558
|
+
const unwrapped = unwrapTypeAnnotation(init);
|
|
559
|
+
if (t.isExpression(unwrapped)) {
|
|
560
|
+
// Recursively resolve the initializer with recursion guard
|
|
561
|
+
resolvingIdentifiers.add(init);
|
|
562
|
+
try {
|
|
563
|
+
return parseStringExpression(unwrapped, binding.path, file, parsingOptions, warnings, errors);
|
|
564
|
+
}
|
|
565
|
+
finally {
|
|
566
|
+
resolvingIdentifiers.delete(init);
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
// Check for destructuring patterns (not yet supported)
|
|
571
|
+
if (binding.path.isObjectProperty() ||
|
|
572
|
+
binding.path.isArrayPattern() ||
|
|
573
|
+
binding.path.isRestElement()) {
|
|
574
|
+
errors.push(warnDeriveDestructuringSync(file, node.name, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
575
|
+
return null;
|
|
124
576
|
}
|
|
125
577
|
// Not a resolvable variable
|
|
126
578
|
return null;
|
|
127
579
|
}
|
|
580
|
+
// Handle optional chaining — not supported, emit error
|
|
581
|
+
if (t.isOptionalMemberExpression(node)) {
|
|
582
|
+
errors.push(warnDeriveOptionalChainingSync(file, generate(node).code, `${node.loc?.start?.line}:${node.loc?.start?.column}`));
|
|
583
|
+
return null;
|
|
584
|
+
}
|
|
585
|
+
// Handle member expressions: obj[key], obj.prop, and nested obj.a.b / obj[a][b]
|
|
586
|
+
if (t.isMemberExpression(node)) {
|
|
587
|
+
if (!t.isExpression(node.object))
|
|
588
|
+
return null;
|
|
589
|
+
// Resolve the object part to ObjectExpression node(s)
|
|
590
|
+
const objectNodes = resolveToObjectNodes(node.object, tPath, file, parsingOptions, warnings, errors);
|
|
591
|
+
if (objectNodes.length === 0)
|
|
592
|
+
return null;
|
|
593
|
+
// Apply the final access to each resolved object
|
|
594
|
+
const branches = [];
|
|
595
|
+
for (const { objExpr, tPath: objPath, file: objFile } of objectNodes) {
|
|
596
|
+
const entries = t.isArrayExpression(objExpr)
|
|
597
|
+
? collectArrayElements(objExpr, objPath, objFile, parsingOptions, warnings, errors)
|
|
598
|
+
: collectObjectProperties(objExpr, objPath, objFile, parsingOptions, warnings, errors);
|
|
599
|
+
// Check for static literal subscripts: obj['key'] or obj[0]
|
|
600
|
+
let staticLiteralKey = null;
|
|
601
|
+
if (node.computed && t.isStringLiteral(node.property)) {
|
|
602
|
+
staticLiteralKey = node.property.value;
|
|
603
|
+
}
|
|
604
|
+
else if (node.computed && t.isNumericLiteral(node.property)) {
|
|
605
|
+
staticLiteralKey = String(node.property.value);
|
|
606
|
+
}
|
|
607
|
+
// Determine the access key (if statically known)
|
|
608
|
+
const propName = staticLiteralKey ??
|
|
609
|
+
(!node.computed && t.isIdentifier(node.property)
|
|
610
|
+
? node.property.name
|
|
611
|
+
: null);
|
|
612
|
+
// Check if we can narrow: need a known access key AND all object keys must be resolvable
|
|
613
|
+
const hasUnresolvableKeys = entries.some((e) => e.key === null);
|
|
614
|
+
const canNarrow = propName !== null && !hasUnresolvableKeys;
|
|
615
|
+
if (canNarrow) {
|
|
616
|
+
// STATIC: extract ONE specific property
|
|
617
|
+
for (const entry of entries) {
|
|
618
|
+
if (entry.key === propName) {
|
|
619
|
+
const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
|
|
620
|
+
if (resolved) {
|
|
621
|
+
branches.push(resolved);
|
|
622
|
+
}
|
|
623
|
+
else {
|
|
624
|
+
errors.push(warnDeriveUnresolvableValueSync(objFile, propName, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
|
|
625
|
+
}
|
|
626
|
+
// Don't break — spreads may introduce duplicate keys
|
|
627
|
+
}
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
else {
|
|
631
|
+
// DYNAMIC: extract ALL values (can't determine which key matches)
|
|
632
|
+
for (const entry of entries) {
|
|
633
|
+
const resolved = parseStringExpression(entry.value, objPath, objFile, parsingOptions, warnings, errors);
|
|
634
|
+
if (resolved) {
|
|
635
|
+
branches.push(resolved);
|
|
636
|
+
}
|
|
637
|
+
else if (entry.key !== null) {
|
|
638
|
+
errors.push(warnDeriveUnresolvableValueSync(objFile, entry.key, `${entry.value.loc?.start?.line}:${entry.value.loc?.start?.column}`));
|
|
639
|
+
}
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
if (branches.length === 0)
|
|
644
|
+
return null;
|
|
645
|
+
if (branches.length === 1)
|
|
646
|
+
return branches[0];
|
|
647
|
+
return { type: 'choice', nodes: branches };
|
|
648
|
+
}
|
|
128
649
|
// Handle function calls (e.g., getName())
|
|
129
650
|
if (t.isCallExpression(node) && t.isIdentifier(node.callee)) {
|
|
130
651
|
const functionName = node.callee.name;
|
|
@@ -184,16 +705,16 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
184
705
|
}
|
|
185
706
|
const filePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
|
|
186
707
|
if (filePath && originalName) {
|
|
187
|
-
return resolveFunctionInFile(filePath, originalName, parsingOptions, warnings);
|
|
708
|
+
return resolveFunctionInFile(filePath, originalName, parsingOptions, warnings, errors);
|
|
188
709
|
}
|
|
189
710
|
return null;
|
|
190
711
|
}
|
|
191
712
|
// Resolve the function locally and get its return values
|
|
192
|
-
return resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings);
|
|
713
|
+
return resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings, errors);
|
|
193
714
|
}
|
|
194
715
|
// Handle parenthesized expressions
|
|
195
716
|
if (t.isParenthesizedExpression(node)) {
|
|
196
|
-
return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings);
|
|
717
|
+
return parseStringExpression(node.expression, tPath, file, parsingOptions, warnings, errors);
|
|
197
718
|
}
|
|
198
719
|
// Handle unary expressions (e.g., -123)
|
|
199
720
|
if (t.isUnaryExpression(node)) {
|
|
@@ -220,7 +741,7 @@ export function parseStringExpression(node, tPath, file, parsingOptions, warning
|
|
|
220
741
|
/**
|
|
221
742
|
* Resolves a function call by traversing its body and collecting return values
|
|
222
743
|
*/
|
|
223
|
-
function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings) {
|
|
744
|
+
function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warnings, errors) {
|
|
224
745
|
if (!calleeBinding) {
|
|
225
746
|
return null;
|
|
226
747
|
}
|
|
@@ -242,7 +763,7 @@ function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warning
|
|
|
242
763
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
243
764
|
return;
|
|
244
765
|
}
|
|
245
|
-
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings);
|
|
766
|
+
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
|
|
246
767
|
if (returnResult !== null) {
|
|
247
768
|
branches.push(returnResult);
|
|
248
769
|
}
|
|
@@ -258,7 +779,7 @@ function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warning
|
|
|
258
779
|
const body = init.get('body');
|
|
259
780
|
// Handle expression body: () => "day"
|
|
260
781
|
if (body.isExpression()) {
|
|
261
|
-
const bodyResult = parseStringExpression(body.node, body, file, parsingOptions, warnings);
|
|
782
|
+
const bodyResult = parseStringExpression(body.node, body, file, parsingOptions, warnings, errors);
|
|
262
783
|
if (bodyResult !== null) {
|
|
263
784
|
branches.push(bodyResult);
|
|
264
785
|
}
|
|
@@ -280,7 +801,7 @@ function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warning
|
|
|
280
801
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
281
802
|
return;
|
|
282
803
|
}
|
|
283
|
-
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings);
|
|
804
|
+
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
|
|
284
805
|
if (returnResult !== null) {
|
|
285
806
|
branches.push(returnResult);
|
|
286
807
|
}
|
|
@@ -299,7 +820,7 @@ function resolveFunctionCall(calleeBinding, tPath, file, parsingOptions, warning
|
|
|
299
820
|
/**
|
|
300
821
|
* Resolves a function definition in an external file
|
|
301
822
|
*/
|
|
302
|
-
function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings) {
|
|
823
|
+
function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings, errors) {
|
|
303
824
|
// Check cache first
|
|
304
825
|
const cacheKey = `${filePath}::${functionName}`;
|
|
305
826
|
if (processFunctionCache.has(cacheKey)) {
|
|
@@ -323,7 +844,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings)
|
|
|
323
844
|
const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
|
|
324
845
|
if (resolvedPath) {
|
|
325
846
|
// Recursively resolve in the re-exported file
|
|
326
|
-
const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, warnings);
|
|
847
|
+
const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, warnings, errors);
|
|
327
848
|
if (reexportResult) {
|
|
328
849
|
result = reexportResult;
|
|
329
850
|
}
|
|
@@ -368,7 +889,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings)
|
|
|
368
889
|
originalName = specifier.local.name;
|
|
369
890
|
}
|
|
370
891
|
// Recursively resolve in the re-exported file
|
|
371
|
-
const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, warnings);
|
|
892
|
+
const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, warnings, errors);
|
|
372
893
|
if (reexportResult) {
|
|
373
894
|
result = reexportResult;
|
|
374
895
|
}
|
|
@@ -393,7 +914,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings)
|
|
|
393
914
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
394
915
|
return;
|
|
395
916
|
}
|
|
396
|
-
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings);
|
|
917
|
+
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
|
|
397
918
|
if (returnResult !== null) {
|
|
398
919
|
branches.push(returnResult);
|
|
399
920
|
}
|
|
@@ -411,58 +932,121 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, warnings)
|
|
|
411
932
|
VariableDeclarator(path) {
|
|
412
933
|
if (t.isIdentifier(path.node.id) &&
|
|
413
934
|
path.node.id.name === functionName &&
|
|
414
|
-
path.node.init &&
|
|
415
|
-
(t.isArrowFunctionExpression(path.node.init) ||
|
|
416
|
-
t.isFunctionExpression(path.node.init)) &&
|
|
417
935
|
result === null) {
|
|
418
|
-
const init = path.
|
|
419
|
-
if (!init
|
|
420
|
-
!init.isFunctionExpression()) {
|
|
936
|
+
const init = path.node.init;
|
|
937
|
+
if (!init)
|
|
421
938
|
return;
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
939
|
+
// Handle arrow/function expressions
|
|
940
|
+
if (t.isArrowFunctionExpression(init) ||
|
|
941
|
+
t.isFunctionExpression(init)) {
|
|
942
|
+
const initPath = path.get('init');
|
|
943
|
+
if (!initPath.isArrowFunctionExpression() &&
|
|
944
|
+
!initPath.isFunctionExpression()) {
|
|
945
|
+
return;
|
|
946
|
+
}
|
|
947
|
+
const bodyPath = initPath.get('body');
|
|
948
|
+
const branches = [];
|
|
949
|
+
// Handle expression body: () => "day"
|
|
950
|
+
if (!Array.isArray(bodyPath) && t.isExpression(bodyPath.node)) {
|
|
951
|
+
const bodyResult = parseStringExpression(bodyPath.node, bodyPath, filePath, parsingOptions, warnings, errors);
|
|
952
|
+
if (bodyResult !== null) {
|
|
953
|
+
branches.push(bodyResult);
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
// Handle block body: () => { return "day"; }
|
|
957
|
+
else if (!Array.isArray(bodyPath) &&
|
|
958
|
+
t.isBlockStatement(bodyPath.node)) {
|
|
959
|
+
const arrowFunction = initPath.node;
|
|
960
|
+
bodyPath.traverse({
|
|
961
|
+
Function(innerPath) {
|
|
962
|
+
// Skip nested functions
|
|
963
|
+
innerPath.skip();
|
|
964
|
+
},
|
|
965
|
+
ReturnStatement(returnPath) {
|
|
966
|
+
// Only process return statements that are direct children of this function
|
|
967
|
+
const parentFunction = returnPath.getFunctionParent();
|
|
968
|
+
if (parentFunction?.node !== arrowFunction) {
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
if (!t.isReturnStatement(returnPath.node)) {
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
const returnArg = returnPath.node.argument;
|
|
975
|
+
if (!returnArg || !t.isExpression(returnArg)) {
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
|
|
979
|
+
if (returnResult !== null) {
|
|
980
|
+
branches.push(returnResult);
|
|
981
|
+
}
|
|
982
|
+
},
|
|
983
|
+
});
|
|
984
|
+
}
|
|
985
|
+
if (branches.length === 1) {
|
|
986
|
+
result = branches[0];
|
|
987
|
+
}
|
|
988
|
+
else if (branches.length > 1) {
|
|
989
|
+
result = { type: 'choice', nodes: branches };
|
|
430
990
|
}
|
|
431
991
|
}
|
|
432
|
-
// Handle
|
|
433
|
-
else if (
|
|
434
|
-
|
|
435
|
-
const arrowFunction = init.node;
|
|
436
|
-
bodyPath.traverse({
|
|
437
|
-
Function(innerPath) {
|
|
438
|
-
// Skip nested functions
|
|
439
|
-
innerPath.skip();
|
|
440
|
-
},
|
|
441
|
-
ReturnStatement(returnPath) {
|
|
442
|
-
// Only process return statements that are direct children of this function
|
|
443
|
-
const parentFunction = returnPath.getFunctionParent();
|
|
444
|
-
if (parentFunction?.node !== arrowFunction) {
|
|
445
|
-
return;
|
|
446
|
-
}
|
|
447
|
-
if (!t.isReturnStatement(returnPath.node)) {
|
|
448
|
-
return;
|
|
449
|
-
}
|
|
450
|
-
const returnArg = returnPath.node.argument;
|
|
451
|
-
if (!returnArg || !t.isExpression(returnArg)) {
|
|
452
|
-
return;
|
|
453
|
-
}
|
|
454
|
-
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings);
|
|
455
|
-
if (returnResult !== null) {
|
|
456
|
-
branches.push(returnResult);
|
|
457
|
-
}
|
|
458
|
-
},
|
|
459
|
-
});
|
|
992
|
+
// Handle string/numeric/boolean/null constants
|
|
993
|
+
else if (t.isStringLiteral(init)) {
|
|
994
|
+
result = { type: 'text', text: init.value };
|
|
460
995
|
}
|
|
461
|
-
if (
|
|
462
|
-
result =
|
|
996
|
+
else if (t.isNumericLiteral(init)) {
|
|
997
|
+
result = { type: 'text', text: String(init.value) };
|
|
463
998
|
}
|
|
464
|
-
else if (
|
|
465
|
-
result = { type: '
|
|
999
|
+
else if (t.isBooleanLiteral(init)) {
|
|
1000
|
+
result = { type: 'text', text: String(init.value) };
|
|
1001
|
+
}
|
|
1002
|
+
// Handle template literals
|
|
1003
|
+
else if (t.isTemplateLiteral(init)) {
|
|
1004
|
+
const parts = [];
|
|
1005
|
+
let failed = false;
|
|
1006
|
+
for (let index = 0; index < init.quasis.length; index++) {
|
|
1007
|
+
const quasi = init.quasis[index];
|
|
1008
|
+
const text = quasi.value.cooked ?? quasi.value.raw ?? '';
|
|
1009
|
+
if (text) {
|
|
1010
|
+
parts.push({ type: 'text', text });
|
|
1011
|
+
}
|
|
1012
|
+
const exprNode = init.expressions[index];
|
|
1013
|
+
if (exprNode && t.isExpression(exprNode)) {
|
|
1014
|
+
const exprResult = parseStringExpression(exprNode, path, filePath, parsingOptions, warnings, errors);
|
|
1015
|
+
if (exprResult === null) {
|
|
1016
|
+
failed = true;
|
|
1017
|
+
break;
|
|
1018
|
+
}
|
|
1019
|
+
parts.push(exprResult);
|
|
1020
|
+
}
|
|
1021
|
+
}
|
|
1022
|
+
if (!failed) {
|
|
1023
|
+
if (parts.length === 0) {
|
|
1024
|
+
result = { type: 'text', text: '' };
|
|
1025
|
+
}
|
|
1026
|
+
else if (parts.length === 1) {
|
|
1027
|
+
result = parts[0];
|
|
1028
|
+
}
|
|
1029
|
+
else {
|
|
1030
|
+
result = { type: 'sequence', nodes: parts };
|
|
1031
|
+
}
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
// Handle object expressions (and `as const` / `satisfies`)
|
|
1035
|
+
else if (t.isObjectExpression(init) ||
|
|
1036
|
+
t.isObjectExpression(unwrapTypeAnnotation(init))) {
|
|
1037
|
+
const objExpr = unwrapTypeAnnotation(init);
|
|
1038
|
+
const branches = [];
|
|
1039
|
+
for (const prop of objExpr.properties) {
|
|
1040
|
+
if (!t.isObjectProperty(prop) || !t.isExpression(prop.value))
|
|
1041
|
+
continue;
|
|
1042
|
+
const resolved = parseStringExpression(prop.value, path, filePath, parsingOptions, warnings, errors);
|
|
1043
|
+
if (resolved)
|
|
1044
|
+
branches.push(resolved);
|
|
1045
|
+
}
|
|
1046
|
+
if (branches.length === 1)
|
|
1047
|
+
result = branches[0];
|
|
1048
|
+
else if (branches.length > 1)
|
|
1049
|
+
result = { type: 'choice', nodes: branches };
|
|
466
1050
|
}
|
|
467
1051
|
}
|
|
468
1052
|
},
|
|
@@ -18,12 +18,13 @@ export type StringTree = (string | StringTree)[];
|
|
|
18
18
|
* - Only provide at entry for template macros, otherwise omit
|
|
19
19
|
* - t`Hello {nonDerivableValue}` -> t`Hello {0}`
|
|
20
20
|
*/
|
|
21
|
-
export declare function handleDerivation({ expr, tPath, file, parsingOptions, errors, runtimeInterpolationState, }: {
|
|
21
|
+
export declare function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, }: {
|
|
22
22
|
expr: t.Expression;
|
|
23
23
|
tPath: NodePath;
|
|
24
24
|
file: string;
|
|
25
25
|
parsingOptions: ParsingConfigOptions;
|
|
26
26
|
errors: string[];
|
|
27
|
+
warnings: Set<string>;
|
|
27
28
|
runtimeInterpolationState?: {
|
|
28
29
|
index: number;
|
|
29
30
|
};
|
|
@@ -38,7 +38,7 @@ const processFunctionCache = new Map();
|
|
|
38
38
|
* - Only provide at entry for template macros, otherwise omit
|
|
39
39
|
* - t`Hello {nonDerivableValue}` -> t`Hello {0}`
|
|
40
40
|
*/
|
|
41
|
-
export function handleDerivation({ expr, tPath, file, parsingOptions, errors, runtimeInterpolationState, }) {
|
|
41
|
+
export function handleDerivation({ expr, tPath, file, parsingOptions, errors, warnings, runtimeInterpolationState, }) {
|
|
42
42
|
if (!expr) {
|
|
43
43
|
return null;
|
|
44
44
|
}
|
|
@@ -51,6 +51,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
51
51
|
file,
|
|
52
52
|
parsingOptions,
|
|
53
53
|
errors,
|
|
54
|
+
warnings,
|
|
54
55
|
});
|
|
55
56
|
if (variants) {
|
|
56
57
|
return {
|
|
@@ -98,6 +99,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
98
99
|
file,
|
|
99
100
|
parsingOptions,
|
|
100
101
|
errors,
|
|
102
|
+
warnings,
|
|
101
103
|
});
|
|
102
104
|
if (result === null)
|
|
103
105
|
return null;
|
|
@@ -111,6 +113,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
111
113
|
file,
|
|
112
114
|
parsingOptions,
|
|
113
115
|
errors,
|
|
116
|
+
warnings,
|
|
114
117
|
runtimeInterpolationState,
|
|
115
118
|
});
|
|
116
119
|
if (result === null)
|
|
@@ -138,6 +141,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
138
141
|
file,
|
|
139
142
|
parsingOptions,
|
|
140
143
|
errors,
|
|
144
|
+
warnings,
|
|
141
145
|
runtimeInterpolationState,
|
|
142
146
|
});
|
|
143
147
|
const rightResult = handleDerivation({
|
|
@@ -146,6 +150,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
146
150
|
file,
|
|
147
151
|
parsingOptions,
|
|
148
152
|
errors,
|
|
153
|
+
warnings,
|
|
149
154
|
runtimeInterpolationState,
|
|
150
155
|
});
|
|
151
156
|
if (leftResult === null || rightResult === null) {
|
|
@@ -161,6 +166,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
161
166
|
file,
|
|
162
167
|
parsingOptions,
|
|
163
168
|
errors,
|
|
169
|
+
warnings,
|
|
164
170
|
runtimeInterpolationState,
|
|
165
171
|
});
|
|
166
172
|
}
|
|
@@ -214,7 +220,7 @@ export function handleDerivation({ expr, tPath, file, parsingOptions, errors, ru
|
|
|
214
220
|
*
|
|
215
221
|
* Returns null if it can't be resolved.
|
|
216
222
|
*/
|
|
217
|
-
function getDeriveVariants({ call, tPath, file, parsingOptions, errors, }) {
|
|
223
|
+
function getDeriveVariants({ call, tPath, file, parsingOptions, errors, warnings, }) {
|
|
218
224
|
// --- Validate Callee --- //
|
|
219
225
|
// Must be a derive(...) call or an alias of it
|
|
220
226
|
if (!isDeriveCall({ expr: call, tPath })) {
|
|
@@ -233,12 +239,12 @@ function getDeriveVariants({ call, tPath, file, parsingOptions, errors, }) {
|
|
|
233
239
|
// Handle await expression: derive(await time())
|
|
234
240
|
if (t.isAwaitExpression(arg)) {
|
|
235
241
|
// Resolve the inner call's possible string outcomes
|
|
236
|
-
return resolveCallStringVariants(arg.argument, tPath, file, parsingOptions, errors);
|
|
242
|
+
return resolveCallStringVariants(arg.argument, tPath, file, parsingOptions, errors, warnings);
|
|
237
243
|
}
|
|
238
244
|
// Resolve the inner call's possible string outcomes
|
|
239
|
-
return resolveCallStringVariants(arg, tPath, file, parsingOptions, errors);
|
|
245
|
+
return resolveCallStringVariants(arg, tPath, file, parsingOptions, errors, warnings);
|
|
240
246
|
}
|
|
241
|
-
function resolveCallStringVariants(expression, tPath, file, parsingOptions, errors) {
|
|
247
|
+
function resolveCallStringVariants(expression, tPath, file, parsingOptions, errors, warnings) {
|
|
242
248
|
// Handle function identifier calls: derive(time())
|
|
243
249
|
if (t.isCallExpression(expression) && t.isIdentifier(expression.callee)) {
|
|
244
250
|
const functionName = expression.callee.name;
|
|
@@ -268,7 +274,7 @@ function resolveCallStringVariants(expression, tPath, file, parsingOptions, erro
|
|
|
268
274
|
if (importPath) {
|
|
269
275
|
const filePath = resolveImportPath(file, importPath, parsingOptions, resolveImportPathCache);
|
|
270
276
|
if (filePath && originalName) {
|
|
271
|
-
const node = resolveFunctionInFile(filePath, originalName, parsingOptions, errors);
|
|
277
|
+
const node = resolveFunctionInFile(filePath, originalName, parsingOptions, errors, warnings);
|
|
272
278
|
if (node) {
|
|
273
279
|
return nodeToStrings(node);
|
|
274
280
|
}
|
|
@@ -277,7 +283,7 @@ function resolveCallStringVariants(expression, tPath, file, parsingOptions, erro
|
|
|
277
283
|
}
|
|
278
284
|
else {
|
|
279
285
|
// Function is local - use parseStringExpression with resolveFunctionCall
|
|
280
|
-
const node = resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptions);
|
|
286
|
+
const node = resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptions, warnings, errors);
|
|
281
287
|
if (node) {
|
|
282
288
|
return nodeToStrings(node);
|
|
283
289
|
}
|
|
@@ -290,7 +296,7 @@ function resolveCallStringVariants(expression, tPath, file, parsingOptions, erro
|
|
|
290
296
|
}
|
|
291
297
|
}
|
|
292
298
|
// If we get here: analyze this call as derivable (statically analyzable)
|
|
293
|
-
const node = parseStringExpression(expression, tPath, file, parsingOptions);
|
|
299
|
+
const node = parseStringExpression(expression, tPath, file, parsingOptions, warnings, errors);
|
|
294
300
|
if (node) {
|
|
295
301
|
return nodeToStrings(node);
|
|
296
302
|
}
|
|
@@ -299,7 +305,7 @@ function resolveCallStringVariants(expression, tPath, file, parsingOptions, erro
|
|
|
299
305
|
/**
|
|
300
306
|
* Resolves a function from a binding (local function) using parseStringExpression logic
|
|
301
307
|
*/
|
|
302
|
-
function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptions) {
|
|
308
|
+
function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptions, warnings, errors) {
|
|
303
309
|
if (!calleeBinding) {
|
|
304
310
|
return null;
|
|
305
311
|
}
|
|
@@ -318,7 +324,7 @@ function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptio
|
|
|
318
324
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
319
325
|
return;
|
|
320
326
|
}
|
|
321
|
-
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions);
|
|
327
|
+
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
|
|
322
328
|
if (returnResult !== null) {
|
|
323
329
|
branches.push(returnResult);
|
|
324
330
|
}
|
|
@@ -334,7 +340,7 @@ function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptio
|
|
|
334
340
|
const body = init.get('body');
|
|
335
341
|
// Handle expression body: () => "day"
|
|
336
342
|
if (body.isExpression()) {
|
|
337
|
-
const bodyResult = parseStringExpression(body.node, body, file, parsingOptions);
|
|
343
|
+
const bodyResult = parseStringExpression(body.node, body, file, parsingOptions, warnings, errors);
|
|
338
344
|
if (bodyResult !== null) {
|
|
339
345
|
branches.push(bodyResult);
|
|
340
346
|
}
|
|
@@ -353,7 +359,7 @@ function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptio
|
|
|
353
359
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
354
360
|
return;
|
|
355
361
|
}
|
|
356
|
-
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions);
|
|
362
|
+
const returnResult = parseStringExpression(returnArg, returnPath, file, parsingOptions, warnings, errors);
|
|
357
363
|
if (returnResult !== null) {
|
|
358
364
|
branches.push(returnResult);
|
|
359
365
|
}
|
|
@@ -372,7 +378,7 @@ function resolveFunctionCallFromBinding(calleeBinding, tPath, file, parsingOptio
|
|
|
372
378
|
/**
|
|
373
379
|
* Resolves a function definition in an external file
|
|
374
380
|
*/
|
|
375
|
-
function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
381
|
+
function resolveFunctionInFile(filePath, functionName, parsingOptions, errors, warnings) {
|
|
376
382
|
// Check cache first
|
|
377
383
|
const cacheKey = `${filePath}::${functionName}`;
|
|
378
384
|
if (processFunctionCache.has(cacheKey)) {
|
|
@@ -396,7 +402,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
|
396
402
|
const resolvedPath = resolveImportPath(filePath, reexportPath, parsingOptions, resolveImportPathCache);
|
|
397
403
|
if (resolvedPath) {
|
|
398
404
|
// Recursively resolve in the re-exported file
|
|
399
|
-
const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, errors);
|
|
405
|
+
const reexportResult = resolveFunctionInFile(resolvedPath, functionName, parsingOptions, errors, warnings);
|
|
400
406
|
if (reexportResult) {
|
|
401
407
|
result = reexportResult;
|
|
402
408
|
}
|
|
@@ -441,7 +447,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
|
441
447
|
originalName = specifier.local.name;
|
|
442
448
|
}
|
|
443
449
|
// Recursively resolve in the re-exported file
|
|
444
|
-
const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, errors);
|
|
450
|
+
const reexportResult = resolveFunctionInFile(resolvedPath, originalName, parsingOptions, errors, warnings);
|
|
445
451
|
if (reexportResult) {
|
|
446
452
|
result = reexportResult;
|
|
447
453
|
}
|
|
@@ -466,7 +472,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
|
466
472
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
467
473
|
return;
|
|
468
474
|
}
|
|
469
|
-
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions);
|
|
475
|
+
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
|
|
470
476
|
if (returnResult !== null) {
|
|
471
477
|
branches.push(returnResult);
|
|
472
478
|
}
|
|
@@ -497,7 +503,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
|
497
503
|
const branches = [];
|
|
498
504
|
// Handle expression body: () => "day"
|
|
499
505
|
if (!Array.isArray(bodyPath) && t.isExpression(bodyPath.node)) {
|
|
500
|
-
const bodyResult = parseStringExpression(bodyPath.node, bodyPath, filePath, parsingOptions);
|
|
506
|
+
const bodyResult = parseStringExpression(bodyPath.node, bodyPath, filePath, parsingOptions, warnings, errors);
|
|
501
507
|
if (bodyResult !== null) {
|
|
502
508
|
branches.push(bodyResult);
|
|
503
509
|
}
|
|
@@ -524,7 +530,7 @@ function resolveFunctionInFile(filePath, functionName, parsingOptions, errors) {
|
|
|
524
530
|
if (!returnArg || !t.isExpression(returnArg)) {
|
|
525
531
|
return;
|
|
526
532
|
}
|
|
527
|
-
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions);
|
|
533
|
+
const returnResult = parseStringExpression(returnArg, returnPath, filePath, parsingOptions, warnings, errors);
|
|
528
534
|
if (returnResult !== null) {
|
|
529
535
|
branches.push(returnResult);
|
|
530
536
|
}
|
|
@@ -27,6 +27,7 @@ export function deriveExpression({ tPath, expr, metadata, config, output, index,
|
|
|
27
27
|
file: config.file,
|
|
28
28
|
parsingOptions: config.parsingOptions,
|
|
29
29
|
errors: output.errors,
|
|
30
|
+
warnings: output.warnings,
|
|
30
31
|
runtimeInterpolationState: enableRuntimeInterpolation
|
|
31
32
|
? { index: 0 }
|
|
32
33
|
: undefined,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gt",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.12.0",
|
|
4
4
|
"main": "dist/index.js",
|
|
5
5
|
"bin": "dist/main.js",
|
|
6
6
|
"files": [
|
|
@@ -110,8 +110,8 @@
|
|
|
110
110
|
"unified": "^11.0.5",
|
|
111
111
|
"unist-util-visit": "^5.0.0",
|
|
112
112
|
"yaml": "^2.8.0",
|
|
113
|
+
"@generaltranslation/python-extractor": "0.2.0",
|
|
113
114
|
"generaltranslation": "8.1.20",
|
|
114
|
-
"@generaltranslation/python-extractor": "0.1.6",
|
|
115
115
|
"gt-remark": "1.0.6"
|
|
116
116
|
},
|
|
117
117
|
"devDependencies": {
|