@typespec/emitter-framework 0.9.0-dev.0 → 0.9.0-dev.10

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.
Files changed (192) hide show
  1. package/dist/src/core/components/output.d.ts +4 -4
  2. package/dist/src/core/components/output.d.ts.map +1 -1
  3. package/dist/src/core/components/output.js +3 -3
  4. package/dist/src/core/context/name-policy-context.d.ts +2 -2
  5. package/dist/src/core/context/name-policy-context.d.ts.map +1 -1
  6. package/dist/src/core/context/tsp-context.d.ts +2 -2
  7. package/dist/src/core/context/tsp-context.d.ts.map +1 -1
  8. package/dist/src/core/transport-name-policy.d.ts +1 -1
  9. package/dist/src/core/transport-name-policy.d.ts.map +1 -1
  10. package/dist/src/core/write-output.d.ts +2 -2
  11. package/dist/src/core/write-output.d.ts.map +1 -1
  12. package/dist/src/csharp/components/class/declaration.d.ts +13 -0
  13. package/dist/src/csharp/components/class/declaration.d.ts.map +1 -0
  14. package/dist/src/csharp/components/class/declaration.js +91 -0
  15. package/dist/src/csharp/components/class/declaration.test.d.ts +2 -0
  16. package/dist/src/csharp/components/class/declaration.test.d.ts.map +1 -0
  17. package/dist/src/csharp/components/class/declaration.test.js +377 -0
  18. package/dist/src/csharp/components/enum/declaration.d.ts +9 -0
  19. package/dist/src/csharp/components/enum/declaration.d.ts.map +1 -0
  20. package/dist/src/csharp/components/enum/declaration.js +55 -0
  21. package/dist/src/csharp/components/enum/declaration.test.d.ts +2 -0
  22. package/dist/src/csharp/components/enum/declaration.test.d.ts.map +1 -0
  23. package/dist/src/csharp/components/enum/declaration.test.js +309 -0
  24. package/dist/src/csharp/components/index.d.ts +5 -0
  25. package/dist/src/csharp/components/index.d.ts.map +1 -0
  26. package/dist/src/csharp/components/index.js +4 -0
  27. package/dist/src/csharp/components/property/property.d.ts +15 -0
  28. package/dist/src/csharp/components/property/property.d.ts.map +1 -0
  29. package/dist/src/csharp/components/property/property.js +85 -0
  30. package/dist/src/csharp/components/property/property.test.d.ts +2 -0
  31. package/dist/src/csharp/components/property/property.test.d.ts.map +1 -0
  32. package/dist/src/csharp/components/property/property.test.js +117 -0
  33. package/dist/src/csharp/components/type-expression.d.ts +11 -0
  34. package/dist/src/csharp/components/type-expression.d.ts.map +1 -0
  35. package/dist/src/csharp/components/type-expression.js +143 -0
  36. package/dist/src/csharp/components/type-expression.test.d.ts +2 -0
  37. package/dist/src/csharp/components/type-expression.test.d.ts.map +1 -0
  38. package/dist/src/csharp/components/type-expression.test.js +128 -0
  39. package/dist/src/csharp/components/utils/doc-comments.d.ts +14 -0
  40. package/dist/src/csharp/components/utils/doc-comments.d.ts.map +1 -0
  41. package/dist/src/csharp/components/utils/doc-comments.js +67 -0
  42. package/dist/src/csharp/components/utils/refkey.d.ts +23 -0
  43. package/dist/src/csharp/components/utils/refkey.d.ts.map +1 -0
  44. package/dist/src/csharp/components/utils/refkey.js +35 -0
  45. package/dist/src/csharp/index.d.ts +2 -0
  46. package/dist/src/csharp/index.d.ts.map +1 -0
  47. package/dist/src/csharp/index.js +1 -0
  48. package/dist/src/testing/index.d.ts +1 -1
  49. package/dist/src/testing/index.d.ts.map +1 -1
  50. package/dist/src/testing/scenario-test/code-block-expectation.d.ts +33 -0
  51. package/dist/src/testing/scenario-test/code-block-expectation.d.ts.map +1 -0
  52. package/dist/src/testing/scenario-test/code-block-expectation.js +69 -0
  53. package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts +2 -0
  54. package/dist/src/testing/scenario-test/code-block-expectation.test.d.ts.map +1 -0
  55. package/dist/src/testing/scenario-test/code-block-expectation.test.js +80 -0
  56. package/dist/src/testing/scenario-test/harness.d.ts +3 -3
  57. package/dist/src/testing/scenario-test/harness.d.ts.map +1 -1
  58. package/dist/src/testing/scenario-test/harness.js +69 -158
  59. package/dist/src/testing/scenario-test/index.d.ts +0 -1
  60. package/dist/src/testing/scenario-test/index.d.ts.map +1 -1
  61. package/dist/src/testing/scenario-test/index.js +1 -2
  62. package/dist/src/testing/scenario-test/snippet-extractor.d.ts +1 -1
  63. package/dist/src/testing/scenario-test/snippet-extractor.js +1 -1
  64. package/dist/src/typescript/components/array-expression.d.ts +2 -3
  65. package/dist/src/typescript/components/array-expression.d.ts.map +1 -1
  66. package/dist/src/typescript/components/array-expression.js +2 -2
  67. package/dist/src/typescript/components/arrow-function.d.ts +2 -2
  68. package/dist/src/typescript/components/arrow-function.d.ts.map +1 -1
  69. package/dist/src/typescript/components/arrow-function.js +2 -1
  70. package/dist/src/typescript/components/class-method.d.ts +1 -1
  71. package/dist/src/typescript/components/class-method.d.ts.map +1 -1
  72. package/dist/src/typescript/components/enum-declaration.d.ts +6 -6
  73. package/dist/src/typescript/components/enum-declaration.d.ts.map +1 -1
  74. package/dist/src/typescript/components/enum-declaration.js +2 -2
  75. package/dist/src/typescript/components/function-declaration.d.ts +1 -1
  76. package/dist/src/typescript/components/function-declaration.d.ts.map +1 -1
  77. package/dist/src/typescript/components/function-expression.d.ts +2 -2
  78. package/dist/src/typescript/components/function-expression.d.ts.map +1 -1
  79. package/dist/src/typescript/components/function-expression.js +2 -1
  80. package/dist/src/typescript/components/function-type.d.ts +2 -2
  81. package/dist/src/typescript/components/function-type.d.ts.map +1 -1
  82. package/dist/src/typescript/components/function-type.js +2 -1
  83. package/dist/src/typescript/components/interface-declaration.d.ts +4 -4
  84. package/dist/src/typescript/components/interface-declaration.d.ts.map +1 -1
  85. package/dist/src/typescript/components/interface-declaration.js +3 -4
  86. package/dist/src/typescript/components/interface-member.d.ts +2 -2
  87. package/dist/src/typescript/components/interface-member.d.ts.map +1 -1
  88. package/dist/src/typescript/components/interface-method.d.ts +2 -2
  89. package/dist/src/typescript/components/interface-method.d.ts.map +1 -1
  90. package/dist/src/typescript/components/record-expression.d.ts +1 -1
  91. package/dist/src/typescript/components/record-expression.d.ts.map +1 -1
  92. package/dist/src/typescript/components/type-alias-declaration.d.ts +1 -1
  93. package/dist/src/typescript/components/type-alias-declaration.d.ts.map +1 -1
  94. package/dist/src/typescript/components/type-declaration.d.ts +1 -1
  95. package/dist/src/typescript/components/type-declaration.d.ts.map +1 -1
  96. package/dist/src/typescript/components/type-expression.d.ts +1 -1
  97. package/dist/src/typescript/components/type-expression.d.ts.map +1 -1
  98. package/dist/src/typescript/components/type-transform.d.ts +2 -2
  99. package/dist/src/typescript/components/type-transform.d.ts.map +1 -1
  100. package/dist/src/typescript/components/union-declaration.d.ts +2 -2
  101. package/dist/src/typescript/components/union-declaration.d.ts.map +1 -1
  102. package/dist/src/typescript/components/union-expression.d.ts +3 -4
  103. package/dist/src/typescript/components/union-expression.d.ts.map +1 -1
  104. package/dist/src/typescript/components/union-expression.js +3 -3
  105. package/dist/src/typescript/components/value-expression.d.ts +2 -2
  106. package/dist/src/typescript/components/value-expression.d.ts.map +1 -1
  107. package/dist/src/typescript/utils/operation.d.ts +2 -2
  108. package/dist/src/typescript/utils/operation.d.ts.map +1 -1
  109. package/dist/test/test-host.d.ts +2 -0
  110. package/dist/test/test-host.d.ts.map +1 -0
  111. package/dist/test/test-host.js +5 -0
  112. package/dist/test/testing/snippet-extractor-csharp.test.js +3 -3
  113. package/dist/test/testing/snippet-extractor-java.test.js +3 -3
  114. package/dist/test/testing/snippet-extractor-python.test.js +2 -2
  115. package/dist/test/testing/snippet-extractor-typescript.test.js +3 -3
  116. package/dist/test/typescript/components/member-expression.test.js +5 -5
  117. package/dist/test/typescript/test-host.d.ts +1 -1
  118. package/dist/test/typescript/test-host.d.ts.map +1 -1
  119. package/dist/test/utils.d.ts +2 -2
  120. package/dist/test/utils.d.ts.map +1 -1
  121. package/dist/test/vitest.setup.d.ts +2 -0
  122. package/dist/test/vitest.setup.d.ts.map +1 -0
  123. package/dist/test/vitest.setup.js +1 -0
  124. package/package.json +30 -8
  125. package/src/core/components/output.tsx +9 -5
  126. package/src/core/context/name-policy-context.ts +2 -2
  127. package/src/core/context/tsp-context.ts +2 -2
  128. package/src/core/transport-name-policy.ts +1 -1
  129. package/src/core/write-output.ts +2 -2
  130. package/src/csharp/components/class/declaration.test.tsx +339 -0
  131. package/src/csharp/components/class/declaration.tsx +86 -0
  132. package/src/csharp/components/enum/declaration.test.tsx +267 -0
  133. package/src/csharp/components/enum/declaration.tsx +56 -0
  134. package/src/csharp/components/index.ts +4 -0
  135. package/src/csharp/components/property/property.test.tsx +97 -0
  136. package/src/csharp/components/property/property.tsx +62 -0
  137. package/src/csharp/components/type-expression.test.tsx +133 -0
  138. package/src/csharp/components/type-expression.tsx +119 -0
  139. package/src/csharp/components/utils/doc-comments.tsx +58 -0
  140. package/src/csharp/components/utils/refkey.ts +36 -0
  141. package/src/csharp/index.ts +1 -0
  142. package/src/testing/index.ts +1 -1
  143. package/src/testing/scenario-test/code-block-expectation.test.ts +95 -0
  144. package/src/testing/scenario-test/code-block-expectation.ts +115 -0
  145. package/src/testing/scenario-test/harness.ts +92 -237
  146. package/src/testing/scenario-test/index.ts +0 -1
  147. package/src/testing/scenario-test/snippet-extractor.ts +1 -1
  148. package/src/typescript/components/array-expression.tsx +3 -3
  149. package/src/typescript/components/arrow-function.tsx +2 -2
  150. package/src/typescript/components/class-method.tsx +1 -1
  151. package/src/typescript/components/enum-declaration.tsx +6 -6
  152. package/src/typescript/components/function-declaration.tsx +1 -1
  153. package/src/typescript/components/function-expression.tsx +2 -2
  154. package/src/typescript/components/function-type.tsx +2 -2
  155. package/src/typescript/components/interface-declaration.tsx +11 -12
  156. package/src/typescript/components/interface-member.tsx +2 -2
  157. package/src/typescript/components/interface-method.tsx +2 -2
  158. package/src/typescript/components/record-expression.tsx +1 -1
  159. package/src/typescript/components/type-alias-declaration.tsx +1 -1
  160. package/src/typescript/components/type-declaration.tsx +1 -1
  161. package/src/typescript/components/type-expression.tsx +2 -2
  162. package/src/typescript/components/type-transform.tsx +3 -3
  163. package/src/typescript/components/union-declaration.tsx +2 -2
  164. package/src/typescript/components/union-expression.tsx +12 -7
  165. package/src/typescript/components/value-expression.tsx +2 -2
  166. package/src/typescript/utils/operation.ts +2 -2
  167. package/test/test-host.ts +4 -0
  168. package/test/testing/snippet-extractor-csharp.test.ts +4 -4
  169. package/test/testing/snippet-extractor-java.test.ts +4 -4
  170. package/test/testing/snippet-extractor-python.test.ts +3 -3
  171. package/test/testing/snippet-extractor-typescript.test.ts +4 -4
  172. package/test/typescript/components/arrow-function.test.tsx +2 -2
  173. package/test/typescript/components/enum-declaration.test.tsx +1 -1
  174. package/test/typescript/components/function-declaration.test.tsx +1 -1
  175. package/test/typescript/components/function-expression.test.tsx +2 -2
  176. package/test/typescript/components/function-type.test.tsx +2 -2
  177. package/test/typescript/components/interface-declaration.test.tsx +1 -1
  178. package/test/typescript/components/interface-method.test.tsx +2 -2
  179. package/test/typescript/components/member-expression.test.tsx +10 -10
  180. package/test/typescript/components/type-alias-declaration.test.tsx +1 -1
  181. package/test/typescript/components/type-transform.test.tsx +2 -2
  182. package/test/typescript/components/union-declaration.test.tsx +2 -2
  183. package/test/typescript/components/value-expression.test.tsx +6 -6
  184. package/test/typescript/test-host.ts +1 -1
  185. package/test/utils.ts +2 -2
  186. package/test/vitest.setup.ts +1 -0
  187. package/tsconfig.json +3 -1
  188. package/vitest.config.ts +2 -1
  189. package/dist/src/testing/scenario-test/test-host.d.ts +0 -8
  190. package/dist/src/testing/scenario-test/test-host.d.ts.map +0 -1
  191. package/dist/src/testing/scenario-test/test-host.js +0 -49
  192. package/src/testing/scenario-test/test-host.ts +0 -83
@@ -0,0 +1,143 @@
1
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
+ import { code } from "@alloy-js/core";
3
+ import { Reference } from "@alloy-js/csharp";
4
+ import { getTypeName } from "@typespec/compiler";
5
+ import { useTsp } from "../../core/index.js";
6
+ import { reportTypescriptDiagnostic } from "../../typescript/lib.js";
7
+ import { efRefkey } from "./utils/refkey.js";
8
+ export function TypeExpression(props) {
9
+ const {
10
+ $
11
+ } = useTsp();
12
+ if (isDeclaration($, props.type)) {
13
+ return _$createComponent(Reference, {
14
+ get refkey() {
15
+ return efRefkey(props.type);
16
+ }
17
+ });
18
+ }
19
+ if ($.scalar.is(props.type)) {
20
+ return getScalarIntrinsicExpression($, props.type);
21
+ } else if ($.array.is(props.type)) {
22
+ return code`${_$createComponent(TypeExpression, {
23
+ get type() {
24
+ return props.type.indexer.value;
25
+ }
26
+ })}[]`;
27
+ } else if ($.record.is(props.type)) {
28
+ return code`IDictionary<string, ${_$createComponent(TypeExpression, {
29
+ get type() {
30
+ return props.type.indexer.value;
31
+ }
32
+ })}>`;
33
+ }
34
+ throw new Error(`Unsupported type for TypeExpression: ${props.type.kind} (${getTypeName(props.type)})`);
35
+ }
36
+ const intrinsicNameToCSharpType = new Map([
37
+ // Core types
38
+ ["unknown", "object"],
39
+ // Matches C#'s `object`
40
+ ["string", "string"],
41
+ // Matches C#'s `string`
42
+ ["boolean", "bool"],
43
+ // Matches C#'s `bool`
44
+ ["null", "null"],
45
+ // Matches C#'s `null`
46
+ ["void", "void"],
47
+ // Matches C#'s `void`
48
+ ["never", null],
49
+ // No direct equivalent in C#
50
+ ["bytes", "byte[]"],
51
+ // Matches C#'s `byte[]`
52
+
53
+ // Numeric types
54
+ ["numeric", "decimal"],
55
+ // Parent type for all numeric types, use most precise
56
+ ["integer", "int"],
57
+ // Broad integer category, maps to `int`
58
+ ["float", "float"],
59
+ // Broad float category, maps to `float`
60
+ ["decimal", "decimal"],
61
+ // Broad decimal category, maps to `decimal`
62
+ ["decimal128", "decimal"],
63
+ // C#'s decimal is 128-bit
64
+ ["int64", "long"],
65
+ // 64-bit signed integer
66
+ ["int32", "int"],
67
+ // 32-bit signed integer
68
+ ["int16", "short"],
69
+ // 16-bit signed integer
70
+ ["int8", "sbyte"],
71
+ // 8-bit signed integer
72
+ ["safeint", "int"],
73
+ // Safe integer, use int as default
74
+ ["uint64", "ulong"],
75
+ // 64-bit unsigned integer
76
+ ["uint32", "uint"],
77
+ // 32-bit unsigned integer
78
+ ["uint16", "ushort"],
79
+ // 16-bit unsigned integer
80
+ ["uint8", "byte"],
81
+ // 8-bit unsigned integer
82
+ ["float32", "float"],
83
+ // 32-bit floating point
84
+ ["float64", "double"],
85
+ // 64-bit floating point
86
+
87
+ // Date and time types
88
+ ["plainDate", "DateOnly"],
89
+ // Use .NET 6+ DateOnly for plain calendar dates
90
+ ["plainTime", "TimeOnly"],
91
+ // Use .NET 6+ TimeOnly for plain clock times
92
+ ["utcDateTime", "DateTimeOffset"],
93
+ // Use DateTimeOffset for UTC date-times
94
+ ["offsetDateTime", "DateTimeOffset"],
95
+ // Use DateTimeOffset for timezone-specific date-times
96
+ ["duration", "TimeSpan"],
97
+ // Duration as TimeSpan
98
+
99
+ // String types
100
+ ["url", "Uri"] // Matches C#'s `Uri`
101
+ ]);
102
+ export function getScalarIntrinsicExpression($, type) {
103
+ let intrinsicName;
104
+ if ($.scalar.isUtcDateTime(type) || $.scalar.extendsUtcDateTime(type)) {
105
+ return "DateTimeOffset";
106
+ }
107
+ if ($.scalar.is(type)) {
108
+ intrinsicName = $.scalar.getStdBase(type)?.name ?? "";
109
+ } else {
110
+ intrinsicName = type.name;
111
+ }
112
+ const csType = intrinsicNameToCSharpType.get(intrinsicName);
113
+ if (!csType) {
114
+ reportTypescriptDiagnostic($.program, {
115
+ code: "typescript-unsupported-scalar",
116
+ target: type
117
+ });
118
+ return "object"; // Fallback to object if unsupported
119
+ }
120
+ return csType;
121
+ }
122
+ function isDeclaration($, type) {
123
+ switch (type.kind) {
124
+ case "Namespace":
125
+ case "Interface":
126
+ case "Enum":
127
+ case "Operation":
128
+ case "EnumMember":
129
+ return true;
130
+ case "UnionVariant":
131
+ return false;
132
+ case "Model":
133
+ if ($.array.is(type) || $.record.is(type)) {
134
+ return false;
135
+ }
136
+ return Boolean(type.name);
137
+ case "Union":
138
+ return Boolean(type.name);
139
+ default:
140
+ return false;
141
+ }
142
+ }
143
+ export { intrinsicNameToCSharpType };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=type-expression.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"type-expression.test.d.ts","sourceRoot":"","sources":["../../../../src/csharp/components/type-expression.test.tsx"],"names":[],"mappings":""}
@@ -0,0 +1,128 @@
1
+ import { createComponent as _$createComponent, createIntrinsic as _$createIntrinsic } from "@alloy-js/core/jsx-runtime";
2
+ import { render } from "@alloy-js/core";
3
+ import { d } from "@alloy-js/core/testing";
4
+ import { Namespace, SourceFile } from "@alloy-js/csharp";
5
+ import { beforeEach, describe, it } from "vitest";
6
+ import { createEmitterFrameworkTestRunner } from "../../../test/typescript/test-host.js";
7
+ import { assertFileContents } from "../../../test/utils.js";
8
+ import { Output } from "../../core/index.js";
9
+ import { ClassDeclaration } from "./class/declaration.js";
10
+ import { TypeExpression } from "./type-expression.js";
11
+ let runner;
12
+ beforeEach(async () => {
13
+ runner = await createEmitterFrameworkTestRunner();
14
+ });
15
+ function Wrapper(props) {
16
+ return _$createComponent(Output, {
17
+ get program() {
18
+ return runner.program;
19
+ },
20
+ get children() {
21
+ return _$createComponent(Namespace, {
22
+ name: "TestNamespace",
23
+ get children() {
24
+ return _$createComponent(SourceFile, {
25
+ path: "test.ts",
26
+ get children() {
27
+ return props.children;
28
+ }
29
+ });
30
+ }
31
+ });
32
+ }
33
+ });
34
+ }
35
+ async function compileType(ref) {
36
+ const {
37
+ test
38
+ } = await runner.compile(`
39
+ model Test {
40
+ @test test: ${ref};
41
+ }
42
+ `);
43
+ return test.type;
44
+ }
45
+ describe("map scalar to c# built-in types", () => {
46
+ it.each([["string", "string"], ["int32", "int"], ["int64", "long"]])("%s => %s", async (tspType, csType) => {
47
+ const type = await compileType(tspType);
48
+ const res = render(_$createComponent(Wrapper, {
49
+ get children() {
50
+ return _$createComponent(TypeExpression, {
51
+ type: type
52
+ });
53
+ }
54
+ }));
55
+ assertFileContents(res, d`
56
+ namespace TestNamespace
57
+ {
58
+ ${csType}
59
+ }
60
+ `);
61
+ });
62
+ });
63
+ it("maps array to c# array", async () => {
64
+ const type = await compileType("int32[]");
65
+ const res = render(_$createComponent(Wrapper, {
66
+ get children() {
67
+ return _$createComponent(TypeExpression, {
68
+ type: type
69
+ });
70
+ }
71
+ }));
72
+ assertFileContents(res, d`
73
+ namespace TestNamespace
74
+ {
75
+ int[]
76
+ }
77
+ `);
78
+ });
79
+ describe("Record map to IDictionary", () => {
80
+ it("for primitive types", async () => {
81
+ const type = await compileType("Record<int32>");
82
+ const res = render(_$createComponent(Wrapper, {
83
+ get children() {
84
+ return _$createComponent(TypeExpression, {
85
+ type: type
86
+ });
87
+ }
88
+ }));
89
+ assertFileContents(res, d`
90
+ namespace TestNamespace
91
+ {
92
+ IDictionary<string, int>
93
+ }
94
+ `);
95
+ });
96
+ it("for models", async () => {
97
+ const {
98
+ test,
99
+ Pet
100
+ } = await runner.compile(`
101
+ model Test {
102
+ @test test: Record<Pet>;
103
+ }
104
+ @test model Pet {}
105
+ `);
106
+ const res = render(_$createComponent(Wrapper, {
107
+ get children() {
108
+ return [_$createComponent(ClassDeclaration, {
109
+ type: Pet
110
+ }), _$createIntrinsic("hbr", {}), _$createComponent(TypeExpression, {
111
+ get type() {
112
+ return test.type;
113
+ }
114
+ })];
115
+ }
116
+ }));
117
+ assertFileContents(res, d`
118
+ namespace TestNamespace
119
+ {
120
+ class Pet
121
+ {
122
+
123
+ }
124
+ IDictionary<string, Pet>
125
+ }
126
+ `);
127
+ });
128
+ });
@@ -0,0 +1,14 @@
1
+ import { type Children } from "@alloy-js/core";
2
+ import { type Type } from "@typespec/compiler";
3
+ import type { Typekit } from "@typespec/compiler/typekit";
4
+ /**
5
+ * Helper to render a doc string for a given TypeSpec type.
6
+ *
7
+ * This is not a JSX component as it needs to return undefined if there is no doc.
8
+ *
9
+ * @param $ The Typekit instance
10
+ * @param type The TypeSpec type to generate documentation for
11
+ * @returns A DocSummary component containing the rendered doc string, or undefined if no doc is available.
12
+ */
13
+ export declare function getDocComments($: Typekit, type: Type): Children;
14
+ //# sourceMappingURL=doc-comments.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doc-comments.d.ts","sourceRoot":"","sources":["../../../../../src/csharp/components/utils/doc-comments.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAQ,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAAiB,KAAK,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAE1D;;;;;;;;GAQG;AACH,wBAAgB,cAAc,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAG,QAAQ,CA2C/D"}
@@ -0,0 +1,67 @@
1
+ import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
2
+ import { List } from "@alloy-js/core";
3
+ import * as cs from "@alloy-js/csharp";
4
+ import { getReturnsDoc } from "@typespec/compiler";
5
+ /**
6
+ * Helper to render a doc string for a given TypeSpec type.
7
+ *
8
+ * This is not a JSX component as it needs to return undefined if there is no doc.
9
+ *
10
+ * @param $ The Typekit instance
11
+ * @param type The TypeSpec type to generate documentation for
12
+ * @returns A DocSummary component containing the rendered doc string, or undefined if no doc is available.
13
+ */
14
+ export function getDocComments($, type) {
15
+ const typeDoc = $.type.getDoc(type);
16
+ if (!typeDoc) {
17
+ return undefined;
18
+ }
19
+ const docElements = [];
20
+
21
+ // Add main type documentation
22
+ docElements.push(_$createComponent(cs.DocSummary, {
23
+ get children() {
24
+ return _$createComponent(cs.DocFromMarkdown, {
25
+ markdown: typeDoc
26
+ });
27
+ }
28
+ }));
29
+
30
+ // Add operation-specific documentation if applicable
31
+ if ($.operation.is(type)) {
32
+ // Add parameter documentation
33
+ const paramDocs = [];
34
+ for (const param of type.parameters.properties.values()) {
35
+ const paramDoc = $.type.getDoc(param);
36
+ if (paramDoc) {
37
+ paramDocs.push(_$createComponent(cs.DocParam, {
38
+ get name() {
39
+ return param.name;
40
+ },
41
+ get children() {
42
+ return _$createComponent(cs.DocFromMarkdown, {
43
+ markdown: paramDoc
44
+ });
45
+ }
46
+ }));
47
+ }
48
+ }
49
+ docElements.push(...paramDocs);
50
+
51
+ // Add return documentation
52
+ const returnDoc = getReturnsDoc($.program, type);
53
+ if (returnDoc) {
54
+ docElements.push(_$createComponent(cs.DocReturns, {
55
+ get children() {
56
+ return _$createComponent(cs.DocFromMarkdown, {
57
+ markdown: returnDoc
58
+ });
59
+ }
60
+ }));
61
+ }
62
+ }
63
+ return _$createComponent(List, {
64
+ doubleHardline: true,
65
+ children: docElements
66
+ });
67
+ }
@@ -0,0 +1,23 @@
1
+ import { type Refkey } from "@alloy-js/core";
2
+ /**
3
+ * A wrapper around `refkey` that uses a custom symbol to avoid collisions with
4
+ * other libraries that use `refkey`.
5
+ *
6
+ * @remarks
7
+ *
8
+ * The underlying refkey function is called with the {@link refKeyPrefix} symbol as the first argument.
9
+ *
10
+ * @param args The parameters of the refkey.
11
+ * @returns A refkey object that can be used to identify the value.
12
+ */
13
+ export declare function efRefkey(...args: unknown[]): Refkey;
14
+ /**
15
+ * Creates a refkey for a declaration by combining the provided refkey with an internal
16
+ * refkey generated from the provided arguments.
17
+ *
18
+ * @param refkey The refkey provided by the user to be passed as is.
19
+ * @param args The parameters of the refkey.
20
+ * @returns An array of refkeys that can be passed to an Alloy declaration.
21
+ */
22
+ export declare function declarationRefkeys(refkey?: Refkey | Refkey[], ...args: unknown[]): Refkey[];
23
+ //# sourceMappingURL=refkey.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"refkey.d.ts","sourceRoot":"","sources":["../../../../../src/csharp/components/utils/refkey.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAIjE;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,CAKnD;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,EAAE,CAK3F"}
@@ -0,0 +1,35 @@
1
+ import { refkey as ayRefkey } from "@alloy-js/core";
2
+ const refKeyPrefix = Symbol.for("emitter-framework:csharp");
3
+
4
+ /**
5
+ * A wrapper around `refkey` that uses a custom symbol to avoid collisions with
6
+ * other libraries that use `refkey`.
7
+ *
8
+ * @remarks
9
+ *
10
+ * The underlying refkey function is called with the {@link refKeyPrefix} symbol as the first argument.
11
+ *
12
+ * @param args The parameters of the refkey.
13
+ * @returns A refkey object that can be used to identify the value.
14
+ */
15
+ export function efRefkey(...args) {
16
+ if (args.length === 0) {
17
+ return ayRefkey(); // Generates a unique refkey
18
+ }
19
+ return ayRefkey(refKeyPrefix, ...args);
20
+ }
21
+
22
+ /**
23
+ * Creates a refkey for a declaration by combining the provided refkey with an internal
24
+ * refkey generated from the provided arguments.
25
+ *
26
+ * @param refkey The refkey provided by the user to be passed as is.
27
+ * @param args The parameters of the refkey.
28
+ * @returns An array of refkeys that can be passed to an Alloy declaration.
29
+ */
30
+ export function declarationRefkeys(refkey, ...args) {
31
+ if (refkey) {
32
+ return [refkey, efRefkey(...args)].flat();
33
+ }
34
+ return [efRefkey(...args)];
35
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./components/index.js";
2
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/csharp/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC"}
@@ -0,0 +1 @@
1
+ export * from "./components/index.js";
@@ -1,4 +1,4 @@
1
- import { TypeSpecTestLibrary } from "@typespec/compiler/testing";
1
+ import { type TypeSpecTestLibrary } from "@typespec/compiler/testing";
2
2
  export declare const EmitterFrameworkTestLibrary: TypeSpecTestLibrary;
3
3
  export * from "./scenario-test/index.js";
4
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGpF,eAAO,MAAM,2BAA2B,EAAE,mBAGxC,CAAC;AAEH,cAAc,0BAA0B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/testing/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAGzF,eAAO,MAAM,2BAA2B,EAAE,mBAGxC,CAAC;AAEH,cAAc,0BAA0B,CAAC"}
@@ -0,0 +1,33 @@
1
+ import type { SnippetExtractor } from "./snippet-extractor.js";
2
+ export interface ElementQuery {
3
+ /** Type to query */
4
+ type: string;
5
+ /** Name of the type to query */
6
+ name: string;
7
+ }
8
+ export interface CodeBlockQuery {
9
+ /** Language */
10
+ lang: string;
11
+ /** File path */
12
+ file: string;
13
+ /** Query for content in the file */
14
+ query?: ElementQuery;
15
+ }
16
+ export interface CodeBlockExpectation extends CodeBlockQuery {
17
+ /** Expected content of the code block */
18
+ expected: string;
19
+ }
20
+ /**
21
+ * Parse a markdown code block following the expectation syntax
22
+ */
23
+ export declare function parseCodeblockExpectation(heading: string, content: string): CodeBlockExpectation;
24
+ /**
25
+ * Parse the codeblock heading for what it should validate.
26
+ * Expected format
27
+ * ```
28
+ * ts path/to/file.ts {type} {name}
29
+ * ```
30
+ */
31
+ export declare function parseCodeBlockHeading(heading: string): CodeBlockQuery;
32
+ export declare function getExcerptForQuery(snippetExtractor: SnippetExtractor, expectation: CodeBlockQuery, outputs: Record<string, string>): string;
33
+ //# sourceMappingURL=code-block-expectation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block-expectation.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/code-block-expectation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,oBAAoB;IACpB,IAAI,EAAE,MAAM,CAAC;IAEb,gCAAgC;IAChC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,eAAe;IACf,IAAI,EAAE,MAAM,CAAC;IAEb,gBAAgB;IAChB,IAAI,EAAE,MAAM,CAAC;IAEb,oCAAoC;IACpC,KAAK,CAAC,EAAE,YAAY,CAAC;CACtB;AAED,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,yCAAyC;IACzC,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,oBAAoB,CAMhG;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,CAerE;AAED,wBAAgB,kBAAkB,CAChC,gBAAgB,EAAE,gBAAgB,EAClC,WAAW,EAAE,cAAc,EAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,MAAM,CAUR"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Parse a markdown code block following the expectation syntax
3
+ */
4
+ export function parseCodeblockExpectation(heading, content) {
5
+ const query = parseCodeBlockHeading(heading);
6
+ return {
7
+ ...query,
8
+ expected: content
9
+ };
10
+ }
11
+
12
+ /**
13
+ * Parse the codeblock heading for what it should validate.
14
+ * Expected format
15
+ * ```
16
+ * ts path/to/file.ts {type} {name}
17
+ * ```
18
+ */
19
+ export function parseCodeBlockHeading(heading) {
20
+ const [lang, file, type, name] = heading.split(" ");
21
+ if (!file) {
22
+ throw new Error(`Invalid code block heading: "${heading}". Missing file path. Expected format: "<lang> <path>"`);
23
+ }
24
+ if (type && !name) {
25
+ throw new Error(`Invalid code block heading: "${heading}". Missing name when using type. Expected format: "<lang> <path> [type] [name]"`);
26
+ }
27
+ return {
28
+ lang,
29
+ file,
30
+ query: type ? {
31
+ type,
32
+ name
33
+ } : undefined
34
+ };
35
+ }
36
+ export function getExcerptForQuery(snippetExtractor, expectation, outputs) {
37
+ const content = outputs[expectation.file];
38
+ if (!content) {
39
+ throw new Error(`File ${expectation.file} not found in emitted files:\n ${Object.keys(outputs).join("\n")}`);
40
+ }
41
+ return getExcerptInFile(snippetExtractor, expectation, content);
42
+ }
43
+ function getExcerptInFile(snippetExtractor, expectation, sourceFile) {
44
+ if (expectation.query) {
45
+ const excerpt = tryGetExcerptInFile(snippetExtractor, expectation.query, sourceFile);
46
+ if (!excerpt) {
47
+ throw new Error(`Could not find ${expectation.query.type} "${expectation.query.name}" in file "${expectation.file}".`);
48
+ }
49
+ return excerpt;
50
+ } else {
51
+ return sourceFile;
52
+ }
53
+ }
54
+ function tryGetExcerptInFile(snippetExtractor, query, sourceFile) {
55
+ switch (query.type) {
56
+ case "interface":
57
+ return snippetExtractor.getInterface(sourceFile, query.name);
58
+ case "type":
59
+ return snippetExtractor.getTypeAlias(sourceFile, query.name);
60
+ case "enum":
61
+ return snippetExtractor.getEnum(sourceFile, query.name);
62
+ case "function":
63
+ return snippetExtractor.getFunction(sourceFile, query.name);
64
+ case "class":
65
+ return snippetExtractor.getClass(sourceFile, query.name);
66
+ default:
67
+ throw new Error("Unsupported type in code block expectation: " + query.type);
68
+ }
69
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=code-block-expectation.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-block-expectation.test.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/code-block-expectation.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,80 @@
1
+ import { d } from "@alloy-js/core/testing";
2
+ import { beforeAll, describe, expect, it } from "vitest";
3
+ import { getExcerptForQuery, parseCodeBlockHeading } from "./code-block-expectation.js";
4
+ import { createSnippetExtractor, createTypeScriptExtractorConfig } from "./snippet-extractor.js";
5
+ describe("parseCodeBlockHeading", () => {
6
+ it("parse whole file expectation", () => {
7
+ expect(parseCodeBlockHeading("ts path/to/file.ts")).toEqual({
8
+ lang: "ts",
9
+ file: "path/to/file.ts"
10
+ });
11
+ });
12
+ it("throws error when no file is provided", () => {
13
+ expect(() => parseCodeBlockHeading("ts")).toThrow('Invalid code block heading: "ts". Missing file path. Expected format: "<lang> <path>"');
14
+ });
15
+ it("parse parse with type and name", () => {
16
+ expect(parseCodeBlockHeading("ts path/to/file.ts interface foo")).toEqual({
17
+ lang: "ts",
18
+ file: "path/to/file.ts",
19
+ query: {
20
+ type: "interface",
21
+ name: "foo"
22
+ }
23
+ });
24
+ });
25
+ it("throws error when using type but no name is provided", () => {
26
+ expect(() => parseCodeBlockHeading("ts path/to/file.ts interface")).toThrow('Invalid code block heading: "ts path/to/file.ts interface". Missing name when using type. Expected format: "<lang> <path> [type] [name]"');
27
+ });
28
+ });
29
+ describe("getExcerptForQuery", () => {
30
+ let snippetExtractor;
31
+ beforeAll(async () => {
32
+ const tsExtractorConfig = await createTypeScriptExtractorConfig();
33
+ snippetExtractor = createSnippetExtractor(tsExtractorConfig);
34
+ });
35
+ it("gets a whole file", async () => {
36
+ const expectation = {
37
+ lang: "ts",
38
+ file: "file.ts"
39
+ };
40
+ const outputs = {
41
+ "file.ts": d`
42
+ interface bar {
43
+
44
+ }
45
+ interface foo {
46
+ bar: string;
47
+ }
48
+ `
49
+ };
50
+ const excerpt = getExcerptForQuery(snippetExtractor, expectation, outputs);
51
+ expect(excerpt).toBe(outputs["file.ts"]);
52
+ });
53
+ it("gets an interface for typescript", async () => {
54
+ const expectation = {
55
+ lang: "ts",
56
+ file: "file.ts",
57
+ query: {
58
+ type: "interface",
59
+ name: "foo"
60
+ }
61
+ };
62
+ const outputs = {
63
+ "file.ts": d`
64
+ interface bar {
65
+
66
+ }
67
+
68
+ interface foo {
69
+ bar: string;
70
+ }
71
+ `
72
+ };
73
+ const excerpt = getExcerptForQuery(snippetExtractor, expectation, outputs);
74
+ expect(excerpt).toBe(d`
75
+ interface foo {
76
+ bar: string;
77
+ }
78
+ `);
79
+ });
80
+ });
@@ -1,4 +1,4 @@
1
- import { TypeSpecTestLibrary } from "@typespec/compiler/testing";
2
- import { LanguageConfiguration, SnippetExtractor } from "./snippet-extractor.js";
3
- export declare function executeScenarios(testLibrary: TypeSpecTestLibrary, languageConfiguration: LanguageConfiguration, scenariosLocation: string, emitterOutputDir: string, snippetExtractor: SnippetExtractor): Promise<void>;
1
+ import { type EmitterTester } from "@typespec/compiler/testing";
2
+ import type { LanguageConfiguration, SnippetExtractor } from "./snippet-extractor.js";
3
+ export declare function executeScenarios(tester: EmitterTester, languageConfiguration: LanguageConfiguration, scenariosLocation: string, snippetExtractor: SnippetExtractor): Promise<void>;
4
4
  //# sourceMappingURL=harness.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/harness.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAC;AAMjE,OAAO,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AA+HjF,wBAAsB,gBAAgB,CACpC,WAAW,EAAE,mBAAmB,EAChC,qBAAqB,EAAE,qBAAqB,EAC5C,iBAAiB,EAAE,MAAM,EACzB,gBAAgB,EAAE,MAAM,EACxB,gBAAgB,EAAE,gBAAgB,iBAkBnC"}
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../../../../src/testing/scenario-test/harness.ts"],"names":[],"mappings":"AACA,OAAO,EAAyB,KAAK,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAUvF,OAAO,KAAK,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAKtF,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,aAAa,EACrB,qBAAqB,EAAE,qBAAqB,EAC5C,iBAAiB,EAAE,MAAM,EACzB,gBAAgB,EAAE,gBAAgB,iBAKnC"}