@typespec/emitter-framework 0.15.0-dev.3 → 0.15.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 +14 -16
- package/dist/src/python/builtins.d.ts +14 -0
- package/dist/src/python/builtins.d.ts.map +1 -0
- package/dist/src/python/builtins.js +29 -0
- package/dist/src/python/builtins.js.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.d.ts +6 -0
- package/dist/src/python/components/array-expression/array-expression.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.js +11 -0
- package/dist/src/python/components/array-expression/array-expression.js.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.test.d.ts +2 -0
- package/dist/src/python/components/array-expression/array-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/array-expression.test.js +19 -0
- package/dist/src/python/components/array-expression/array-expression.test.js.map +1 -0
- package/dist/src/python/components/array-expression/index.d.ts +2 -0
- package/dist/src/python/components/array-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/array-expression/index.js +2 -0
- package/dist/src/python/components/array-expression/index.js.map +1 -0
- package/dist/src/python/components/atom/atom.d.ts +33 -0
- package/dist/src/python/components/atom/atom.d.ts.map +1 -0
- package/dist/src/python/components/atom/atom.js +88 -0
- package/dist/src/python/components/atom/atom.js.map +1 -0
- package/dist/src/python/components/atom/atom.test.d.ts +2 -0
- package/dist/src/python/components/atom/atom.test.d.ts.map +1 -0
- package/dist/src/python/components/atom/atom.test.js +224 -0
- package/dist/src/python/components/atom/atom.test.js.map +1 -0
- package/dist/src/python/components/atom/index.d.ts +2 -0
- package/dist/src/python/components/atom/index.d.ts.map +1 -0
- package/dist/src/python/components/atom/index.js +2 -0
- package/dist/src/python/components/atom/index.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-bases.d.ts +45 -0
- package/dist/src/python/components/class-declaration/class-bases.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-bases.js +84 -0
- package/dist/src/python/components/class-declaration/class-bases.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-body.d.ts +16 -0
- package/dist/src/python/components/class-declaration/class-body.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-body.js +52 -0
- package/dist/src/python/components/class-declaration/class-body.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.d.ts +23 -0
- package/dist/src/python/components/class-declaration/class-declaration.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.js +118 -0
- package/dist/src/python/components/class-declaration/class-declaration.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.js +1527 -0
- package/dist/src/python/components/class-declaration/class-declaration.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.d.ts +16 -0
- package/dist/src/python/components/class-declaration/class-member.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.js +71 -0
- package/dist/src/python/components/class-declaration/class-member.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-member.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-member.test.js +202 -0
- package/dist/src/python/components/class-declaration/class-member.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.d.ts +22 -0
- package/dist/src/python/components/class-declaration/class-method.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.js +76 -0
- package/dist/src/python/components/class-declaration/class-method.js.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.test.d.ts +2 -0
- package/dist/src/python/components/class-declaration/class-method.test.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/class-method.test.js +298 -0
- package/dist/src/python/components/class-declaration/class-method.test.js.map +1 -0
- package/dist/src/python/components/class-declaration/index.d.ts +7 -0
- package/dist/src/python/components/class-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/index.js +7 -0
- package/dist/src/python/components/class-declaration/index.js.map +1 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.d.ts +22 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.d.ts.map +1 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.js +67 -0
- package/dist/src/python/components/class-declaration/primitive-initializer.js.map +1 -0
- package/dist/src/python/components/doc-element/doc-element.d.ts +46 -0
- package/dist/src/python/components/doc-element/doc-element.d.ts.map +1 -0
- package/dist/src/python/components/doc-element/doc-element.js +59 -0
- package/dist/src/python/components/doc-element/doc-element.js.map +1 -0
- package/dist/src/python/components/doc-element/index.d.ts +2 -0
- package/dist/src/python/components/doc-element/index.d.ts.map +1 -0
- package/dist/src/python/components/doc-element/index.js +2 -0
- package/dist/src/python/components/doc-element/index.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.d.ts +8 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.js +80 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts +2 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.js +344 -0
- package/dist/src/python/components/enum-declaration/enum-declaration.test.js.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-member.d.ts +9 -0
- package/dist/src/python/components/enum-declaration/enum-member.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/enum-member.js +22 -0
- package/dist/src/python/components/enum-declaration/enum-member.js.map +1 -0
- package/dist/src/python/components/enum-declaration/index.d.ts +3 -0
- package/dist/src/python/components/enum-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/enum-declaration/index.js +3 -0
- package/dist/src/python/components/enum-declaration/index.js.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.d.ts +24 -0
- package/dist/src/python/components/function-declaration/function-declaration.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.js +68 -0
- package/dist/src/python/components/function-declaration/function-declaration.js.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.d.ts +2 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.js +682 -0
- package/dist/src/python/components/function-declaration/function-declaration.test.js.map +1 -0
- package/dist/src/python/components/function-declaration/index.d.ts +2 -0
- package/dist/src/python/components/function-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/function-declaration/index.js +2 -0
- package/dist/src/python/components/function-declaration/index.js.map +1 -0
- package/dist/src/python/components/index.d.ts +12 -0
- package/dist/src/python/components/index.d.ts.map +1 -0
- package/dist/src/python/components/index.js +12 -0
- package/dist/src/python/components/index.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts +25 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.js +33 -0
- package/dist/src/python/components/protocol-declaration/callable-parameters.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/index.d.ts +3 -0
- package/dist/src/python/components/protocol-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/index.js +3 -0
- package/dist/src/python/components/protocol-declaration/index.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts +8 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.js +86 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.js.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts +2 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js +117 -0
- package/dist/src/python/components/protocol-declaration/protocol-declaration.test.js.map +1 -0
- package/dist/src/python/components/record-expression/index.d.ts +2 -0
- package/dist/src/python/components/record-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/index.js +2 -0
- package/dist/src/python/components/record-expression/index.js.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.d.ts +6 -0
- package/dist/src/python/components/record-expression/record-expression.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.js +13 -0
- package/dist/src/python/components/record-expression/record-expression.js.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.test.d.ts +2 -0
- package/dist/src/python/components/record-expression/record-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/record-expression/record-expression.test.js +19 -0
- package/dist/src/python/components/record-expression/record-expression.test.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/index.d.ts +2 -0
- package/dist/src/python/components/type-alias-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/index.js +2 -0
- package/dist/src/python/components/type-alias-declaration/index.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts +16 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js +75 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.js.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts +2 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js +140 -0
- package/dist/src/python/components/type-alias-declaration/type-alias-declaration.test.js.map +1 -0
- package/dist/src/python/components/type-declaration/index.d.ts +2 -0
- package/dist/src/python/components/type-declaration/index.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/index.js +2 -0
- package/dist/src/python/components/type-declaration/index.js.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.d.ts +11 -0
- package/dist/src/python/components/type-declaration/type-declaration.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.js +31 -0
- package/dist/src/python/components/type-declaration/type-declaration.js.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.d.ts +2 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.d.ts.map +1 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.js +69 -0
- package/dist/src/python/components/type-declaration/type-declaration.test.js.map +1 -0
- package/dist/src/python/components/type-expression/index.d.ts +2 -0
- package/dist/src/python/components/type-expression/index.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/index.js +2 -0
- package/dist/src/python/components/type-expression/index.js.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.d.ts +12 -0
- package/dist/src/python/components/type-expression/type-expression.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.js +348 -0
- package/dist/src/python/components/type-expression/type-expression.js.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.test.d.ts +2 -0
- package/dist/src/python/components/type-expression/type-expression.test.d.ts.map +1 -0
- package/dist/src/python/components/type-expression/type-expression.test.js +503 -0
- package/dist/src/python/components/type-expression/type-expression.test.js.map +1 -0
- package/dist/src/python/index.d.ts +4 -0
- package/dist/src/python/index.d.ts.map +1 -0
- package/dist/src/python/index.js +4 -0
- package/dist/src/python/index.js.map +1 -0
- package/dist/src/python/lib.d.ts +68 -0
- package/dist/src/python/lib.d.ts.map +1 -0
- package/dist/src/python/lib.js +38 -0
- package/dist/src/python/lib.js.map +1 -0
- package/dist/src/python/test-utils.d.ts +8 -0
- package/dist/src/python/test-utils.d.ts.map +1 -0
- package/dist/src/python/test-utils.js +25 -0
- package/dist/src/python/test-utils.js.map +1 -0
- package/dist/src/python/utils/index.d.ts +4 -0
- package/dist/src/python/utils/index.d.ts.map +1 -0
- package/dist/src/python/utils/index.js +4 -0
- package/dist/src/python/utils/index.js.map +1 -0
- package/dist/src/python/utils/operation.d.ts +27 -0
- package/dist/src/python/utils/operation.d.ts.map +1 -0
- package/dist/src/python/utils/operation.js +139 -0
- package/dist/src/python/utils/operation.js.map +1 -0
- package/dist/src/python/utils/refkey.d.ts +23 -0
- package/dist/src/python/utils/refkey.d.ts.map +1 -0
- package/dist/src/python/utils/refkey.js +36 -0
- package/dist/src/python/utils/refkey.js.map +1 -0
- package/dist/src/python/utils/type.d.ts +19 -0
- package/dist/src/python/utils/type.d.ts.map +1 -0
- package/dist/src/python/utils/type.js +24 -0
- package/dist/src/python/utils/type.js.map +1 -0
- package/package.json +12 -5
- package/package.json.bak +14 -6
- package/src/python/builtins.ts +43 -0
- package/src/python/components/array-expression/array-expression.test.tsx +14 -0
- package/src/python/components/array-expression/array-expression.tsx +11 -0
- package/src/python/components/array-expression/index.ts +1 -0
- package/src/python/components/atom/atom.test.tsx +244 -0
- package/src/python/components/atom/atom.tsx +95 -0
- package/src/python/components/atom/index.ts +1 -0
- package/src/python/components/class-declaration/class-bases.tsx +92 -0
- package/src/python/components/class-declaration/class-body.tsx +56 -0
- package/src/python/components/class-declaration/class-declaration.test.tsx +1414 -0
- package/src/python/components/class-declaration/class-declaration.tsx +116 -0
- package/src/python/components/class-declaration/class-member.test.tsx +194 -0
- package/src/python/components/class-declaration/class-member.tsx +67 -0
- package/src/python/components/class-declaration/class-method.test.tsx +250 -0
- package/src/python/components/class-declaration/class-method.tsx +97 -0
- package/src/python/components/class-declaration/index.ts +6 -0
- package/src/python/components/class-declaration/primitive-initializer.tsx +62 -0
- package/src/python/components/doc-element/doc-element.tsx +83 -0
- package/src/python/components/doc-element/index.ts +1 -0
- package/src/python/components/enum-declaration/enum-declaration.test.tsx +319 -0
- package/src/python/components/enum-declaration/enum-declaration.tsx +77 -0
- package/src/python/components/enum-declaration/enum-member.tsx +21 -0
- package/src/python/components/enum-declaration/index.ts +2 -0
- package/src/python/components/function-declaration/function-declaration.test.tsx +582 -0
- package/src/python/components/function-declaration/function-declaration.tsx +90 -0
- package/src/python/components/function-declaration/index.ts +1 -0
- package/src/python/components/index.ts +11 -0
- package/src/python/components/protocol-declaration/callable-parameters.tsx +44 -0
- package/src/python/components/protocol-declaration/index.ts +2 -0
- package/src/python/components/protocol-declaration/protocol-declaration.test.tsx +106 -0
- package/src/python/components/protocol-declaration/protocol-declaration.tsx +73 -0
- package/src/python/components/record-expression/index.ts +1 -0
- package/src/python/components/record-expression/record-expression.test.tsx +14 -0
- package/src/python/components/record-expression/record-expression.tsx +13 -0
- package/src/python/components/type-alias-declaration/index.ts +1 -0
- package/src/python/components/type-alias-declaration/type-alias-declaration.test.tsx +117 -0
- package/src/python/components/type-alias-declaration/type-alias-declaration.tsx +67 -0
- package/src/python/components/type-declaration/index.ts +1 -0
- package/src/python/components/type-declaration/type-declaration.test.tsx +58 -0
- package/src/python/components/type-declaration/type-declaration.tsx +26 -0
- package/src/python/components/type-expression/index.ts +1 -0
- package/src/python/components/type-expression/type-expression.test.tsx +463 -0
- package/src/python/components/type-expression/type-expression.tsx +333 -0
- package/src/python/index.ts +3 -0
- package/src/python/lib.ts +40 -0
- package/src/python/test-utils.tsx +31 -0
- package/src/python/utils/index.ts +3 -0
- package/src/python/utils/operation.ts +161 -0
- package/src/python/utils/refkey.ts +36 -0
- package/src/python/utils/type.ts +31 -0
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
import { Experimental_OverridableComponent } from "#core/components/index.js";
|
|
2
|
+
import { useTsp } from "#core/context/index.js";
|
|
3
|
+
import { reportPythonDiagnostic } from "#python/lib.js";
|
|
4
|
+
import { code, For, List, mapJoin } from "@alloy-js/core";
|
|
5
|
+
import * as py from "@alloy-js/python";
|
|
6
|
+
import {
|
|
7
|
+
isNeverType,
|
|
8
|
+
type IntrinsicType,
|
|
9
|
+
type Model,
|
|
10
|
+
type Scalar,
|
|
11
|
+
type Type,
|
|
12
|
+
} from "@typespec/compiler";
|
|
13
|
+
import type { TemplateParameterDeclarationNode } from "@typespec/compiler/ast";
|
|
14
|
+
import type { Typekit } from "@typespec/compiler/typekit";
|
|
15
|
+
import { datetimeModule, decimalModule, typingModule } from "../../builtins.js";
|
|
16
|
+
import { efRefkey } from "../../utils/refkey.js";
|
|
17
|
+
import { ArrayExpression } from "../array-expression/array-expression.js";
|
|
18
|
+
import { RecordExpression } from "../record-expression/record-expression.js";
|
|
19
|
+
|
|
20
|
+
export interface TypeExpressionProps {
|
|
21
|
+
type: Type;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Whether to disallow references. Setting this will force the type to be
|
|
25
|
+
* emitted inline, even if it is a declaration that would otherwise be
|
|
26
|
+
* referenced.
|
|
27
|
+
*/
|
|
28
|
+
noReference?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export function TypeExpression(props: TypeExpressionProps) {
|
|
32
|
+
const { $ } = useTsp();
|
|
33
|
+
const type = props.type;
|
|
34
|
+
if (!props.noReference && isDeclaration($, type)) {
|
|
35
|
+
return (
|
|
36
|
+
<Experimental_OverridableComponent reference type={type}>
|
|
37
|
+
<py.Reference refkey={efRefkey(type)} />
|
|
38
|
+
</Experimental_OverridableComponent>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
switch (type.kind) {
|
|
43
|
+
case "Scalar": // Custom types based on primitives (Intrinsics)
|
|
44
|
+
case "Intrinsic": // Language primitives like `string`, `number`, etc.
|
|
45
|
+
if (isNeverType(type)) {
|
|
46
|
+
return typingModule["."]["Never"];
|
|
47
|
+
}
|
|
48
|
+
return <>{getScalarIntrinsicExpression($, type)}</>;
|
|
49
|
+
case "Boolean":
|
|
50
|
+
case "Number":
|
|
51
|
+
case "String":
|
|
52
|
+
// Single literal values are wrapped in Literal[...]
|
|
53
|
+
return (
|
|
54
|
+
<>
|
|
55
|
+
{typingModule["."]["Literal"]}[{formatLiteralValue(type)}]
|
|
56
|
+
</>
|
|
57
|
+
);
|
|
58
|
+
case "Tuple":
|
|
59
|
+
return (
|
|
60
|
+
<>
|
|
61
|
+
tuple[
|
|
62
|
+
<For each={type.values} comma space>
|
|
63
|
+
{(element) => <TypeExpression type={element} />}
|
|
64
|
+
</For>
|
|
65
|
+
]
|
|
66
|
+
</>
|
|
67
|
+
);
|
|
68
|
+
case "Union": {
|
|
69
|
+
const variants = Array.from((type as any).variants?.values?.() ?? []);
|
|
70
|
+
|
|
71
|
+
// Check if all variants are literals or named union variant refs with literal values
|
|
72
|
+
const isLiteralOrVariantRef = (t: Type): boolean => {
|
|
73
|
+
if (!t) return false;
|
|
74
|
+
if (isLiteral($, t)) return true;
|
|
75
|
+
// Named union variant with a literal inner value
|
|
76
|
+
if (t.kind === "UnionVariant" && (t as any).union?.name) {
|
|
77
|
+
return isLiteral($, (t as any).type);
|
|
78
|
+
}
|
|
79
|
+
return false;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
const innerTypes = variants.map((v: any) => v.type);
|
|
83
|
+
if (innerTypes.every(isLiteralOrVariantRef)) {
|
|
84
|
+
// All literals - render as Literal[...]
|
|
85
|
+
const literalValues = variants
|
|
86
|
+
.map((v: any) => {
|
|
87
|
+
const innerType = v.type;
|
|
88
|
+
// Named union variant ref with literal value
|
|
89
|
+
if (innerType.kind === "UnionVariant" && innerType.union?.name) {
|
|
90
|
+
const variantName = String(innerType.name).toUpperCase();
|
|
91
|
+
return code`${efRefkey(innerType.union)}.${variantName}`;
|
|
92
|
+
}
|
|
93
|
+
if (isLiteral($, innerType)) {
|
|
94
|
+
return formatLiteralValue(innerType);
|
|
95
|
+
}
|
|
96
|
+
return undefined;
|
|
97
|
+
})
|
|
98
|
+
.filter(Boolean);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<>
|
|
102
|
+
{typingModule["."]["Literal"]}[<List children={literalValues} joiner=", " />]
|
|
103
|
+
</>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Not all literals - render as union type
|
|
108
|
+
return mapJoin(
|
|
109
|
+
() => variants,
|
|
110
|
+
(v: any) => <TypeExpression type={v.type} />,
|
|
111
|
+
{ joiner: " | " },
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
case "UnionVariant": {
|
|
115
|
+
// Union variant from a named union with a literal value
|
|
116
|
+
if (type.union && (type.union as any).name && isLiteral($, type.type)) {
|
|
117
|
+
// Use the variant's name (e.g., "red", "active"), converted to UPPER_CASE by the enum
|
|
118
|
+
const variantName = String(type.name).toUpperCase();
|
|
119
|
+
return (
|
|
120
|
+
<>
|
|
121
|
+
{typingModule["."]["Literal"]}[{efRefkey(type.union)}.{variantName}]
|
|
122
|
+
</>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
// Unnamed union variant or non-literal value, unwrap to its inner type
|
|
126
|
+
return <TypeExpression type={type.type} />;
|
|
127
|
+
}
|
|
128
|
+
case "ModelProperty":
|
|
129
|
+
return <TypeExpression type={type.type} />;
|
|
130
|
+
case "Model":
|
|
131
|
+
if ($.array.is(type)) {
|
|
132
|
+
const elementType = type.indexer!.value;
|
|
133
|
+
return <ArrayExpression elementType={elementType} />;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if ($.record.is(type)) {
|
|
137
|
+
const elementType = (type as Model).indexer!.value;
|
|
138
|
+
return <RecordExpression elementType={elementType} />;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// TODO: When TypeSpec adds true generics support, handle generic type references here.
|
|
142
|
+
// Currently, TypeSpec templates are macros that expand to concrete types, so template
|
|
143
|
+
// instances (e.g., Response<string>) are treated as regular concrete types, not as
|
|
144
|
+
// parameterized generic types (e.g., Response[str]).
|
|
145
|
+
// When generics are implemented, this is where we would render: ClassName[TypeArg, ...]
|
|
146
|
+
|
|
147
|
+
// Regular named models should be handled as references
|
|
148
|
+
if (type.name) {
|
|
149
|
+
return (
|
|
150
|
+
<Experimental_OverridableComponent reference type={type}>
|
|
151
|
+
<py.Reference refkey={efRefkey(type)} />
|
|
152
|
+
</Experimental_OverridableComponent>
|
|
153
|
+
);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
reportPythonDiagnostic($.program, { code: "python-unsupported-type", target: type });
|
|
157
|
+
return <></>;
|
|
158
|
+
case "TemplateParameter":
|
|
159
|
+
return code`${String((type.node as TemplateParameterDeclarationNode).id.sv)}`;
|
|
160
|
+
|
|
161
|
+
case "Operation": {
|
|
162
|
+
// Render function types as typing.Callable[[ArgTypes...], ReturnType]
|
|
163
|
+
// If parameters cannot be enumerated, fall back to Callable[..., ReturnType]
|
|
164
|
+
let paramTypes: Type[] | null = null;
|
|
165
|
+
const op: any = type as any;
|
|
166
|
+
if (op.parameters) {
|
|
167
|
+
try {
|
|
168
|
+
const { $ } = useTsp();
|
|
169
|
+
const modelProps = $.model.getProperties(op.parameters);
|
|
170
|
+
paramTypes = Array.from(modelProps.values()).map((p: any) => p.type);
|
|
171
|
+
} catch {
|
|
172
|
+
// Unknown/unsupported params shape
|
|
173
|
+
paramTypes = null;
|
|
174
|
+
}
|
|
175
|
+
} else {
|
|
176
|
+
paramTypes = [];
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return (
|
|
180
|
+
<>
|
|
181
|
+
{typingModule["."]["Callable"]}[
|
|
182
|
+
{paramTypes === null ? (
|
|
183
|
+
<>...</>
|
|
184
|
+
) : paramTypes.length > 0 ? (
|
|
185
|
+
<>
|
|
186
|
+
[
|
|
187
|
+
<For each={paramTypes} comma space>
|
|
188
|
+
{(t) => <TypeExpression type={t} />}
|
|
189
|
+
</For>
|
|
190
|
+
]
|
|
191
|
+
</>
|
|
192
|
+
) : (
|
|
193
|
+
<>[]</>
|
|
194
|
+
)}
|
|
195
|
+
{", "}
|
|
196
|
+
<TypeExpression type={(type as any).returnType} />]
|
|
197
|
+
</>
|
|
198
|
+
);
|
|
199
|
+
}
|
|
200
|
+
default:
|
|
201
|
+
reportPythonDiagnostic($.program, { code: "python-unsupported-type", target: type });
|
|
202
|
+
// Return empty fragment - the diagnostic has already been reported
|
|
203
|
+
return <></>;
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Checks if a type is a literal (string, numeric, or boolean).
|
|
209
|
+
*/
|
|
210
|
+
function isLiteral($: Typekit, type: Type): boolean {
|
|
211
|
+
return $.literal.isString(type) || $.literal.isNumeric(type) || $.literal.isBoolean(type);
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Formats a literal type value for use in Python's Literal[...] syntax.
|
|
216
|
+
*/
|
|
217
|
+
function formatLiteralValue(type: { kind: string; value: unknown }): string {
|
|
218
|
+
switch (type.kind) {
|
|
219
|
+
case "String":
|
|
220
|
+
return JSON.stringify(type.value);
|
|
221
|
+
case "Boolean":
|
|
222
|
+
return type.value ? "True" : "False";
|
|
223
|
+
case "Number":
|
|
224
|
+
return String(type.value);
|
|
225
|
+
default:
|
|
226
|
+
return String(type.value);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
const intrinsicNameToPythonType = new Map<string, string | null>([
|
|
231
|
+
// Core types
|
|
232
|
+
["unknown", "Any"], // Matches Python's `Any`
|
|
233
|
+
["string", "str"], // Matches Python's `str`
|
|
234
|
+
["boolean", "bool"], // Matches Python's `bool`
|
|
235
|
+
["null", "None"], // Matches Python's `None`
|
|
236
|
+
["void", "None"], // Matches Python's `None`
|
|
237
|
+
["never", "Never"], // Matches Python's `Never`
|
|
238
|
+
["bytes", "bytes"], // Matches Python's `bytes`
|
|
239
|
+
|
|
240
|
+
// Numeric types
|
|
241
|
+
["numeric", "number"], // Parent type for all numeric types
|
|
242
|
+
["integer", "int"], // Broad integer category, maps to `int`
|
|
243
|
+
["float", "float"], // Broad float category, maps to `float`
|
|
244
|
+
["decimal", "Decimal"], // Broad decimal category, maps to `Decimal`
|
|
245
|
+
["decimal128", "Decimal"], // 128-bit decimal category, maps to `Decimal`
|
|
246
|
+
["int64", "int"], // Use `int` to handle large 64-bit integers
|
|
247
|
+
["int32", "int"], // 32-bit integer fits in Python's `int`
|
|
248
|
+
["int16", "int"], // 16-bit integer
|
|
249
|
+
["int8", "int"], // 8-bit integer
|
|
250
|
+
["safeint", "int"], // Safe integer fits within Python limits
|
|
251
|
+
["uint64", "int"], // Use `int` for unsigned 64-bit integers
|
|
252
|
+
["uint32", "int"], // 32-bit unsigned integer
|
|
253
|
+
["uint16", "int"], // 16-bit unsigned integer
|
|
254
|
+
["uint8", "int"], // 8-bit unsigned integer
|
|
255
|
+
["float32", "float"], // Maps to Python's `float`
|
|
256
|
+
["float64", "float"], // Maps to Python's `float`.
|
|
257
|
+
|
|
258
|
+
// Date and time types
|
|
259
|
+
["plainDate", "str"], // Use `str` for plain calendar dates
|
|
260
|
+
["plainTime", "str"], // Use `str` for plain clock times
|
|
261
|
+
["utcDateTime", "datetime"], // Use `datetime` for UTC date-times
|
|
262
|
+
["offsetDateTime", "str"], // Use `str` for timezone-specific date-times
|
|
263
|
+
["duration", "str"], // Duration as an ISO 8601 string or custom format
|
|
264
|
+
|
|
265
|
+
// String types
|
|
266
|
+
["url", "str"], // Matches Python's `str`
|
|
267
|
+
]);
|
|
268
|
+
|
|
269
|
+
const pythonTypeToImport = new Map<string, any>([
|
|
270
|
+
["Any", typingModule["."]["Any"]],
|
|
271
|
+
["Never", typingModule["."]["Never"]],
|
|
272
|
+
["datetime", datetimeModule["."]["datetime"]],
|
|
273
|
+
["Decimal", decimalModule["."]["Decimal"]],
|
|
274
|
+
]);
|
|
275
|
+
|
|
276
|
+
function getScalarIntrinsicExpression($: Typekit, type: Scalar | IntrinsicType): string | null {
|
|
277
|
+
let intrinsicName: string;
|
|
278
|
+
if ($.scalar.is(type)) {
|
|
279
|
+
if ($.scalar.isUtcDateTime(type) || $.scalar.extendsUtcDateTime(type)) {
|
|
280
|
+
const encoding = $.scalar.getEncoding(type);
|
|
281
|
+
intrinsicName = "utcDateTime";
|
|
282
|
+
switch (encoding?.encoding) {
|
|
283
|
+
case "unixTimestamp":
|
|
284
|
+
case "rfc7231":
|
|
285
|
+
case "rfc3339":
|
|
286
|
+
default:
|
|
287
|
+
intrinsicName = `utcDateTime`;
|
|
288
|
+
break;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
intrinsicName = $.scalar.getStdBase(type)?.name ?? "";
|
|
292
|
+
} else {
|
|
293
|
+
intrinsicName = type.name;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
let pythonType = intrinsicNameToPythonType.get(intrinsicName);
|
|
297
|
+
const importModule = pythonTypeToImport.get(pythonType ?? "");
|
|
298
|
+
pythonType = importModule ? importModule : pythonType;
|
|
299
|
+
|
|
300
|
+
if (!pythonType) {
|
|
301
|
+
reportPythonDiagnostic($.program, { code: "python-unsupported-scalar", target: type });
|
|
302
|
+
return "any";
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
return pythonType;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
// TODO: When TypeSpec adds true generics support, add helper to detect generic type instances.
|
|
309
|
+
// Currently, TypeSpec templates expand to concrete types at compile time, so we treat all
|
|
310
|
+
// template instances as regular concrete types.
|
|
311
|
+
|
|
312
|
+
function isDeclaration($: Typekit, type: Type): boolean {
|
|
313
|
+
switch (type.kind) {
|
|
314
|
+
case "Namespace":
|
|
315
|
+
case "Interface":
|
|
316
|
+
case "Enum":
|
|
317
|
+
case "Operation":
|
|
318
|
+
case "EnumMember":
|
|
319
|
+
case "UnionVariant":
|
|
320
|
+
return false;
|
|
321
|
+
|
|
322
|
+
case "Model":
|
|
323
|
+
if ($.array.is(type) || $.record.is(type)) {
|
|
324
|
+
return false;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
return Boolean(type.name);
|
|
328
|
+
case "Union":
|
|
329
|
+
return Boolean(type.name);
|
|
330
|
+
default:
|
|
331
|
+
return false;
|
|
332
|
+
}
|
|
333
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createTypeSpecLibrary } from "@typespec/compiler";
|
|
2
|
+
|
|
3
|
+
export const $pythonLib = createTypeSpecLibrary({
|
|
4
|
+
name: "emitter-framework",
|
|
5
|
+
diagnostics: {
|
|
6
|
+
"python-unsupported-scalar": {
|
|
7
|
+
severity: "warning",
|
|
8
|
+
messages: {
|
|
9
|
+
default: "Unsupported scalar type, falling back to Any",
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
"python-unsupported-type": {
|
|
13
|
+
severity: "error",
|
|
14
|
+
messages: {
|
|
15
|
+
default: "Unsupported type, falling back to Any",
|
|
16
|
+
},
|
|
17
|
+
description: "This type is not supported by the Python emitter",
|
|
18
|
+
},
|
|
19
|
+
"python-unsupported-model-discriminator": {
|
|
20
|
+
severity: "error",
|
|
21
|
+
messages: {
|
|
22
|
+
default:
|
|
23
|
+
"Unsupported model discriminator, falling back to not discriminating on serialization/deserialization",
|
|
24
|
+
},
|
|
25
|
+
description: "Discriminators at the model are not supported",
|
|
26
|
+
},
|
|
27
|
+
"python-unsupported-type-transform": {
|
|
28
|
+
severity: "error",
|
|
29
|
+
messages: {
|
|
30
|
+
default: "Unsupported type for transformation, falling back to not transforming this type",
|
|
31
|
+
},
|
|
32
|
+
description: "This type cannot be transformed",
|
|
33
|
+
},
|
|
34
|
+
},
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export const {
|
|
38
|
+
reportDiagnostic: reportPythonDiagnostic,
|
|
39
|
+
createDiagnostic: createPythonDiagnostic,
|
|
40
|
+
} = $pythonLib;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Output } from "#core/components/index.js";
|
|
2
|
+
import { type Children } from "@alloy-js/core";
|
|
3
|
+
import * as py from "@alloy-js/python";
|
|
4
|
+
import type { Program } from "@typespec/compiler";
|
|
5
|
+
import { abcModule, datetimeModule, decimalModule, typingModule } from "./builtins.js";
|
|
6
|
+
|
|
7
|
+
export const renderOptions = {
|
|
8
|
+
printWidth: 80,
|
|
9
|
+
tabWidth: 4,
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
export function getOutput(program: Program, children: Children[]): Children {
|
|
13
|
+
const policy = py.createPythonNamePolicy();
|
|
14
|
+
return (
|
|
15
|
+
<Output
|
|
16
|
+
program={program}
|
|
17
|
+
externals={[
|
|
18
|
+
abcModule,
|
|
19
|
+
datetimeModule,
|
|
20
|
+
decimalModule,
|
|
21
|
+
typingModule,
|
|
22
|
+
py.abcModule,
|
|
23
|
+
py.dataclassesModule,
|
|
24
|
+
py.enumModule,
|
|
25
|
+
]}
|
|
26
|
+
namePolicy={policy}
|
|
27
|
+
>
|
|
28
|
+
<py.SourceFile path="test.py">{children}</py.SourceFile>
|
|
29
|
+
</Output>
|
|
30
|
+
);
|
|
31
|
+
}
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { typingModule } from "#python/builtins.js";
|
|
2
|
+
import { refkey, type Children, type Refkey } from "@alloy-js/core";
|
|
3
|
+
import * as py from "@alloy-js/python";
|
|
4
|
+
import type { Model, ModelProperty, Operation, Type } from "@typespec/compiler";
|
|
5
|
+
import { useTsp } from "../../core/index.js";
|
|
6
|
+
import { Atom } from "../components/atom/atom.js";
|
|
7
|
+
import { TypeExpression } from "../components/type-expression/type-expression.js";
|
|
8
|
+
import { efRefkey } from "./refkey.js";
|
|
9
|
+
|
|
10
|
+
export function getReturnType(
|
|
11
|
+
type: Operation,
|
|
12
|
+
options: { skipErrorFiltering: boolean } = { skipErrorFiltering: false },
|
|
13
|
+
): Type {
|
|
14
|
+
const { $ } = useTsp();
|
|
15
|
+
let returnType = type.returnType;
|
|
16
|
+
|
|
17
|
+
if (!options.skipErrorFiltering && type.returnType.kind === "Union") {
|
|
18
|
+
returnType = $.union.filter(type.returnType, (variant) => !$.type.isError(variant.type));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return returnType;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export interface BuildParameterDescriptorsOptions {
|
|
25
|
+
params?: (py.ParameterDescriptor | string)[];
|
|
26
|
+
suffixRefkey?: Refkey;
|
|
27
|
+
/** If true, params replaces operation parameters instead of adding to them */
|
|
28
|
+
replaceParameters?: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Build a parameter descriptor array from a TypeSpec Model.
|
|
33
|
+
*
|
|
34
|
+
* Parameter ordering (unless replaceParameters is true):
|
|
35
|
+
* - Operation params without defaults: positional (e.g., URL path params)
|
|
36
|
+
* - "*" marker (if any keyword-only params exist)
|
|
37
|
+
* - Operation params with defaults: keyword-only (e.g., query params)
|
|
38
|
+
* - Additional params: keyword-only
|
|
39
|
+
*/
|
|
40
|
+
export function buildParameterDescriptors(
|
|
41
|
+
type: Model,
|
|
42
|
+
options: BuildParameterDescriptorsOptions = {},
|
|
43
|
+
): (py.ParameterDescriptor | string)[] | undefined {
|
|
44
|
+
const { $ } = useTsp();
|
|
45
|
+
const suffixRefkey = options.suffixRefkey ?? refkey();
|
|
46
|
+
const optionsParams: py.ParameterDescriptor[] = normalizeParameters(options.params ?? []);
|
|
47
|
+
|
|
48
|
+
// If replaceParameters is true, ignore operation params and just return options params
|
|
49
|
+
// All replacement parameters are keyword-only (following "additional parameters are keyword-only" principle)
|
|
50
|
+
if (options.replaceParameters) {
|
|
51
|
+
const withoutDefaults = optionsParams.filter((p) => p.default === undefined);
|
|
52
|
+
const withDefaults = optionsParams.filter((p) => p.default !== undefined);
|
|
53
|
+
|
|
54
|
+
// Always add "*" marker since all replacement params should be keyword-only
|
|
55
|
+
const allParams: (py.ParameterDescriptor | string)[] =
|
|
56
|
+
optionsParams.length > 0 ? ["*", ...withoutDefaults, ...withDefaults] : [];
|
|
57
|
+
|
|
58
|
+
return allParams;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
const modelProperties = $.model.getProperties(type);
|
|
62
|
+
const operationParams: py.ParameterDescriptor[] = [...modelProperties.values()].map((m) =>
|
|
63
|
+
buildParameterDescriptor(m, suffixRefkey),
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
// Split operation params: params without defaults are positional, params with defaults are keyword-only
|
|
67
|
+
const opParamsWithoutDefaults = operationParams.filter((p) => p.default === undefined);
|
|
68
|
+
const opParamsWithDefaults = operationParams.filter((p) => p.default !== undefined);
|
|
69
|
+
|
|
70
|
+
// Reorder additional params: params without defaults before params with defaults
|
|
71
|
+
const optionsWithoutDefaults = optionsParams.filter((p) => p.default === undefined);
|
|
72
|
+
const optionsWithDefaults = optionsParams.filter((p) => p.default !== undefined);
|
|
73
|
+
|
|
74
|
+
// Build final parameter list:
|
|
75
|
+
// - Operation params without defaults: positional (e.g., URL path params)
|
|
76
|
+
// - "*" marker (if there are keyword-only params)
|
|
77
|
+
// - Operation params with defaults: keyword-only (e.g., query params with defaults)
|
|
78
|
+
// - Additional params: keyword-only
|
|
79
|
+
|
|
80
|
+
// If there are no operation params at all, treat additional params without defaults as positional
|
|
81
|
+
const hasOperationParams = operationParams.length > 0;
|
|
82
|
+
|
|
83
|
+
const positionalParams = hasOperationParams
|
|
84
|
+
? opParamsWithoutDefaults
|
|
85
|
+
: [...opParamsWithoutDefaults, ...optionsWithoutDefaults];
|
|
86
|
+
|
|
87
|
+
const keywordOnlyParams = hasOperationParams
|
|
88
|
+
? [...optionsWithoutDefaults, ...opParamsWithDefaults, ...optionsWithDefaults]
|
|
89
|
+
: [...opParamsWithDefaults, ...optionsWithDefaults];
|
|
90
|
+
|
|
91
|
+
// Add "*" marker if we have keyword-only params
|
|
92
|
+
// This enforces that params with defaults are truly keyword-only
|
|
93
|
+
const allParams: (py.ParameterDescriptor | string)[] =
|
|
94
|
+
keywordOnlyParams.length > 0
|
|
95
|
+
? [...positionalParams, "*", ...keywordOnlyParams]
|
|
96
|
+
: [...positionalParams];
|
|
97
|
+
|
|
98
|
+
return allParams;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Convert a TypeSpec ModelProperty into a Python ParameterDescriptor.
|
|
103
|
+
*/
|
|
104
|
+
export function buildParameterDescriptor(
|
|
105
|
+
modelProperty: ModelProperty,
|
|
106
|
+
suffixRefkey: Refkey,
|
|
107
|
+
): py.ParameterDescriptor {
|
|
108
|
+
const { $ } = useTsp();
|
|
109
|
+
const namePolicy = py.usePythonNamePolicy();
|
|
110
|
+
const paramName = namePolicy.getName(modelProperty.name, "parameter");
|
|
111
|
+
const isOptional = modelProperty.optional || modelProperty.defaultValue !== undefined;
|
|
112
|
+
const doc = $.type.getDoc(modelProperty);
|
|
113
|
+
let defaultValueNode: Children | undefined = undefined;
|
|
114
|
+
const hasDefault =
|
|
115
|
+
modelProperty.defaultValue !== undefined && modelProperty.defaultValue !== null;
|
|
116
|
+
if (hasDefault) {
|
|
117
|
+
defaultValueNode = Atom({ value: (modelProperty as any).defaultValue });
|
|
118
|
+
} else if (isOptional) {
|
|
119
|
+
// Render Python None for optional parameters without explicit default
|
|
120
|
+
defaultValueNode = py.Atom({ jsValue: null }) as any;
|
|
121
|
+
}
|
|
122
|
+
return {
|
|
123
|
+
doc,
|
|
124
|
+
name: paramName,
|
|
125
|
+
refkey: efRefkey(modelProperty, suffixRefkey),
|
|
126
|
+
type: TypeExpression({ type: modelProperty.type }),
|
|
127
|
+
...(defaultValueNode !== undefined ? { default: defaultValueNode } : {}),
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const rawTypeMap = {
|
|
132
|
+
string: "str",
|
|
133
|
+
number: "float",
|
|
134
|
+
boolean: "bool",
|
|
135
|
+
any: typingModule["."]["Any"],
|
|
136
|
+
never: typingModule["."]["Never"],
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* Convert a parameter descriptor array to normalized parameter descriptors.
|
|
141
|
+
* String parameter names are converted to basic parameter descriptors.
|
|
142
|
+
*/
|
|
143
|
+
function normalizeParameters(
|
|
144
|
+
params: (py.ParameterDescriptor | string)[],
|
|
145
|
+
): py.ParameterDescriptor[] {
|
|
146
|
+
if (!params) return [];
|
|
147
|
+
|
|
148
|
+
return params.map((param) => {
|
|
149
|
+
if (typeof param === "string") {
|
|
150
|
+
// Convert string names to parameter descriptors
|
|
151
|
+
return { name: param };
|
|
152
|
+
}
|
|
153
|
+
if (typeof (param as any).type === "string") {
|
|
154
|
+
return {
|
|
155
|
+
...param,
|
|
156
|
+
type: rawTypeMap[param.type as keyof typeof rawTypeMap] ?? param.type,
|
|
157
|
+
} as py.ParameterDescriptor;
|
|
158
|
+
}
|
|
159
|
+
return param;
|
|
160
|
+
});
|
|
161
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { refkey as ayRefkey, type Refkey } from "@alloy-js/core";
|
|
2
|
+
|
|
3
|
+
const refKeyPrefix = Symbol.for("emitter-framework:python");
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* A wrapper around `refkey` that uses a custom symbol to avoid collisions with
|
|
7
|
+
* other libraries that use `refkey`.
|
|
8
|
+
*
|
|
9
|
+
* @remarks
|
|
10
|
+
*
|
|
11
|
+
* The underlying refkey function is called with the {@link refKeyPrefix} symbol as the first argument.
|
|
12
|
+
*
|
|
13
|
+
* @param args The parameters of the refkey.
|
|
14
|
+
* @returns A refkey object that can be used to identify the value.
|
|
15
|
+
*/
|
|
16
|
+
export function efRefkey(...args: unknown[]): Refkey {
|
|
17
|
+
if (args.length === 0) {
|
|
18
|
+
return ayRefkey(); // Generates a unique refkey
|
|
19
|
+
}
|
|
20
|
+
return ayRefkey(refKeyPrefix, ...args);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Creates a refkey for a declaration by combining the provided refkey with an internal
|
|
25
|
+
* refkey generated from the provided arguments.
|
|
26
|
+
*
|
|
27
|
+
* @param refkey The refkey provided by the user to be passed as is.
|
|
28
|
+
* @param args The parameters of the refkey.
|
|
29
|
+
* @returns An array of refkeys that can be passed to an Alloy declaration.
|
|
30
|
+
*/
|
|
31
|
+
export function declarationRefkeys(refkey?: Refkey | Refkey[], ...args: unknown[]): Refkey[] {
|
|
32
|
+
if (refkey) {
|
|
33
|
+
return [refkey, efRefkey(...args)].flat();
|
|
34
|
+
}
|
|
35
|
+
return [efRefkey(...args)];
|
|
36
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { Typekit } from "@typespec/compiler/typekit";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Check if a type is a literal type (string, numeric, boolean, or union variant).
|
|
5
|
+
* This is useful for determining if a type can be used in a Python Literal[] type.
|
|
6
|
+
*
|
|
7
|
+
* @param $ - The Typekit instance
|
|
8
|
+
* @param type - The type to check
|
|
9
|
+
* @returns true if the type is a literal type
|
|
10
|
+
*/
|
|
11
|
+
export function isLiteral($: Typekit, type: any): boolean {
|
|
12
|
+
if (!type) return false;
|
|
13
|
+
|
|
14
|
+
return (
|
|
15
|
+
$.literal.isString(type) ||
|
|
16
|
+
$.literal.isNumeric(type) ||
|
|
17
|
+
$.literal.isBoolean(type) ||
|
|
18
|
+
type.kind === "UnionVariant"
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Check if all types in an array are literal types.
|
|
24
|
+
*
|
|
25
|
+
* @param $ - The Typekit instance
|
|
26
|
+
* @param types - Array of types to check
|
|
27
|
+
* @returns true if all types are literals
|
|
28
|
+
*/
|
|
29
|
+
export function areAllLiterals($: Typekit, types: any[]): boolean {
|
|
30
|
+
return types.every((type) => isLiteral($, type));
|
|
31
|
+
}
|