@alloy-js/csharp 0.20.0-dev.1 → 0.20.0-dev.3
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/components/EnumDeclaration.d.ts.map +1 -1
- package/dist/src/components/EnumDeclaration.js +2 -5
- package/dist/src/components/class/declaration.js +1 -1
- package/dist/src/components/class/declaration.test.js +22 -1
- package/dist/src/components/constructor/constructor.d.ts.map +1 -1
- package/dist/src/components/constructor/constructor.js +2 -5
- package/dist/src/components/field/field.d.ts.map +1 -1
- package/dist/src/components/field/field.js +2 -5
- package/dist/src/components/interface/method.d.ts.map +1 -1
- package/dist/src/components/interface/method.js +2 -5
- package/dist/src/components/interface/property.d.ts.map +1 -1
- package/dist/src/components/interface/property.js +2 -5
- package/dist/src/components/method/method.d.ts.map +1 -1
- package/dist/src/components/method/method.js +2 -5
- package/dist/src/components/parameters/parameters.d.ts.map +1 -1
- package/dist/src/components/parameters/parameters.js +2 -5
- package/dist/src/components/property/property.d.ts.map +1 -1
- package/dist/src/components/property/property.js +2 -5
- package/dist/src/components/record/declaration.d.ts +18 -0
- package/dist/src/components/record/declaration.d.ts.map +1 -1
- package/dist/src/components/record/declaration.js +11 -1
- package/dist/src/components/record/declaration.test.js +56 -2
- package/dist/src/symbols/scopes.d.ts +6 -0
- package/dist/src/symbols/scopes.d.ts.map +1 -1
- package/dist/src/symbols/scopes.js +11 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/src/components/EnumDeclaration.tsx +6 -7
- package/src/components/class/declaration.test.tsx +19 -1
- package/src/components/class/declaration.tsx +1 -1
- package/src/components/constructor/constructor.tsx +5 -10
- package/src/components/field/field.tsx +2 -10
- package/src/components/interface/method.tsx +6 -7
- package/src/components/interface/property.tsx +6 -7
- package/src/components/method/method.tsx +5 -10
- package/src/components/parameters/parameters.tsx +7 -12
- package/src/components/property/property.tsx +9 -12
- package/src/components/record/declaration.test.tsx +53 -2
- package/src/components/record/declaration.tsx +24 -0
- package/src/symbols/scopes.ts +20 -0
- package/temp/api.json +205 -1
- package/tsdoc-metadata.json +1 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@alloy-js/csharp",
|
|
3
|
-
"version": "0.20.0-dev.
|
|
4
|
-
"description": "",
|
|
3
|
+
"version": "0.20.0-dev.3",
|
|
4
|
+
"description": "Alloy components for CSharp language.",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
7
7
|
"import": "./dist/src/index.js"
|
|
@@ -14,9 +14,9 @@
|
|
|
14
14
|
"author": "jhendrix@microsoft.com",
|
|
15
15
|
"license": "MIT",
|
|
16
16
|
"dependencies": {
|
|
17
|
-
"@alloy-js/core": "~0.19.0 || >= 0.20.0-dev.
|
|
17
|
+
"@alloy-js/core": "~0.19.0 || >= 0.20.0-dev.4",
|
|
18
18
|
"change-case": "^5.4.4",
|
|
19
|
-
"marked": "^
|
|
19
|
+
"marked": "^16.1.1",
|
|
20
20
|
"pathe": "^2.0.3"
|
|
21
21
|
},
|
|
22
22
|
"devDependencies": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@alloy-js/rollup-plugin": "~0.1.0 || >= 0.1.1-dev.0",
|
|
25
25
|
"@microsoft/api-extractor": "~7.52.8",
|
|
26
26
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
27
|
-
"concurrently": "^9.
|
|
27
|
+
"concurrently": "^9.2.0",
|
|
28
28
|
"typescript": "^5.8.3",
|
|
29
29
|
"vitest": "^3.2.4"
|
|
30
30
|
},
|
|
@@ -6,7 +6,11 @@ import {
|
|
|
6
6
|
} from "../modifiers.js";
|
|
7
7
|
import { useCSharpNamePolicy } from "../name-policy.js";
|
|
8
8
|
import { CSharpOutputSymbol } from "../symbols/csharp-output-symbol.js";
|
|
9
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
CSharpMemberScope,
|
|
11
|
+
useCSharpMemberScope,
|
|
12
|
+
useCSharpScope,
|
|
13
|
+
} from "../symbols/scopes.js";
|
|
10
14
|
import { Name } from "./Name.jsx";
|
|
11
15
|
|
|
12
16
|
// properties for creating an enum
|
|
@@ -78,12 +82,7 @@ export interface EnumMemberProps {
|
|
|
78
82
|
|
|
79
83
|
// a member within a C# enum
|
|
80
84
|
export function EnumMember(props: EnumMemberProps) {
|
|
81
|
-
const scope =
|
|
82
|
-
if (scope.kind === "member" && scope.name !== "enum-decl") {
|
|
83
|
-
throw new Error(
|
|
84
|
-
"can't define an enum member outside of an enum-decl scope",
|
|
85
|
-
);
|
|
86
|
-
}
|
|
85
|
+
const scope = useCSharpMemberScope(["enum-decl"]);
|
|
87
86
|
|
|
88
87
|
const name = useCSharpNamePolicy().getName(props.name, "enum-member");
|
|
89
88
|
const thisEnumValueSymbol = new CSharpOutputSymbol(name, {
|
|
@@ -70,6 +70,24 @@ describe("modifiers", () => {
|
|
|
70
70
|
public abstract partial class TestClass;
|
|
71
71
|
`);
|
|
72
72
|
});
|
|
73
|
+
|
|
74
|
+
it("places visibility, attributes, and modifiers in the correct order", () => {
|
|
75
|
+
expect(
|
|
76
|
+
<TestNamespace>
|
|
77
|
+
<ClassDeclaration
|
|
78
|
+
partial
|
|
79
|
+
public
|
|
80
|
+
abstract
|
|
81
|
+
sealed
|
|
82
|
+
name="TestClass"
|
|
83
|
+
attributes={[<Attribute name="Test" />]}
|
|
84
|
+
/>
|
|
85
|
+
</TestNamespace>,
|
|
86
|
+
).toRenderTo(`
|
|
87
|
+
[Test]
|
|
88
|
+
public abstract sealed partial class TestClass;
|
|
89
|
+
`);
|
|
90
|
+
});
|
|
73
91
|
});
|
|
74
92
|
|
|
75
93
|
describe("base", () => {
|
|
@@ -308,7 +326,7 @@ it("declares class with invalid members", () => {
|
|
|
308
326
|
);
|
|
309
327
|
|
|
310
328
|
expect(() => toSourceText(decl)).toThrow(
|
|
311
|
-
"
|
|
329
|
+
"Can't define a EnumMember outside of a enum-decl scope",
|
|
312
330
|
);
|
|
313
331
|
});
|
|
314
332
|
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
} from "../../modifiers.js";
|
|
15
15
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
16
16
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
CSharpMemberScope,
|
|
19
|
+
useCSharpMemberScope,
|
|
20
|
+
} from "../../symbols/scopes.js";
|
|
18
21
|
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
19
22
|
|
|
20
23
|
/**
|
|
@@ -32,15 +35,7 @@ export interface ConstructorProps extends AccessModifiers {
|
|
|
32
35
|
}
|
|
33
36
|
|
|
34
37
|
export function Constructor(props: ConstructorProps) {
|
|
35
|
-
const scope =
|
|
36
|
-
if (
|
|
37
|
-
scope.kind !== "member" ||
|
|
38
|
-
(scope.name !== "class-decl" && scope.name !== "struct-decl")
|
|
39
|
-
) {
|
|
40
|
-
throw new Error(
|
|
41
|
-
"can't define a class method outside of a class or struct scope",
|
|
42
|
-
);
|
|
43
|
-
}
|
|
38
|
+
const scope = useCSharpMemberScope(["class-decl", "struct-decl"]);
|
|
44
39
|
|
|
45
40
|
const name = useCSharpNamePolicy().getName(scope.owner!.name, "class-method");
|
|
46
41
|
const ctorSymbol = new CSharpOutputSymbol(name, {
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "../../modifiers.js";
|
|
8
8
|
import { CSharpElements, useCSharpNamePolicy } from "../../name-policy.js";
|
|
9
9
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
10
|
-
import {
|
|
10
|
+
import { useCSharpMemberScope } from "../../symbols/scopes.js";
|
|
11
11
|
import { DocWhen } from "../doc/comment.jsx";
|
|
12
12
|
|
|
13
13
|
/** Field modifiers. */
|
|
@@ -40,15 +40,7 @@ export function Field(props: FieldProps) {
|
|
|
40
40
|
nameElement = "class-member-public";
|
|
41
41
|
}
|
|
42
42
|
const name = useCSharpNamePolicy().getName(props.name, nameElement);
|
|
43
|
-
const scope =
|
|
44
|
-
if (
|
|
45
|
-
scope.kind !== "member" ||
|
|
46
|
-
(scope.name !== "class-decl" && scope.name !== "struct-decl")
|
|
47
|
-
) {
|
|
48
|
-
throw new Error(
|
|
49
|
-
"can't define a class member outside of a class or struct scope",
|
|
50
|
-
);
|
|
51
|
-
}
|
|
43
|
+
const scope = useCSharpMemberScope(["class-decl", "struct-decl"]);
|
|
52
44
|
|
|
53
45
|
const memberSymbol = new CSharpOutputSymbol(name, {
|
|
54
46
|
scope,
|
|
@@ -14,7 +14,10 @@ import {
|
|
|
14
14
|
} from "../../modifiers.js";
|
|
15
15
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
16
16
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
CSharpMemberScope,
|
|
19
|
+
useCSharpMemberScope,
|
|
20
|
+
} from "../../symbols/scopes.js";
|
|
18
21
|
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
19
22
|
import { DocWhen } from "../doc/comment.jsx";
|
|
20
23
|
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
@@ -77,12 +80,8 @@ export interface InterfaceMethodProps
|
|
|
77
80
|
// a C# interface method
|
|
78
81
|
export function InterfaceMethod(props: InterfaceMethodProps) {
|
|
79
82
|
const name = useCSharpNamePolicy().getName(props.name, "class-method");
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
throw new Error(
|
|
83
|
-
"can't define an interface method outside of an interface scope",
|
|
84
|
-
);
|
|
85
|
-
}
|
|
83
|
+
|
|
84
|
+
const scope = useCSharpMemberScope(["interface-decl"]);
|
|
86
85
|
|
|
87
86
|
const methodSymbol = new CSharpOutputSymbol(name, {
|
|
88
87
|
scope,
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
} from "../../modifiers.js";
|
|
16
16
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
17
17
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
CSharpMemberScope,
|
|
20
|
+
useCSharpMemberScope,
|
|
21
|
+
} from "../../symbols/scopes.js";
|
|
19
22
|
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
20
23
|
import { DocWhen } from "../doc/comment.jsx";
|
|
21
24
|
|
|
@@ -85,12 +88,8 @@ export interface InterfacePropertyProps
|
|
|
85
88
|
*/
|
|
86
89
|
export function InterfaceProperty(props: InterfacePropertyProps) {
|
|
87
90
|
const name = useCSharpNamePolicy().getName(props.name, "class-property");
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
throw new Error(
|
|
91
|
-
"can't define an interface method outside of an interface scope",
|
|
92
|
-
);
|
|
93
|
-
}
|
|
91
|
+
|
|
92
|
+
const scope = useCSharpMemberScope(["interface-decl"]);
|
|
94
93
|
|
|
95
94
|
const propertySymbol = new CSharpOutputSymbol(name, {
|
|
96
95
|
scope,
|
|
@@ -15,7 +15,10 @@ import {
|
|
|
15
15
|
} from "../../modifiers.js";
|
|
16
16
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
17
17
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
18
|
-
import {
|
|
18
|
+
import {
|
|
19
|
+
CSharpMemberScope,
|
|
20
|
+
useCSharpMemberScope,
|
|
21
|
+
} from "../../symbols/scopes.js";
|
|
19
22
|
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
20
23
|
import { DocWhen } from "../doc/comment.jsx";
|
|
21
24
|
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
@@ -111,15 +114,7 @@ export interface MethodProps extends AccessModifiers, MethodModifiers {
|
|
|
111
114
|
// a C# class method
|
|
112
115
|
export function Method(props: MethodProps) {
|
|
113
116
|
const name = useCSharpNamePolicy().getName(props.name, "class-method");
|
|
114
|
-
const scope =
|
|
115
|
-
if (
|
|
116
|
-
scope.kind !== "member" ||
|
|
117
|
-
(scope.name !== "class-decl" && scope.name !== "struct-decl")
|
|
118
|
-
) {
|
|
119
|
-
throw new Error(
|
|
120
|
-
"can't define a class method outside of a class or struct scope",
|
|
121
|
-
);
|
|
122
|
-
}
|
|
117
|
+
const scope = useCSharpMemberScope(["class-decl", "struct-decl"]);
|
|
123
118
|
|
|
124
119
|
const methodSymbol = new CSharpOutputSymbol(name, {
|
|
125
120
|
scope,
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
} from "@alloy-js/core";
|
|
11
11
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
12
12
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
13
|
-
import {
|
|
13
|
+
import { useCSharpMemberScope } from "../../symbols/scopes.js";
|
|
14
14
|
import { Name } from "../Name.jsx";
|
|
15
15
|
|
|
16
16
|
export interface ParameterProps {
|
|
@@ -27,17 +27,12 @@ export interface ParameterProps {
|
|
|
27
27
|
/** Define a parameter to be used in class or interface method. */
|
|
28
28
|
export function Parameter(props: ParameterProps) {
|
|
29
29
|
const name = useCSharpNamePolicy().getName(props.name, "parameter");
|
|
30
|
-
const scope =
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
) {
|
|
37
|
-
throw new Error(
|
|
38
|
-
"can't define a parameter outside of a constructor-decl or method-decl scope",
|
|
39
|
-
);
|
|
40
|
-
}
|
|
30
|
+
const scope = useCSharpMemberScope([
|
|
31
|
+
"constructor-decl",
|
|
32
|
+
"method-decl",
|
|
33
|
+
"class-decl",
|
|
34
|
+
"record-decl",
|
|
35
|
+
]);
|
|
41
36
|
|
|
42
37
|
const memberSymbol = new CSharpOutputSymbol(name, {
|
|
43
38
|
scope,
|
|
@@ -16,7 +16,10 @@ import {
|
|
|
16
16
|
} from "../../modifiers.js";
|
|
17
17
|
import { useCSharpNamePolicy } from "../../name-policy.js";
|
|
18
18
|
import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
19
|
-
import {
|
|
19
|
+
import {
|
|
20
|
+
CSharpMemberScope,
|
|
21
|
+
useCSharpMemberScope,
|
|
22
|
+
} from "../../symbols/scopes.js";
|
|
20
23
|
import { AttributeList, AttributesProp } from "../attributes/attributes.jsx";
|
|
21
24
|
import { DocWhen } from "../doc/comment.jsx";
|
|
22
25
|
|
|
@@ -119,17 +122,11 @@ export interface PropertyProps extends AccessModifiers, PropertyModifiers {
|
|
|
119
122
|
*/
|
|
120
123
|
export function Property(props: PropertyProps) {
|
|
121
124
|
const name = useCSharpNamePolicy().getName(props.name, "class-property");
|
|
122
|
-
const scope =
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
scope.name !== "struct-decl")
|
|
128
|
-
) {
|
|
129
|
-
throw new Error(
|
|
130
|
-
"can't define an interface method outside of an interface scope",
|
|
131
|
-
);
|
|
132
|
-
}
|
|
125
|
+
const scope = useCSharpMemberScope([
|
|
126
|
+
"class-decl",
|
|
127
|
+
"record-decl",
|
|
128
|
+
"struct-decl",
|
|
129
|
+
]);
|
|
133
130
|
|
|
134
131
|
const propertySymbol = new CSharpOutputSymbol(name, {
|
|
135
132
|
scope,
|
|
@@ -1,9 +1,19 @@
|
|
|
1
|
+
import { Children, code, refkey } from "@alloy-js/core";
|
|
1
2
|
import { describe, expect, it } from "vitest";
|
|
2
3
|
import { TestNamespace } from "../../../test/utils.jsx";
|
|
3
4
|
import { Property } from "../property/property.jsx";
|
|
5
|
+
import { SourceFile } from "../SourceFile.jsx";
|
|
4
6
|
import { RecordDeclaration } from "./declaration.jsx";
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
function Wrapper({ children }: { children: Children }) {
|
|
9
|
+
return (
|
|
10
|
+
<TestNamespace>
|
|
11
|
+
<SourceFile path="Test.cs">{children}</SourceFile>
|
|
12
|
+
</TestNamespace>
|
|
13
|
+
);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
it("declares record with no members", () => {
|
|
7
17
|
expect(
|
|
8
18
|
<TestNamespace>
|
|
9
19
|
<RecordDeclaration name="TestRecord" />
|
|
@@ -56,7 +66,7 @@ it("specify doc comment", () => {
|
|
|
56
66
|
`);
|
|
57
67
|
});
|
|
58
68
|
|
|
59
|
-
it("specify
|
|
69
|
+
it("specify record property inside", () => {
|
|
60
70
|
expect(
|
|
61
71
|
<TestNamespace>
|
|
62
72
|
<RecordDeclaration name="TestRecord" doc="This is a test">
|
|
@@ -71,3 +81,44 @@ it("specify class property inside", () => {
|
|
|
71
81
|
}
|
|
72
82
|
`);
|
|
73
83
|
});
|
|
84
|
+
|
|
85
|
+
describe("constructor", () => {
|
|
86
|
+
it("declares primary constructor with args", () => {
|
|
87
|
+
const paramNameRefkey = refkey();
|
|
88
|
+
const paramSizeRefkey = refkey();
|
|
89
|
+
|
|
90
|
+
const ctorParams = [
|
|
91
|
+
{
|
|
92
|
+
name: "name",
|
|
93
|
+
type: "string",
|
|
94
|
+
refkey: paramNameRefkey,
|
|
95
|
+
},
|
|
96
|
+
{
|
|
97
|
+
name: "size",
|
|
98
|
+
type: "int",
|
|
99
|
+
refkey: paramSizeRefkey,
|
|
100
|
+
},
|
|
101
|
+
];
|
|
102
|
+
|
|
103
|
+
expect(
|
|
104
|
+
<Wrapper>
|
|
105
|
+
<RecordDeclaration public name="Test" primaryConstructor={ctorParams}>
|
|
106
|
+
<Property
|
|
107
|
+
name="PrettyName"
|
|
108
|
+
type="string"
|
|
109
|
+
get
|
|
110
|
+
initializer={code`$"{${paramNameRefkey}} {${paramSizeRefkey}}"`}
|
|
111
|
+
/>
|
|
112
|
+
</RecordDeclaration>
|
|
113
|
+
</Wrapper>,
|
|
114
|
+
).toRenderTo(`
|
|
115
|
+
namespace TestCode
|
|
116
|
+
{
|
|
117
|
+
public record Test(string name, int size)
|
|
118
|
+
{
|
|
119
|
+
string PrettyName { get; } = $"{name} {size}";
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
`);
|
|
123
|
+
});
|
|
124
|
+
});
|
|
@@ -10,6 +10,7 @@ import { CSharpOutputSymbol } from "../../symbols/csharp-output-symbol.js";
|
|
|
10
10
|
import { CSharpMemberScope } from "../../symbols/scopes.js";
|
|
11
11
|
import { DocWhen } from "../doc/comment.jsx";
|
|
12
12
|
import { Name } from "../Name.jsx";
|
|
13
|
+
import { ParameterProps, Parameters } from "../parameters/parameters.jsx";
|
|
13
14
|
|
|
14
15
|
export interface RecordModifiers {
|
|
15
16
|
readonly partial?: boolean;
|
|
@@ -28,6 +29,24 @@ export interface RecordDeclarationProps
|
|
|
28
29
|
doc?: core.Children;
|
|
29
30
|
refkey?: core.Refkey;
|
|
30
31
|
typeParameters?: Record<string, core.Refkey>;
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Set the primary constructor parameters
|
|
35
|
+
* @example
|
|
36
|
+
* ```tsx
|
|
37
|
+
* <ClassDeclaration name="MyClass" primaryConstructor={[
|
|
38
|
+
* {name: "value", type: "int"}
|
|
39
|
+
* ]}>
|
|
40
|
+
* ```
|
|
41
|
+
* This will produce:
|
|
42
|
+
* ```csharp
|
|
43
|
+
* public class MyClass(int value)
|
|
44
|
+
* {
|
|
45
|
+
*
|
|
46
|
+
* }
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
primaryConstructor?: ParameterProps[];
|
|
31
50
|
}
|
|
32
51
|
|
|
33
52
|
/**
|
|
@@ -99,6 +118,11 @@ export function RecordDeclaration(props: RecordDeclarationProps) {
|
|
|
99
118
|
<DocWhen doc={props.doc} />
|
|
100
119
|
{modifiers}record <Name />
|
|
101
120
|
{typeParams}
|
|
121
|
+
{props.primaryConstructor && (
|
|
122
|
+
<core.Scope value={thisRecordScope}>
|
|
123
|
+
<Parameters parameters={props.primaryConstructor} />
|
|
124
|
+
</core.Scope>
|
|
125
|
+
)}
|
|
102
126
|
{props.children ?
|
|
103
127
|
<core.Block newline>
|
|
104
128
|
<core.Scope value={thisRecordScope}>{props.children}</core.Scope>
|
package/src/symbols/scopes.ts
CHANGED
|
@@ -39,3 +39,23 @@ export type CSharpOutputScope = CSharpMemberScope | CSharpNamespaceScope;
|
|
|
39
39
|
export function useCSharpScope(): CSharpOutputScope {
|
|
40
40
|
return core.useScope() as CSharpOutputScope;
|
|
41
41
|
}
|
|
42
|
+
|
|
43
|
+
export function useCSharpMemberScope<T extends unknown[]>(
|
|
44
|
+
names: T,
|
|
45
|
+
): CSharpMemberScope & { name: T[number] } {
|
|
46
|
+
const scope = useCSharpScope();
|
|
47
|
+
assertMemberOfScope(scope, names);
|
|
48
|
+
return scope;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export function assertMemberOfScope<T extends unknown[]>(
|
|
52
|
+
scope: CSharpOutputScope,
|
|
53
|
+
names: T,
|
|
54
|
+
): asserts scope is CSharpMemberScope & { name: T[number] } {
|
|
55
|
+
if (scope.kind !== "member" || !names.includes(scope.name as T[number])) {
|
|
56
|
+
const context = core.getContext();
|
|
57
|
+
throw new Error(
|
|
58
|
+
`Can't define a ${context?.componentOwner?.component.name} outside of a ${names.join(" or ")} scope`,
|
|
59
|
+
);
|
|
60
|
+
}
|
|
61
|
+
}
|