modality-ts 0.0.1 → 0.0.2
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/dist/extraction/index.d.ts +1 -1
- package/dist/extraction/index.d.ts.map +1 -1
- package/dist/extraction/index.js +112 -37
- package/dist/extraction/index.js.map +1 -1
- package/dist/modality/features/extract/command.d.ts.map +1 -1
- package/dist/modality/features/extract/command.js +33 -1
- package/dist/modality/features/extract/command.js.map +1 -1
- package/dist/sources/use-state/index.d.ts +1 -1
- package/dist/sources/use-state/index.d.ts.map +1 -1
- package/dist/sources/use-state/index.js +23 -9
- package/dist/sources/use-state/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -25,7 +25,7 @@ export interface UseStateExtractionResult {
|
|
|
25
25
|
export interface ExtractedModelSkeleton extends UseStateExtractionResult {
|
|
26
26
|
transitions: Transition[];
|
|
27
27
|
}
|
|
28
|
-
export declare function inferDomainFromTypeNode(node: ts.TypeNode | undefined): AbstractDomain;
|
|
28
|
+
export declare function inferDomainFromTypeNode(node: ts.TypeNode | undefined, typeAliases?: ReadonlyMap<string, ts.TypeNode>): AbstractDomain;
|
|
29
29
|
export declare function extractUseStateVars(sourceText: string, options?: UseStateExtractionOptions): UseStateExtractionResult;
|
|
30
30
|
export declare function extractUseStateSkeleton(sourceText: string, options?: UseStateExtractionOptions): ExtractedModelSkeleton;
|
|
31
31
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extraction/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAA6B,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAuB,SAAQ,wBAAwB;IACtE,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AA0CD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,GAAG,cAAc,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/extraction/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AACjC,OAAO,KAAK,EAAE,cAAc,EAA6B,YAAY,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AACrH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAEnD,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAE/B,MAAM,WAAW,yBAAyB;IACxC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC/B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,OAAO,EAAE,KAAK,CAAC;QAAC,KAAK,CAAC,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IAClE,SAAS,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;IACpC,aAAa,CAAC,EAAE,SAAS,YAAY,EAAE,CAAC;CACzC;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,YAAY,EAAE,CAAC;IACrB,QAAQ,EAAE,iBAAiB,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,sBAAuB,SAAQ,wBAAwB;IACtE,WAAW,EAAE,UAAU,EAAE,CAAC;CAC3B;AA0CD,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,EAAE,CAAC,QAAQ,GAAG,SAAS,EAAE,WAAW,GAAE,WAAW,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAa,GAAG,cAAc,CAuBhJ;AAED,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,wBAAwB,CAEzH;AAED,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,yBAA8B,GAAG,sBAAsB,CA2I3H"}
|
package/dist/extraction/index.js
CHANGED
|
@@ -11,7 +11,7 @@ function setterBindingFromDecl(decl) {
|
|
|
11
11
|
domain: decl.domain
|
|
12
12
|
};
|
|
13
13
|
}
|
|
14
|
-
export function inferDomainFromTypeNode(node) {
|
|
14
|
+
export function inferDomainFromTypeNode(node, typeAliases = new Map()) {
|
|
15
15
|
if (!node)
|
|
16
16
|
return { kind: "tokens", count: 1 };
|
|
17
17
|
switch (node.kind) {
|
|
@@ -25,13 +25,13 @@ export function inferDomainFromTypeNode(node) {
|
|
|
25
25
|
case ts.SyntaxKind.LiteralType:
|
|
26
26
|
return domainFromLiteralType(node);
|
|
27
27
|
case ts.SyntaxKind.UnionType:
|
|
28
|
-
return domainFromUnion(node);
|
|
28
|
+
return domainFromUnion(node, typeAliases);
|
|
29
29
|
case ts.SyntaxKind.TypeLiteral:
|
|
30
30
|
return domainFromTypeLiteral(node);
|
|
31
31
|
case ts.SyntaxKind.ArrayType:
|
|
32
32
|
return { kind: "lengthCat" };
|
|
33
33
|
case ts.SyntaxKind.TypeReference:
|
|
34
|
-
return domainFromTypeReference(node);
|
|
34
|
+
return domainFromTypeReference(node, typeAliases);
|
|
35
35
|
default:
|
|
36
36
|
return { kind: "tokens", count: 1 };
|
|
37
37
|
}
|
|
@@ -42,6 +42,7 @@ export function extractUseStateVars(sourceText, options = {}) {
|
|
|
42
42
|
export function extractUseStateSkeleton(sourceText, options = {}) {
|
|
43
43
|
const fileName = options.fileName ?? "App.tsx";
|
|
44
44
|
const source = ts.createSourceFile(fileName, sourceText, ts.ScriptTarget.Latest, true, ts.ScriptKind.TSX);
|
|
45
|
+
const typeAliases = typeAliasDeclarations(source);
|
|
45
46
|
const vars = options.stateVars ? [...options.stateVars] : [];
|
|
46
47
|
const transitions = [];
|
|
47
48
|
const warnings = [];
|
|
@@ -96,7 +97,7 @@ export function extractUseStateSkeleton(sourceText, options = {}) {
|
|
|
96
97
|
const stateName = node.name.elements[0];
|
|
97
98
|
const setterName = node.name.elements[1];
|
|
98
99
|
if (ts.isBindingElement(stateName) && ts.isIdentifier(stateName.name)) {
|
|
99
|
-
const domain = inferUseStateDomain(node.initializer);
|
|
100
|
+
const domain = inferUseStateDomain(node.initializer, typeAliases);
|
|
100
101
|
const component = nextComponent ?? "Anonymous";
|
|
101
102
|
const varId = `local:${component}.${stateName.name.text}`;
|
|
102
103
|
if (!options.stateVars) {
|
|
@@ -159,9 +160,10 @@ export function extractUseStateSkeleton(sourceText, options = {}) {
|
|
|
159
160
|
ts.forEachChild(node, (child) => visit(child, nextComponent));
|
|
160
161
|
return;
|
|
161
162
|
}
|
|
163
|
+
const guardLocals = componentGuardLocalsFor(node, setters);
|
|
162
164
|
const guard = combineParsedGuards([
|
|
163
|
-
renderGuardFor(node, setters, warnings, source, nextComponent ?? "Anonymous"),
|
|
164
|
-
disabledGuardFor(node, setters, warnings, source, nextComponent ?? "Anonymous")
|
|
165
|
+
renderGuardFor(node, setters, warnings, source, nextComponent ?? "Anonymous", guardLocals),
|
|
166
|
+
disabledGuardFor(node, setters, warnings, source, nextComponent ?? "Anonymous", guardLocals)
|
|
165
167
|
]);
|
|
166
168
|
const extracted = transitionsFromJsxAttribute(source, fileName, node, setters, handlers, nextComponent ?? "Anonymous", effectApis, options.asyncOutcomes ?? {}, guard, warnings);
|
|
167
169
|
transitions.push(...extracted);
|
|
@@ -223,10 +225,10 @@ function shortHash(value) {
|
|
|
223
225
|
}
|
|
224
226
|
return (hash >>> 0).toString(36).padStart(6, "0").slice(0, 6);
|
|
225
227
|
}
|
|
226
|
-
function inferUseStateDomain(call) {
|
|
228
|
+
function inferUseStateDomain(call, typeAliases = new Map()) {
|
|
227
229
|
const typeArg = call.typeArguments?.[0];
|
|
228
230
|
if (typeArg)
|
|
229
|
-
return inferDomainFromTypeNode(typeArg);
|
|
231
|
+
return inferDomainFromTypeNode(typeArg, typeAliases);
|
|
230
232
|
const initial = call.arguments[0];
|
|
231
233
|
if (!initial)
|
|
232
234
|
return { kind: "tokens", count: 1 };
|
|
@@ -289,10 +291,10 @@ function domainFromLiteralType(node) {
|
|
|
289
291
|
return { kind: "option", inner: { kind: "tokens", count: 1 } };
|
|
290
292
|
return { kind: "tokens", count: 1 };
|
|
291
293
|
}
|
|
292
|
-
function domainFromUnion(node) {
|
|
294
|
+
function domainFromUnion(node, typeAliases = new Map()) {
|
|
293
295
|
const nonNull = node.types.filter((part) => part.kind !== ts.SyntaxKind.UndefinedKeyword && !(ts.isLiteralTypeNode(part) && part.literal.kind === ts.SyntaxKind.NullKeyword));
|
|
294
296
|
if (nonNull.length !== node.types.length && nonNull.length > 0) {
|
|
295
|
-
return { kind: "option", inner: nonNull.length === 1 ? inferDomainFromTypeNode(nonNull[0]) : domainFromUnionMembers(nonNull) };
|
|
297
|
+
return { kind: "option", inner: nonNull.length === 1 ? inferDomainFromTypeNode(nonNull[0], typeAliases) : domainFromUnionMembers(nonNull) };
|
|
296
298
|
}
|
|
297
299
|
return domainFromUnionMembers(node.types);
|
|
298
300
|
}
|
|
@@ -353,14 +355,27 @@ function domainFromTypeLiteral(node, omitField) {
|
|
|
353
355
|
}
|
|
354
356
|
return { kind: "record", fields };
|
|
355
357
|
}
|
|
356
|
-
function domainFromTypeReference(node) {
|
|
358
|
+
function domainFromTypeReference(node, typeAliases = new Map()) {
|
|
357
359
|
const name = node.typeName.getText();
|
|
360
|
+
const alias = typeAliases.get(name);
|
|
361
|
+
if (alias)
|
|
362
|
+
return inferDomainFromTypeNode(alias, typeAliases);
|
|
358
363
|
if ((name === "Array" || name === "ReadonlyArray") && node.typeArguments?.length === 1)
|
|
359
364
|
return { kind: "lengthCat" };
|
|
360
365
|
if (name === "Record")
|
|
361
366
|
return { kind: "tokens", count: 1 };
|
|
362
367
|
return { kind: "tokens", count: 1 };
|
|
363
368
|
}
|
|
369
|
+
function typeAliasDeclarations(source) {
|
|
370
|
+
const aliases = new Map();
|
|
371
|
+
const visit = (node) => {
|
|
372
|
+
if (ts.isTypeAliasDeclaration(node) && ts.isIdentifier(node.name))
|
|
373
|
+
aliases.set(node.name.text, node.type);
|
|
374
|
+
ts.forEachChild(node, visit);
|
|
375
|
+
};
|
|
376
|
+
visit(source);
|
|
377
|
+
return aliases;
|
|
378
|
+
}
|
|
364
379
|
function isUseStateCall(node) {
|
|
365
380
|
return ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === "useState";
|
|
366
381
|
}
|
|
@@ -504,9 +519,10 @@ function transitionsFromComponentPropAttribute(source, fileName, node, setters,
|
|
|
504
519
|
const handler = handlerExpression(expression, handlers);
|
|
505
520
|
if (!handler)
|
|
506
521
|
return [];
|
|
522
|
+
const guardLocals = componentGuardLocalsFor(node, setters);
|
|
507
523
|
const callerGuard = combineParsedGuards([
|
|
508
|
-
renderGuardFor(node, setters, warnings, source, component),
|
|
509
|
-
disabledGuardFor(node, setters, warnings, source, component)
|
|
524
|
+
renderGuardFor(node, setters, warnings, source, component, guardLocals),
|
|
525
|
+
disabledGuardFor(node, setters, warnings, source, component, guardLocals)
|
|
510
526
|
]);
|
|
511
527
|
return tagStableIdKey(transitionsFromResolvedHandler(source, fileName, node, trigger.attr, handler, setters, handlers, component, effectApis, asyncOutcomes, combineParsedGuards([trigger.guard, callerGuard]), trigger.locator, warnings), handler);
|
|
512
528
|
}
|
|
@@ -936,6 +952,30 @@ function effectWriteVars(effect) {
|
|
|
936
952
|
function stateNameForVar(varId, setters) {
|
|
937
953
|
return [...setters.values()].find((setter) => setter.varId === varId)?.stateName;
|
|
938
954
|
}
|
|
955
|
+
function componentGuardLocalsFor(attribute, setters) {
|
|
956
|
+
const body = enclosingFunctionBody(attribute);
|
|
957
|
+
if (!body)
|
|
958
|
+
return new Map();
|
|
959
|
+
const locals = new Map();
|
|
960
|
+
for (const statement of body.statements) {
|
|
961
|
+
if (statement.pos > attribute.pos)
|
|
962
|
+
break;
|
|
963
|
+
if (ts.isReturnStatement(statement))
|
|
964
|
+
break;
|
|
965
|
+
bindConstStatement(statement, setters, locals, true);
|
|
966
|
+
}
|
|
967
|
+
return locals;
|
|
968
|
+
}
|
|
969
|
+
function enclosingFunctionBody(node) {
|
|
970
|
+
let current = node;
|
|
971
|
+
while (current) {
|
|
972
|
+
if ((ts.isFunctionDeclaration(current) || ts.isFunctionExpression(current) || ts.isArrowFunction(current)) && current.body && ts.isBlock(current.body)) {
|
|
973
|
+
return current.body;
|
|
974
|
+
}
|
|
975
|
+
current = current.parent;
|
|
976
|
+
}
|
|
977
|
+
return undefined;
|
|
978
|
+
}
|
|
939
979
|
function callSummaryFromHandler(handler, setters, initialLocals = new Map()) {
|
|
940
980
|
const body = handler.body;
|
|
941
981
|
if (ts.isCallExpression(body))
|
|
@@ -953,7 +993,7 @@ function callSummaryFromHandler(handler, setters, initialLocals = new Map()) {
|
|
|
953
993
|
}
|
|
954
994
|
return undefined;
|
|
955
995
|
}
|
|
956
|
-
function bindConstStatement(statement, setters, locals) {
|
|
996
|
+
function bindConstStatement(statement, setters, locals, partialBoolean = false) {
|
|
957
997
|
if (!ts.isVariableStatement(statement))
|
|
958
998
|
return false;
|
|
959
999
|
if ((ts.getCombinedNodeFlags(statement.declarationList) & ts.NodeFlags.Const) === 0)
|
|
@@ -961,7 +1001,8 @@ function bindConstStatement(statement, setters, locals) {
|
|
|
961
1001
|
for (const declaration of statement.declarationList.declarations) {
|
|
962
1002
|
if (!ts.isIdentifier(declaration.name) || !declaration.initializer)
|
|
963
1003
|
return false;
|
|
964
|
-
const binding = valueExpr(declaration.initializer, setters, locals)
|
|
1004
|
+
const binding = valueExpr(declaration.initializer, setters, locals) ??
|
|
1005
|
+
(partialBoolean ? parseConjunctiveGuardExpression(declaration.initializer, setters, locals) : booleanExpr(declaration.initializer, setters, locals));
|
|
965
1006
|
if (!binding)
|
|
966
1007
|
return false;
|
|
967
1008
|
locals.set(declaration.name.text, binding);
|
|
@@ -1847,7 +1888,7 @@ function combineParsedGuards(guards) {
|
|
|
1847
1888
|
reads: [...new Set(parsed.flatMap((guard) => guard.reads))]
|
|
1848
1889
|
};
|
|
1849
1890
|
}
|
|
1850
|
-
function renderGuardFor(eventAttribute, setters, warnings, source, component) {
|
|
1891
|
+
function renderGuardFor(eventAttribute, setters, warnings, source, component, locals = new Map()) {
|
|
1851
1892
|
const element = jsxElementForAttribute(eventAttribute);
|
|
1852
1893
|
if (!element)
|
|
1853
1894
|
return undefined;
|
|
@@ -1857,7 +1898,7 @@ function renderGuardFor(eventAttribute, setters, warnings, source, component) {
|
|
|
1857
1898
|
if (ts.isBinaryExpression(parent) &&
|
|
1858
1899
|
parent.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken &&
|
|
1859
1900
|
parent.right === current) {
|
|
1860
|
-
const parsed =
|
|
1901
|
+
const parsed = parseConjunctiveGuardExpression(parent.left, setters, locals);
|
|
1861
1902
|
if (!parsed) {
|
|
1862
1903
|
warnings.push({ message: `Unsupported render guard ${component}.${eventAttribute.name.getText(source)}`, ...lineAndColumn(source, parent.left) });
|
|
1863
1904
|
return undefined;
|
|
@@ -1865,7 +1906,7 @@ function renderGuardFor(eventAttribute, setters, warnings, source, component) {
|
|
|
1865
1906
|
return parsed;
|
|
1866
1907
|
}
|
|
1867
1908
|
if (ts.isConditionalExpression(parent) && parent.whenTrue === current) {
|
|
1868
|
-
const parsed =
|
|
1909
|
+
const parsed = parseConjunctiveGuardExpression(parent.condition, setters, locals);
|
|
1869
1910
|
if (!parsed) {
|
|
1870
1911
|
warnings.push({ message: `Unsupported render guard ${component}.${eventAttribute.name.getText(source)}`, ...lineAndColumn(source, parent.condition) });
|
|
1871
1912
|
return undefined;
|
|
@@ -1873,7 +1914,7 @@ function renderGuardFor(eventAttribute, setters, warnings, source, component) {
|
|
|
1873
1914
|
return parsed;
|
|
1874
1915
|
}
|
|
1875
1916
|
if (ts.isConditionalExpression(parent) && parent.whenFalse === current) {
|
|
1876
|
-
const parsed =
|
|
1917
|
+
const parsed = parseConjunctiveGuardExpression(parent.condition, setters, locals);
|
|
1877
1918
|
if (!parsed) {
|
|
1878
1919
|
warnings.push({ message: `Unsupported render guard ${component}.${eventAttribute.name.getText(source)}`, ...lineAndColumn(source, parent.condition) });
|
|
1879
1920
|
return undefined;
|
|
@@ -1897,50 +1938,73 @@ function jsxElementForAttribute(attribute) {
|
|
|
1897
1938
|
return element.parent;
|
|
1898
1939
|
return ts.isJsxSelfClosingElement(element) ? element : undefined;
|
|
1899
1940
|
}
|
|
1900
|
-
function disabledGuardFor(eventAttribute, setters, warnings, source, component) {
|
|
1941
|
+
function disabledGuardFor(eventAttribute, setters, warnings, source, component, locals = new Map()) {
|
|
1901
1942
|
const attrs = eventAttribute.parent;
|
|
1902
1943
|
if (!ts.isJsxAttributes(attrs))
|
|
1903
1944
|
return undefined;
|
|
1904
|
-
const disabled = attrs.properties.find((property) => ts.isJsxAttribute(property) && ts.isIdentifier(property.name) && (property.name.text === "disabled" || property.name.text === "aria-disabled"));
|
|
1945
|
+
const disabled = attrs.properties.find((property) => ts.isJsxAttribute(property) && ts.isIdentifier(property.name) && (property.name.text === "disabled" || property.name.text === "aria-disabled")) ?? submitButtonDisabledAttribute(eventAttribute);
|
|
1905
1946
|
if (!disabled)
|
|
1906
1947
|
return undefined;
|
|
1907
|
-
const parsed = jsxAttributeBoolean(disabled, setters);
|
|
1948
|
+
const parsed = jsxAttributeBoolean(disabled, setters, locals);
|
|
1908
1949
|
if (!parsed) {
|
|
1909
1950
|
warnings.push({ message: `Unsupported disabled guard ${component}.${eventAttribute.name.getText(source)}`, ...lineAndColumn(source, disabled) });
|
|
1910
1951
|
return undefined;
|
|
1911
1952
|
}
|
|
1912
1953
|
return { expr: { kind: "not", args: [parsed.expr] }, reads: parsed.reads };
|
|
1913
1954
|
}
|
|
1914
|
-
function
|
|
1955
|
+
function submitButtonDisabledAttribute(eventAttribute) {
|
|
1956
|
+
if (!ts.isIdentifier(eventAttribute.name) || eventAttribute.name.text !== "onSubmit")
|
|
1957
|
+
return undefined;
|
|
1958
|
+
const element = jsxElementForAttribute(eventAttribute);
|
|
1959
|
+
if (!element || !ts.isJsxElement(element))
|
|
1960
|
+
return undefined;
|
|
1961
|
+
let found;
|
|
1962
|
+
const visit = (node) => {
|
|
1963
|
+
if (found)
|
|
1964
|
+
return;
|
|
1965
|
+
if (ts.isJsxOpeningElement(node) || ts.isJsxSelfClosingElement(node)) {
|
|
1966
|
+
const tag = ts.isIdentifier(node.tagName) ? node.tagName.text : undefined;
|
|
1967
|
+
if (tag === "button" && stringAttribute(node.attributes, "type") === "submit") {
|
|
1968
|
+
found = node.attributes.properties.find((property) => ts.isJsxAttribute(property) && ts.isIdentifier(property.name) && (property.name.text === "disabled" || property.name.text === "aria-disabled"));
|
|
1969
|
+
if (found)
|
|
1970
|
+
return;
|
|
1971
|
+
}
|
|
1972
|
+
}
|
|
1973
|
+
ts.forEachChild(node, visit);
|
|
1974
|
+
};
|
|
1975
|
+
visit(element);
|
|
1976
|
+
return found;
|
|
1977
|
+
}
|
|
1978
|
+
function jsxAttributeBoolean(attribute, setters, locals = new Map()) {
|
|
1915
1979
|
if (!attribute.initializer)
|
|
1916
1980
|
return { expr: { kind: "lit", value: true }, reads: [] };
|
|
1917
1981
|
if (ts.isStringLiteral(attribute.initializer))
|
|
1918
1982
|
return { expr: { kind: "lit", value: attribute.initializer.text === "true" }, reads: [] };
|
|
1919
1983
|
if (!ts.isJsxExpression(attribute.initializer) || !attribute.initializer.expression)
|
|
1920
1984
|
return undefined;
|
|
1921
|
-
return
|
|
1985
|
+
return parseConjunctiveGuardExpression(attribute.initializer.expression, setters, locals);
|
|
1922
1986
|
}
|
|
1923
|
-
function parseGuardExpression(expression, setters) {
|
|
1987
|
+
function parseGuardExpression(expression, setters, locals = new Map()) {
|
|
1924
1988
|
if (expression.kind === ts.SyntaxKind.TrueKeyword)
|
|
1925
1989
|
return { expr: { kind: "lit", value: true }, reads: [] };
|
|
1926
1990
|
if (expression.kind === ts.SyntaxKind.FalseKeyword)
|
|
1927
1991
|
return { expr: { kind: "lit", value: false }, reads: [] };
|
|
1928
1992
|
if (ts.isIdentifier(expression) || ts.isPropertyAccessExpression(expression))
|
|
1929
|
-
return valueExpr(expression, setters,
|
|
1993
|
+
return valueExpr(expression, setters, locals);
|
|
1930
1994
|
if (ts.isPrefixUnaryExpression(expression) && expression.operator === ts.SyntaxKind.ExclamationToken) {
|
|
1931
|
-
const parsed = parseGuardExpression(expression.operand, setters);
|
|
1995
|
+
const parsed = parseGuardExpression(expression.operand, setters, locals);
|
|
1932
1996
|
return parsed ? { expr: { kind: "not", args: [parsed.expr] }, reads: parsed.reads } : undefined;
|
|
1933
1997
|
}
|
|
1934
1998
|
if (ts.isParenthesizedExpression(expression))
|
|
1935
|
-
return parseGuardExpression(expression.expression, setters);
|
|
1999
|
+
return parseGuardExpression(expression.expression, setters, locals);
|
|
1936
2000
|
if (ts.isBinaryExpression(expression))
|
|
1937
|
-
return parseBinaryGuardExpression(expression, setters);
|
|
2001
|
+
return parseBinaryGuardExpression(expression, setters, locals);
|
|
1938
2002
|
return undefined;
|
|
1939
2003
|
}
|
|
1940
|
-
function parseBinaryGuardExpression(expression, setters) {
|
|
2004
|
+
function parseBinaryGuardExpression(expression, setters, locals = new Map()) {
|
|
1941
2005
|
if (expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken || expression.operatorToken.kind === ts.SyntaxKind.BarBarToken) {
|
|
1942
|
-
const left = parseGuardExpression(expression.left, setters);
|
|
1943
|
-
const right = parseGuardExpression(expression.right, setters);
|
|
2006
|
+
const left = parseGuardExpression(expression.left, setters, locals);
|
|
2007
|
+
const right = parseGuardExpression(expression.right, setters, locals);
|
|
1944
2008
|
if (!left || !right)
|
|
1945
2009
|
return undefined;
|
|
1946
2010
|
return {
|
|
@@ -1952,8 +2016,8 @@ function parseBinaryGuardExpression(expression, setters) {
|
|
|
1952
2016
|
expression.operatorToken.kind === ts.SyntaxKind.EqualsEqualsToken ||
|
|
1953
2017
|
expression.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsEqualsToken ||
|
|
1954
2018
|
expression.operatorToken.kind === ts.SyntaxKind.ExclamationEqualsToken) {
|
|
1955
|
-
const left = parseGuardOperand(expression.left, setters);
|
|
1956
|
-
const right = parseGuardOperand(expression.right, setters);
|
|
2019
|
+
const left = parseGuardOperand(expression.left, setters, locals);
|
|
2020
|
+
const right = parseGuardOperand(expression.right, setters, locals);
|
|
1957
2021
|
if (!left || !right)
|
|
1958
2022
|
return undefined;
|
|
1959
2023
|
return {
|
|
@@ -1966,13 +2030,24 @@ function parseBinaryGuardExpression(expression, setters) {
|
|
|
1966
2030
|
}
|
|
1967
2031
|
return undefined;
|
|
1968
2032
|
}
|
|
1969
|
-
function parseGuardOperand(expression, setters) {
|
|
2033
|
+
function parseGuardOperand(expression, setters, locals = new Map()) {
|
|
1970
2034
|
const value = literalValue(expression);
|
|
1971
2035
|
if (value !== undefined)
|
|
1972
2036
|
return { expr: { kind: "lit", value }, reads: [] };
|
|
1973
2037
|
if (ts.isIdentifier(expression) || ts.isPropertyAccessExpression(expression))
|
|
1974
|
-
return valueExpr(expression, setters,
|
|
1975
|
-
return parseGuardExpression(expression, setters);
|
|
2038
|
+
return valueExpr(expression, setters, locals);
|
|
2039
|
+
return parseGuardExpression(expression, setters, locals);
|
|
2040
|
+
}
|
|
2041
|
+
function parseConjunctiveGuardExpression(expression, setters, locals = new Map()) {
|
|
2042
|
+
if (ts.isParenthesizedExpression(expression))
|
|
2043
|
+
return parseConjunctiveGuardExpression(expression.expression, setters, locals);
|
|
2044
|
+
if (ts.isBinaryExpression(expression) && expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandToken) {
|
|
2045
|
+
return combineParsedGuards([
|
|
2046
|
+
parseConjunctiveGuardExpression(expression.left, setters, locals),
|
|
2047
|
+
parseConjunctiveGuardExpression(expression.right, setters, locals)
|
|
2048
|
+
]);
|
|
2049
|
+
}
|
|
2050
|
+
return parseGuardExpression(expression, setters, locals);
|
|
1976
2051
|
}
|
|
1977
2052
|
function stateVarForName(name, setters) {
|
|
1978
2053
|
return [...setters.values()].find((setter) => setter.stateName === name)?.varId;
|