@typespec/emitter-framework 0.11.0-dev.0 → 0.11.0-dev.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/src/core/components/index.d.ts +2 -0
- package/dist/src/core/components/index.d.ts.map +1 -1
- package/dist/src/core/components/index.js +3 -1
- package/dist/src/core/components/overrides/component-overrides.d.ts +64 -0
- package/dist/src/core/components/overrides/component-overrides.d.ts.map +1 -0
- package/dist/src/core/components/overrides/component-overrides.js +40 -0
- package/dist/src/core/components/overrides/config.d.ts +28 -0
- package/dist/src/core/components/overrides/config.d.ts.map +1 -0
- package/dist/src/core/components/overrides/config.js +54 -0
- package/dist/src/core/components/overrides/context.d.ts +11 -0
- package/dist/src/core/components/overrides/context.d.ts.map +1 -0
- package/dist/src/core/components/overrides/context.js +8 -0
- package/dist/src/csharp/components/class/declaration.d.ts +1 -1
- package/dist/src/csharp/components/class/declaration.d.ts.map +1 -1
- package/dist/src/csharp/components/class/declaration.js +4 -3
- package/dist/src/csharp/components/class/declaration.test.js +74 -1
- package/dist/src/csharp/components/type-expression.d.ts.map +1 -1
- package/dist/src/csharp/components/type-expression.js +54 -5
- package/dist/src/csharp/components/type-expression.test.js +60 -0
- package/dist/src/testing/scenario-test/harness.js +6 -1
- package/dist/src/typescript/components/interface-member.d.ts.map +1 -1
- package/dist/src/typescript/components/interface-member.js +11 -19
- package/dist/src/typescript/components/type-expression.d.ts +0 -1
- package/dist/src/typescript/components/type-expression.d.ts.map +1 -1
- package/dist/src/typescript/components/type-expression.js +11 -11
- package/dist/src/typescript/components/type-transform.d.ts.map +1 -1
- package/dist/src/typescript/components/type-transform.js +3 -3
- package/dist/test/typescript/components/component-override.test.d.ts +2 -0
- package/dist/test/typescript/components/component-override.test.d.ts.map +1 -0
- package/dist/test/typescript/components/component-override.test.js +77 -0
- package/dist/test/typescript/test-host.d.ts +2 -6
- package/dist/test/typescript/test-host.d.ts.map +1 -1
- package/dist/test/typescript/test-host.js +4 -15
- package/package.json +2 -6
- package/src/core/components/index.tsx +2 -0
- package/src/core/components/overrides/component-overrides.tsx +134 -0
- package/src/core/components/overrides/config.ts +85 -0
- package/src/core/components/overrides/context.ts +14 -0
- package/src/csharp/components/class/declaration.test.tsx +65 -1
- package/src/csharp/components/class/declaration.tsx +7 -3
- package/src/csharp/components/type-expression.test.tsx +64 -0
- package/src/csharp/components/type-expression.tsx +54 -5
- package/src/testing/scenario-test/harness.ts +6 -1
- package/src/typescript/components/interface-member.tsx +8 -14
- package/src/typescript/components/type-expression.tsx +7 -8
- package/src/typescript/components/type-transform.tsx +3 -7
- package/test/typescript/components/component-override.test.tsx +71 -0
- package/test/typescript/test-host.ts +4 -16
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/components/index.tsx"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/components/index.tsx"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,qCAAqC,CAAC;AACpD,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { type Children, type ComponentDefinition } from "@alloy-js/core";
|
|
2
|
+
import type { ObjectPropertyProps, VarDeclarationProps } from "@alloy-js/typescript";
|
|
3
|
+
import type { Enum, EnumMember, Model, ModelProperty, Scalar, Type, Union, UnionVariant } from "@typespec/compiler";
|
|
4
|
+
import { type Experimental_ComponentOverridesConfig } from "./config.js";
|
|
5
|
+
export interface Experimental_OverrideEmitPropsBase<TCustomType extends Type> {
|
|
6
|
+
/**
|
|
7
|
+
* The TypeSpec type to render.
|
|
8
|
+
*/
|
|
9
|
+
type: TCustomType;
|
|
10
|
+
/**
|
|
11
|
+
* The default emitted output for this type.
|
|
12
|
+
*/
|
|
13
|
+
default: Children;
|
|
14
|
+
}
|
|
15
|
+
export type Experimental_CustomTypeToProps<TCustomType extends Type> = TCustomType extends ModelProperty ? ObjectPropertyProps : TCustomType extends EnumMember ? {} : TCustomType extends UnionVariant ? {} : TCustomType extends Model | Scalar | Union | Enum ? VarDeclarationProps : VarDeclarationProps | ObjectPropertyProps;
|
|
16
|
+
export interface Experimental_OverrideReferenceProps<TCustomType extends Type> extends Experimental_OverrideEmitPropsBase<TCustomType> {
|
|
17
|
+
/**
|
|
18
|
+
* The member this type is referenced from, if any. This member may contain
|
|
19
|
+
* additional metadata that should be represented in the emitted output.
|
|
20
|
+
*/
|
|
21
|
+
member?: ModelProperty;
|
|
22
|
+
}
|
|
23
|
+
export interface Experimental_OverrideDeclareProps<TCustomType extends Type> extends Experimental_OverrideEmitPropsBase<TCustomType> {
|
|
24
|
+
Declaration: ComponentDefinition<Experimental_CustomTypeToProps<TCustomType>>;
|
|
25
|
+
declarationProps: Experimental_CustomTypeToProps<TCustomType>;
|
|
26
|
+
}
|
|
27
|
+
export type Experimental_OverrideDeclarationComponent<TCustomType extends Type> = ComponentDefinition<Experimental_OverrideDeclareProps<TCustomType>>;
|
|
28
|
+
export type Experimental_OverrideReferenceComponent<TCustomType extends Type> = ComponentDefinition<Experimental_OverrideReferenceProps<TCustomType>>;
|
|
29
|
+
export interface Experimental_ComponentOverridesConfigBase<TCustomType extends Type> {
|
|
30
|
+
/**
|
|
31
|
+
* Override when this type is referenced.
|
|
32
|
+
* e.g. When used in <TypeExpression type={type} />
|
|
33
|
+
*/
|
|
34
|
+
reference?: Experimental_OverrideReferenceComponent<TCustomType>;
|
|
35
|
+
}
|
|
36
|
+
export interface Experimental_ComponentOverridesProps {
|
|
37
|
+
overrides: Experimental_ComponentOverridesConfig;
|
|
38
|
+
children?: Children;
|
|
39
|
+
}
|
|
40
|
+
export declare function Experimental_ComponentOverrides(props: Experimental_ComponentOverridesProps): Children;
|
|
41
|
+
export interface Experimental_OverrideTypeComponentCommonProps<T extends Type> {
|
|
42
|
+
/**
|
|
43
|
+
* The TypeSpec type to render.
|
|
44
|
+
*/
|
|
45
|
+
type: T;
|
|
46
|
+
/**
|
|
47
|
+
* The default rendering.
|
|
48
|
+
*/
|
|
49
|
+
children: Children;
|
|
50
|
+
}
|
|
51
|
+
export interface Experimental_OverridableComponentReferenceProps<T extends Type> extends Experimental_OverrideTypeComponentCommonProps<T> {
|
|
52
|
+
/**
|
|
53
|
+
* Pass when rendering a reference to the provided type or type kind.
|
|
54
|
+
*/
|
|
55
|
+
reference: true;
|
|
56
|
+
/**
|
|
57
|
+
* The member this type is referenced from, if any. This member may contain
|
|
58
|
+
* additional metadata that should be represented in the emitted output.
|
|
59
|
+
*/
|
|
60
|
+
member?: ModelProperty;
|
|
61
|
+
}
|
|
62
|
+
export type Experimental_OverridableComponentProps<T extends Type> = Experimental_OverridableComponentReferenceProps<T>;
|
|
63
|
+
export declare function Experimental_OverridableComponent<T extends Type>(props: Experimental_OverridableComponentProps<T>): Children;
|
|
64
|
+
//# sourceMappingURL=component-overrides.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"component-overrides.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/overrides/component-overrides.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,KAAK,mBAAmB,EAAE,MAAM,gBAAgB,CAAC;AACzE,OAAO,KAAK,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AACrF,OAAO,KAAK,EACV,IAAI,EACJ,UAAU,EACV,KAAK,EACL,aAAa,EACb,MAAM,EACN,IAAI,EACJ,KAAK,EACL,YAAY,EACb,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,KAAK,qCAAqC,EAG3C,MAAM,aAAa,CAAC;AAGrB,MAAM,WAAW,kCAAkC,CAAC,WAAW,SAAS,IAAI;IAC1E;;OAEG;IACH,IAAI,EAAE,WAAW,CAAC;IAElB;;OAEG;IACH,OAAO,EAAE,QAAQ,CAAC;CACnB;AAED,MAAM,MAAM,8BAA8B,CAAC,WAAW,SAAS,IAAI,IACjE,WAAW,SAAS,aAAa,GAC7B,mBAAmB,GACnB,WAAW,SAAS,UAAU,GAC5B,EAAE,GACF,WAAW,SAAS,YAAY,GAC9B,EAAE,GACF,WAAW,SAAS,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,IAAI,GAC/C,mBAAmB,GACnB,mBAAmB,GAAG,mBAAmB,CAAC;AAEtD,MAAM,WAAW,mCAAmC,CAAC,WAAW,SAAS,IAAI,CAC3E,SAAQ,kCAAkC,CAAC,WAAW,CAAC;IACvD;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,iCAAiC,CAAC,WAAW,SAAS,IAAI,CACzE,SAAQ,kCAAkC,CAAC,WAAW,CAAC;IACvD,WAAW,EAAE,mBAAmB,CAAC,8BAA8B,CAAC,WAAW,CAAC,CAAC,CAAC;IAC9E,gBAAgB,EAAE,8BAA8B,CAAC,WAAW,CAAC,CAAC;CAC/D;AAED,MAAM,MAAM,yCAAyC,CAAC,WAAW,SAAS,IAAI,IAC5E,mBAAmB,CAAC,iCAAiC,CAAC,WAAW,CAAC,CAAC,CAAC;AAEtE,MAAM,MAAM,uCAAuC,CAAC,WAAW,SAAS,IAAI,IAAI,mBAAmB,CACjG,mCAAmC,CAAC,WAAW,CAAC,CACjD,CAAC;AAEF,MAAM,WAAW,yCAAyC,CAAC,WAAW,SAAS,IAAI;IACjF;;;OAGG;IACH,SAAS,CAAC,EAAE,uCAAuC,CAAC,WAAW,CAAC,CAAC;CAClE;AAED,MAAM,WAAW,oCAAoC;IACnD,SAAS,EAAE,qCAAqC,CAAC;IACjD,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB;AACD,wBAAgB,+BAA+B,CAAC,KAAK,EAAE,oCAAoC,YAM1F;AAED,MAAM,WAAW,6CAA6C,CAAC,CAAC,SAAS,IAAI;IAC3E;;OAEG;IACH,IAAI,EAAE,CAAC,CAAC;IAER;;OAEG;IACH,QAAQ,EAAE,QAAQ,CAAC;CACpB;AAED,MAAM,WAAW,+CAA+C,CAAC,CAAC,SAAS,IAAI,CAC7E,SAAQ,6CAA6C,CAAC,CAAC,CAAC;IACxD;;OAEG;IACH,SAAS,EAAE,IAAI,CAAC;IAEhB;;;OAGG;IACH,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,MAAM,sCAAsC,CAAC,CAAC,SAAS,IAAI,IAC/D,+CAA+C,CAAC,CAAC,CAAC,CAAC;AAErD,wBAAgB,iCAAiC,CAAC,CAAC,SAAS,IAAI,EAC9D,KAAK,EAAE,sCAAsC,CAAC,CAAC,CAAC,YAkBjD"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { useTsp } from "../../context/index.js";
|
|
3
|
+
import { getOverrideForType, getOverridesForTypeKind } from "./config.js";
|
|
4
|
+
import { OverridesContext, useOverrides } from "./context.js";
|
|
5
|
+
export function Experimental_ComponentOverrides(props) {
|
|
6
|
+
const context = {
|
|
7
|
+
overrides: props.overrides
|
|
8
|
+
};
|
|
9
|
+
return _$createComponent(OverridesContext.Provider, {
|
|
10
|
+
value: context,
|
|
11
|
+
get children() {
|
|
12
|
+
return props.children;
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
export function Experimental_OverridableComponent(props) {
|
|
17
|
+
const options = useOverrides();
|
|
18
|
+
const {
|
|
19
|
+
$
|
|
20
|
+
} = useTsp();
|
|
21
|
+
const descriptor = getOverrideForType($.program, props.type, options.overrides) ?? getOverridesForTypeKind($.program, props.type.kind, options.overrides);
|
|
22
|
+
if (!descriptor) {
|
|
23
|
+
return [_$memo(() => props.children)];
|
|
24
|
+
}
|
|
25
|
+
if ("reference" in props && props.reference && descriptor.reference) {
|
|
26
|
+
const CustomComponent = descriptor.reference;
|
|
27
|
+
return _$createComponent(CustomComponent, {
|
|
28
|
+
get type() {
|
|
29
|
+
return props.type;
|
|
30
|
+
},
|
|
31
|
+
get member() {
|
|
32
|
+
return props.member;
|
|
33
|
+
},
|
|
34
|
+
get ["default"]() {
|
|
35
|
+
return props.children;
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return [_$memo(() => props.children)];
|
|
40
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { Program, Type } from "@typespec/compiler";
|
|
2
|
+
import type { Experimental_ComponentOverridesConfigBase } from "./component-overrides.jsx";
|
|
3
|
+
declare const getOverrideForTypeSym: unique symbol;
|
|
4
|
+
declare const getOverrideForTypeKindSym: unique symbol;
|
|
5
|
+
export type Experimental_ComponentOverridesConfig = Experimental_ComponentOverridesClass;
|
|
6
|
+
export declare const Experimental_ComponentOverridesConfig: {
|
|
7
|
+
new (): Experimental_ComponentOverridesClass;
|
|
8
|
+
(): Experimental_ComponentOverridesClass;
|
|
9
|
+
};
|
|
10
|
+
export declare class Experimental_ComponentOverridesClass {
|
|
11
|
+
#private;
|
|
12
|
+
forType<const T extends Type>(type: T, options: Experimental_ComponentOverridesConfigBase<T>): this;
|
|
13
|
+
forTypeKind<const TKind extends Type["kind"]>(typeKind: TKind, options: Experimental_ComponentOverridesConfigBase<Extract<Type, {
|
|
14
|
+
kind: TKind;
|
|
15
|
+
}>>): this;
|
|
16
|
+
/**
|
|
17
|
+
* @internal
|
|
18
|
+
*/
|
|
19
|
+
[getOverrideForTypeSym](program: Program, type: Type): Experimental_ComponentOverridesConfigBase<any> | undefined;
|
|
20
|
+
/**
|
|
21
|
+
* @internal
|
|
22
|
+
*/
|
|
23
|
+
[getOverrideForTypeKindSym](program: Program, typeKind: Type["kind"]): Experimental_ComponentOverridesConfigBase<any> | undefined;
|
|
24
|
+
}
|
|
25
|
+
export declare function getOverrideForType(program: Program, type: Type, options?: Experimental_ComponentOverridesConfig): Experimental_ComponentOverridesConfigBase<any> | undefined;
|
|
26
|
+
export declare function getOverridesForTypeKind(program: Program, typeKind: Type["kind"], options?: Experimental_ComponentOverridesConfig): Experimental_ComponentOverridesConfigBase<any> | undefined;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/overrides/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAU,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAEhE,OAAO,KAAK,EAAE,yCAAyC,EAAE,MAAM,2BAA2B,CAAC;AAE3F,QAAA,MAAM,qBAAqB,EAAE,OAAO,MAA+C,CAAC;AACpF,QAAA,MAAM,yBAAyB,EAAE,OAAO,MAAmD,CAAC;AAE5F,MAAM,MAAM,qCAAqC,GAAG,oCAAoC,CAAC;AACzF,eAAO,MAAM,qCAAqC,EAE7C;IACH,QAAQ,oCAAoC,CAAC;IAC7C,IAAI,oCAAoC,CAAC;CAC1C,CAAC;AAEF,qBAAa,oCAAoC;;IAK/C,OAAO,CAAC,KAAK,CAAC,CAAC,SAAS,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,OAAO,EAAE,yCAAyC,CAAC,CAAC,CAAC;IAM5F,WAAW,CAAC,KAAK,CAAC,KAAK,SAAS,IAAI,CAAC,MAAM,CAAC,EAC1C,QAAQ,EAAE,KAAK,EACf,OAAO,EAAE,yCAAyC,CAAC,OAAO,CAAC,IAAI,EAAE;QAAE,IAAI,EAAE,KAAK,CAAA;KAAE,CAAC,CAAC;IAOpF;;OAEG;IACH,CAAC,qBAAqB,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI;IAwBpD;;OAEG;IACH,CAAC,yBAAyB,CAAC,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC;CAGrE;AAED,wBAAgB,kBAAkB,CAChC,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,OAAO,CAAC,EAAE,qCAAqC,8DAGhD;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,EACtB,OAAO,CAAC,EAAE,qCAAqC,8DAGhD"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { $ } from "@typespec/compiler/typekit";
|
|
2
|
+
const getOverrideForTypeSym = Symbol.for("ef-ts:getOverrideForType");
|
|
3
|
+
const getOverrideForTypeKindSym = Symbol.for("ef-ts:getOverrideForTypeKind");
|
|
4
|
+
export const Experimental_ComponentOverridesConfig = function () {
|
|
5
|
+
return new Experimental_ComponentOverridesClass();
|
|
6
|
+
};
|
|
7
|
+
export class Experimental_ComponentOverridesClass {
|
|
8
|
+
#typeEmitOptions = new Map();
|
|
9
|
+
#typeKindEmitOptions = new Map();
|
|
10
|
+
forType(type, options) {
|
|
11
|
+
this.#typeEmitOptions.set(type, options);
|
|
12
|
+
return this;
|
|
13
|
+
}
|
|
14
|
+
forTypeKind(typeKind, options) {
|
|
15
|
+
this.#typeKindEmitOptions.set(typeKind, options);
|
|
16
|
+
return this;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @internal
|
|
21
|
+
*/
|
|
22
|
+
[getOverrideForTypeSym](program, type) {
|
|
23
|
+
const options = this.#typeEmitOptions.get(type);
|
|
24
|
+
if (options || !$(program).scalar.is(type) /** || isBuiltIn(program, type) */) {
|
|
25
|
+
return options;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// have a scalar, it's not a built-in scalar, and didn't find options, so
|
|
29
|
+
// see if we have options for a base scalar.
|
|
30
|
+
let currentScalar = type;
|
|
31
|
+
while (currentScalar &&
|
|
32
|
+
// !isBuiltIn(program, currentScalar) &&
|
|
33
|
+
!this.#typeEmitOptions.has(currentScalar)) {
|
|
34
|
+
currentScalar = currentScalar?.baseScalar;
|
|
35
|
+
}
|
|
36
|
+
if (!currentScalar) {
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|
|
39
|
+
return this.#typeEmitOptions.get(currentScalar);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @internal
|
|
44
|
+
*/
|
|
45
|
+
[getOverrideForTypeKindSym](program, typeKind) {
|
|
46
|
+
return this.#typeKindEmitOptions.get(typeKind);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export function getOverrideForType(program, type, options) {
|
|
50
|
+
return options?.[getOverrideForTypeSym](program, type);
|
|
51
|
+
}
|
|
52
|
+
export function getOverridesForTypeKind(program, typeKind, options) {
|
|
53
|
+
return options?.[getOverrideForTypeKindSym](program, typeKind);
|
|
54
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { type ComponentContext } from "@alloy-js/core";
|
|
2
|
+
import type { Experimental_ComponentOverridesConfig } from "./config.js";
|
|
3
|
+
export interface ComponentOverridesContext {
|
|
4
|
+
overrides?: Experimental_ComponentOverridesConfig;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Context for setting overrides for components
|
|
8
|
+
*/
|
|
9
|
+
export declare const OverridesContext: ComponentContext<ComponentOverridesContext>;
|
|
10
|
+
export declare function useOverrides(): ComponentOverridesContext;
|
|
11
|
+
//# sourceMappingURL=context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../../../src/core/components/overrides/context.ts"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;AAClF,OAAO,KAAK,EAAE,qCAAqC,EAAE,MAAM,aAAa,CAAC;AAEzE,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,qCAAqC,CAAC;CACnD;AACD;;GAEG;AACH,eAAO,MAAM,gBAAgB,EAAE,gBAAgB,CAAC,yBAAyB,CAAqB,CAAC;AAE/F,wBAAgB,YAAY,IAAI,yBAAyB,CAExD"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { type Children } from "@alloy-js/core";
|
|
2
2
|
import * as cs from "@alloy-js/csharp";
|
|
3
|
-
import type
|
|
3
|
+
import { type Interface, type Model } from "@typespec/compiler";
|
|
4
4
|
export interface ClassDeclarationProps extends Omit<cs.ClassDeclarationProps, "name"> {
|
|
5
5
|
/** Set an alternative name for the class. Otherwise default to the type name. */
|
|
6
6
|
name?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../../../../../src/csharp/components/class/declaration.tsx"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"declaration.d.ts","sourceRoot":"","sources":["../../../../../src/csharp/components/class/declaration.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAO,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAEvC,OAAO,EAAc,KAAK,SAAS,EAAE,KAAK,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAO5E,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,EAAE,CAAC,qBAAqB,EAAE,MAAM,CAAC;IACnF,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,wCAAwC;IACxC,IAAI,EAAE,KAAK,GAAG,SAAS,CAAC;IACxB,8FAA8F;IAC9F,cAAc,CAAC,EAAE,OAAO,CAAC;CAC1B;AAYD,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,GAAG,QAAQ,CAuBvE"}
|
|
@@ -2,6 +2,7 @@ import { memo as _$memo, mergeProps as _$mergeProps, createComponent as _$create
|
|
|
2
2
|
import { For } from "@alloy-js/core";
|
|
3
3
|
import * as cs from "@alloy-js/csharp";
|
|
4
4
|
import { Method } from "@alloy-js/csharp";
|
|
5
|
+
import { isVoidType } from "@typespec/compiler";
|
|
5
6
|
import { useTsp } from "../../../core/index.js";
|
|
6
7
|
import { Property } from "../property/property.js";
|
|
7
8
|
import { TypeExpression } from "../type-expression.js";
|
|
@@ -38,10 +39,10 @@ export function ClassDeclaration(props) {
|
|
|
38
39
|
}))];
|
|
39
40
|
}
|
|
40
41
|
function ClassProperties(props) {
|
|
42
|
+
// Ignore 'void' type properties which is not valid in csharp
|
|
43
|
+
const properties = Array.from(props.type.properties.entries()).filter(([_, p]) => !isVoidType(p.type));
|
|
41
44
|
return _$createComponent(For, {
|
|
42
|
-
|
|
43
|
-
return props.type.properties.entries();
|
|
44
|
-
},
|
|
45
|
+
each: properties,
|
|
45
46
|
hardline: true,
|
|
46
47
|
children: ([name, property]) => _$createComponent(Property, {
|
|
47
48
|
type: property,
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
-
import { createComponent as _$createComponent, createIntrinsic as _$createIntrinsic } from "@alloy-js/core/jsx-runtime";
|
|
1
|
+
import { createComponent as _$createComponent, memo as _$memo, createIntrinsic as _$createIntrinsic } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { Experimental_ComponentOverrides, Experimental_ComponentOverridesConfig } from "#core/index.js";
|
|
2
3
|
import { Tester } from "#test/test-host.js";
|
|
4
|
+
import { List } from "@alloy-js/core";
|
|
5
|
+
import { d } from "@alloy-js/core/testing";
|
|
3
6
|
import { createCSharpNamePolicy, Namespace, SourceFile } from "@alloy-js/csharp";
|
|
4
7
|
import { t } from "@typespec/compiler/testing";
|
|
5
8
|
import { beforeEach, describe, expect, it } from "vitest";
|
|
@@ -79,6 +82,76 @@ it("renders a class declaration with properties", async () => {
|
|
|
79
82
|
}
|
|
80
83
|
`);
|
|
81
84
|
});
|
|
85
|
+
it("renders a class declaration with properties using component override", async () => {
|
|
86
|
+
const {
|
|
87
|
+
TestModel,
|
|
88
|
+
Foo,
|
|
89
|
+
Bar
|
|
90
|
+
} = await runner.compile(t.code`
|
|
91
|
+
model ${t.model("Foo")} {}
|
|
92
|
+
model ${t.model("Bar")} {}
|
|
93
|
+
model ${t.model("TestModel")} {
|
|
94
|
+
Prop1: string;
|
|
95
|
+
Prop2: int32;
|
|
96
|
+
Prop3?: Foo;
|
|
97
|
+
}
|
|
98
|
+
`);
|
|
99
|
+
expect(_$createComponent(Wrapper, {
|
|
100
|
+
get children() {
|
|
101
|
+
return _$createComponent(TestClientOverrides, {
|
|
102
|
+
get children() {
|
|
103
|
+
return _$createComponent(List, {
|
|
104
|
+
hardline: true,
|
|
105
|
+
get children() {
|
|
106
|
+
return [_$createComponent(ClassDeclaration, {
|
|
107
|
+
type: Foo
|
|
108
|
+
}), _$createComponent(ClassDeclaration, {
|
|
109
|
+
type: Bar
|
|
110
|
+
}), _$createComponent(ClassDeclaration, {
|
|
111
|
+
type: TestModel
|
|
112
|
+
})];
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
})).toRenderTo(d`
|
|
119
|
+
namespace TestNamespace
|
|
120
|
+
{
|
|
121
|
+
class Foo
|
|
122
|
+
{
|
|
123
|
+
|
|
124
|
+
}
|
|
125
|
+
class Bar
|
|
126
|
+
{
|
|
127
|
+
|
|
128
|
+
}
|
|
129
|
+
class TestModel
|
|
130
|
+
{
|
|
131
|
+
public required string Prop1 { get; set; }
|
|
132
|
+
public required int Prop2 { get; set; }
|
|
133
|
+
public Bar Prop3 { get; set; }
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
`);
|
|
137
|
+
});
|
|
138
|
+
function TestClientOverrides(props) {
|
|
139
|
+
const overrides = Experimental_ComponentOverridesConfig().forTypeKind("Model", {
|
|
140
|
+
reference: props => {
|
|
141
|
+
if (props.type.name === "Foo") {
|
|
142
|
+
return "Bar";
|
|
143
|
+
} else {
|
|
144
|
+
return props.default;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return _$createComponent(Experimental_ComponentOverrides, {
|
|
149
|
+
overrides: overrides,
|
|
150
|
+
get children() {
|
|
151
|
+
return props.children;
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
}
|
|
82
155
|
it("can override class name", async () => {
|
|
83
156
|
const {
|
|
84
157
|
TestModel
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-expression.d.ts","sourceRoot":"","sources":["../../../../src/csharp/components/type-expression.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"type-expression.d.ts","sourceRoot":"","sources":["../../../../src/csharp/components/type-expression.tsx"],"names":[],"mappings":"AACA,OAAO,EAAQ,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,MAAM,EACX,KAAK,IAAI,EAEV,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,4BAA4B,CAAC;AAK1D,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAC;CACZ;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,QAAQ,CAmCnE;AAwBD,QAAA,MAAM,yBAAyB,4BAqC7B,CAAC;AAEH,wBAAgB,4BAA4B,CAC1C,CAAC,EAAE,OAAO,EACV,IAAI,EAAE,MAAM,GAAG,aAAa,GAC3B,MAAM,GAAG,IAAI,CAoBf;AAyBD,OAAO,EAAE,yBAAyB,EAAE,CAAC"}
|
|
@@ -1,18 +1,35 @@
|
|
|
1
1
|
import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
|
|
2
|
+
import { Experimental_OverridableComponent } from "#core/index.js";
|
|
2
3
|
import { code } from "@alloy-js/core";
|
|
3
4
|
import { Reference } from "@alloy-js/csharp";
|
|
4
|
-
import { getTypeName } from "@typespec/compiler";
|
|
5
|
+
import { getTypeName, isNullType, isVoidType } from "@typespec/compiler";
|
|
5
6
|
import { useTsp } from "../../core/index.js";
|
|
6
7
|
import { reportTypescriptDiagnostic } from "../../typescript/lib.js";
|
|
7
8
|
import { efRefkey } from "./utils/refkey.js";
|
|
8
9
|
export function TypeExpression(props) {
|
|
10
|
+
if (props.type.kind === "Union") {
|
|
11
|
+
const nullabletype = getNullableUnionInnerType(props.type);
|
|
12
|
+
if (nullabletype) {
|
|
13
|
+
return code`${_$createComponent(TypeExpression, {
|
|
14
|
+
type: nullabletype
|
|
15
|
+
})}?`;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
9
18
|
const {
|
|
10
19
|
$
|
|
11
20
|
} = useTsp();
|
|
12
21
|
if (isDeclaration($, props.type)) {
|
|
13
|
-
return _$createComponent(
|
|
14
|
-
|
|
15
|
-
|
|
22
|
+
return _$createComponent(Experimental_OverridableComponent, {
|
|
23
|
+
reference: true,
|
|
24
|
+
get type() {
|
|
25
|
+
return props.type;
|
|
26
|
+
},
|
|
27
|
+
get children() {
|
|
28
|
+
return _$createComponent(Reference, {
|
|
29
|
+
get refkey() {
|
|
30
|
+
return efRefkey(props.type);
|
|
31
|
+
}
|
|
32
|
+
});
|
|
16
33
|
}
|
|
17
34
|
});
|
|
18
35
|
}
|
|
@@ -30,9 +47,41 @@ export function TypeExpression(props) {
|
|
|
30
47
|
return props.type.indexer.value;
|
|
31
48
|
}
|
|
32
49
|
})}>`;
|
|
50
|
+
} else if ($.literal.isString(props.type)) {
|
|
51
|
+
// c# doesn't have literal types, so we map them to their corresponding C# types in general
|
|
52
|
+
return code`string`;
|
|
53
|
+
} else if ($.literal.isNumeric(props.type)) {
|
|
54
|
+
return Number.isInteger(props.type.value) ? code`int` : code`double`;
|
|
55
|
+
} else if ($.literal.isBoolean(props.type)) {
|
|
56
|
+
return code`bool`;
|
|
57
|
+
} else if (isVoidType(props.type)) {
|
|
58
|
+
return code`void`;
|
|
33
59
|
}
|
|
34
60
|
throw new Error(`Unsupported type for TypeExpression: ${props.type.kind} (${getTypeName(props.type)})`);
|
|
35
61
|
}
|
|
62
|
+
|
|
63
|
+
/** Get the inner type if the union is a nullable, otherwise return undefined */
|
|
64
|
+
function getNullableUnionInnerType(u) {
|
|
65
|
+
const isNull = type => isNullType(type) || isVoidType(type);
|
|
66
|
+
if (Array.from(u.variants.values()).some(v => isNull(v.type))) {
|
|
67
|
+
const {
|
|
68
|
+
$
|
|
69
|
+
} = useTsp();
|
|
70
|
+
const left = Array.from(u.variants.values()).filter(v => !isNull(v.type));
|
|
71
|
+
if (left.length === 0) {
|
|
72
|
+
// a union only has null or void?
|
|
73
|
+
return $.intrinsic.void;
|
|
74
|
+
} else if (left.length === 1) {
|
|
75
|
+
return left[0].type;
|
|
76
|
+
} else {
|
|
77
|
+
return $.union.create({
|
|
78
|
+
name: u.name,
|
|
79
|
+
variants: left
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return undefined;
|
|
84
|
+
}
|
|
36
85
|
const intrinsicNameToCSharpType = new Map([
|
|
37
86
|
// Core types
|
|
38
87
|
["unknown", "object"],
|
|
@@ -133,7 +182,7 @@ function isDeclaration($, type) {
|
|
|
133
182
|
if ($.array.is(type) || $.record.is(type)) {
|
|
134
183
|
return false;
|
|
135
184
|
}
|
|
136
|
-
return
|
|
185
|
+
return true;
|
|
137
186
|
case "Union":
|
|
138
187
|
return Boolean(type.name);
|
|
139
188
|
default:
|
|
@@ -125,4 +125,64 @@ describe("Record map to IDictionary", () => {
|
|
|
125
125
|
}
|
|
126
126
|
`);
|
|
127
127
|
});
|
|
128
|
+
});
|
|
129
|
+
describe("Nullable union", () => {
|
|
130
|
+
it("nullable boolean", async () => {
|
|
131
|
+
const {
|
|
132
|
+
Pet
|
|
133
|
+
} = await runner.compile(`
|
|
134
|
+
@test model Pet {
|
|
135
|
+
@test name: boolean | null;
|
|
136
|
+
}
|
|
137
|
+
`);
|
|
138
|
+
const res = render(_$createComponent(Wrapper, {
|
|
139
|
+
get children() {
|
|
140
|
+
return _$createComponent(ClassDeclaration, {
|
|
141
|
+
type: Pet
|
|
142
|
+
});
|
|
143
|
+
}
|
|
144
|
+
}));
|
|
145
|
+
assertFileContents(res, d`
|
|
146
|
+
namespace TestNamespace
|
|
147
|
+
{
|
|
148
|
+
class Pet
|
|
149
|
+
{
|
|
150
|
+
public required bool? name { get; set; }
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
`);
|
|
154
|
+
});
|
|
155
|
+
});
|
|
156
|
+
describe("Literal types", () => {
|
|
157
|
+
it("literal types (string, int, double, bool)", async () => {
|
|
158
|
+
const {
|
|
159
|
+
Pet
|
|
160
|
+
} = await runner.compile(`
|
|
161
|
+
@test model Pet {
|
|
162
|
+
@test boolName: true;
|
|
163
|
+
@test intName: 42;
|
|
164
|
+
@test doubleName: 3.14;
|
|
165
|
+
@test stringName: "Hello";
|
|
166
|
+
}
|
|
167
|
+
`);
|
|
168
|
+
const res = render(_$createComponent(Wrapper, {
|
|
169
|
+
get children() {
|
|
170
|
+
return _$createComponent(ClassDeclaration, {
|
|
171
|
+
type: Pet
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
}));
|
|
175
|
+
assertFileContents(res, d`
|
|
176
|
+
namespace TestNamespace
|
|
177
|
+
{
|
|
178
|
+
class Pet
|
|
179
|
+
{
|
|
180
|
+
public required bool boolName { get; set; }
|
|
181
|
+
public required int intName { get; set; }
|
|
182
|
+
public required double doubleName { get; set; }
|
|
183
|
+
public required string stringName { get; set; }
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
`);
|
|
187
|
+
});
|
|
128
188
|
});
|
|
@@ -133,7 +133,12 @@ function describeScenarios(scenarioFiles, tester, languageConfiguration, snippet
|
|
|
133
133
|
it(`Test: ${testBlock.heading}`, async () => {
|
|
134
134
|
const result = getExcerptForQuery(snippetExtractor, testBlock.expectation, outputFiles);
|
|
135
135
|
if (SCENARIOS_UPDATE) {
|
|
136
|
-
|
|
136
|
+
try {
|
|
137
|
+
testBlock.content = await languageConfiguration.format(result);
|
|
138
|
+
} catch {
|
|
139
|
+
// If formatting fails, we still want to update the content
|
|
140
|
+
testBlock.content = result;
|
|
141
|
+
}
|
|
137
142
|
} else {
|
|
138
143
|
const expected = await languageConfiguration.format(testBlock.content);
|
|
139
144
|
const actual = await languageConfiguration.format(result);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"interface-member.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-member.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAe,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"interface-member.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/interface-member.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAE/C,OAAO,EAAe,KAAK,aAAa,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAKrF,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,aAAa,GAAG,SAAS,CAAC;IAChC,GAAG,CAAC,EAAE,QAAQ,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB;AAED,wBAAgB,eAAe,CAAC,KAAK,EAAE,oBAAoB,YAyB1D"}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { createComponent as _$createComponent } from "@alloy-js/core/jsx-runtime";
|
|
2
2
|
import * as ts from "@alloy-js/typescript";
|
|
3
3
|
import { isNeverType } from "@typespec/compiler";
|
|
4
|
-
import { getHttpPart } from "@typespec/http";
|
|
5
4
|
import { useTsp } from "../../core/context/tsp-context.js";
|
|
6
5
|
import { InterfaceMethod } from "./interface-method.js";
|
|
7
6
|
import { TypeExpression } from "./type-expression.js";
|
|
@@ -16,23 +15,16 @@ export function InterfaceMember(props) {
|
|
|
16
15
|
if (isNeverType(props.type.type)) {
|
|
17
16
|
return null;
|
|
18
17
|
}
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
},
|
|
30
|
-
get type() {
|
|
31
|
-
return _$createComponent(TypeExpression, {
|
|
32
|
-
type: unpackedType
|
|
33
|
-
});
|
|
34
|
-
}
|
|
35
|
-
});
|
|
18
|
+
const unpackedType = props.type.type;
|
|
19
|
+
const interfaceMemberProps = {
|
|
20
|
+
doc,
|
|
21
|
+
name,
|
|
22
|
+
optional: props.optional ?? props.type.optional,
|
|
23
|
+
type: _$createComponent(TypeExpression, {
|
|
24
|
+
type: unpackedType
|
|
25
|
+
})
|
|
26
|
+
};
|
|
27
|
+
return _$createComponent(ts.InterfaceMember, interfaceMemberProps);
|
|
36
28
|
}
|
|
37
29
|
if ($.operation.is(props.type)) {
|
|
38
30
|
return _$createComponent(InterfaceMethod, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"type-expression.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/type-expression.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgC,IAAI,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"type-expression.d.ts","sourceRoot":"","sources":["../../../../src/typescript/components/type-expression.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAgC,IAAI,EAAE,MAAM,oBAAoB,CAAC;AAY7E,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,IAAI,CAAC;IAEX;;;;OAIG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,qCAyDxD"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createComponent as _$createComponent, memo as _$memo } from "@alloy-js/core/jsx-runtime";
|
|
2
2
|
import { For } from "@alloy-js/core";
|
|
3
3
|
import { Reference, ValueExpression } from "@alloy-js/typescript";
|
|
4
|
-
import "
|
|
4
|
+
import { Experimental_OverridableComponent } from "../../core/components/overrides/component-overrides.js";
|
|
5
5
|
import { useTsp } from "../../core/context/tsp-context.js";
|
|
6
6
|
import { reportTypescriptDiagnostic } from "../../typescript/lib.js";
|
|
7
7
|
import { efRefkey } from "../utils/refkey.js";
|
|
@@ -14,13 +14,19 @@ export function TypeExpression(props) {
|
|
|
14
14
|
const {
|
|
15
15
|
$
|
|
16
16
|
} = useTsp();
|
|
17
|
-
const type =
|
|
17
|
+
const type = props.type;
|
|
18
18
|
if (!props.noReference && isDeclaration($, type)) {
|
|
19
19
|
// todo: probably need abstraction around deciding what's a declaration in the output
|
|
20
20
|
// (it may not correspond to things which are declarations in TypeSpec?)
|
|
21
|
-
return _$createComponent(
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
return _$createComponent(Experimental_OverridableComponent, {
|
|
22
|
+
reference: true,
|
|
23
|
+
type: type,
|
|
24
|
+
get children() {
|
|
25
|
+
return _$createComponent(Reference, {
|
|
26
|
+
get refkey() {
|
|
27
|
+
return efRefkey(type);
|
|
28
|
+
}
|
|
29
|
+
});
|
|
24
30
|
}
|
|
25
31
|
});
|
|
26
32
|
//throw new Error("Reference not implemented");
|
|
@@ -79,12 +85,6 @@ export function TypeExpression(props) {
|
|
|
79
85
|
elementType: elementType
|
|
80
86
|
});
|
|
81
87
|
}
|
|
82
|
-
if ($.httpPart.is(type)) {
|
|
83
|
-
const partType = $.httpPart.unpack(type);
|
|
84
|
-
return _$createComponent(TypeExpression, {
|
|
85
|
-
type: partType
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
88
|
return _$createComponent(InterfaceExpression, {
|
|
89
89
|
type: type
|
|
90
90
|
});
|