Skip to content

Commit 7b85bcd

Browse files
committed
Output the default values of generic types
1 parent 168b6dc commit 7b85bcd

9 files changed

+96
-2
lines changed

lib/parse/ClassIndex.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ export interface ClassLoaded extends ClassReference {
5959
/**
6060
* A hash of generic type name to its properties.
6161
*/
62-
export type GenericTypes = Record<string, { type?: TSESTree.TypeNode }>;
62+
export type GenericTypes = Record<string, { type?: TSESTree.TypeNode; default?: TSESTree.TypeNode }>;
6363

6464
/**
6565
* Something (like a class or interface) that may have generic types assigned to it as instantiation.

lib/parse/ClassLoader.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -444,7 +444,7 @@ export class ClassLoader {
444444
const genericTypes: GenericTypes = {};
445445
if (classDeclaration.typeParameters) {
446446
for (const param of classDeclaration.typeParameters.params) {
447-
genericTypes[param.name.name] = { type: param.constraint };
447+
genericTypes[param.name.name] = { type: param.constraint, default: param.default };
448448
}
449449
}
450450
return genericTypes;

lib/parse/ParameterLoader.ts

+14
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ export class ParameterLoader {
128128
genericTypeParameters,
129129
genericName,
130130
genericType.type,
131+
genericType.default,
131132
);
132133
}
133134

@@ -143,12 +144,14 @@ export class ParameterLoader {
143144
* @param genericTypeParameters The array of generic type parameters that will be appended to.
144145
* @param genericName The generic type name.
145146
* @param genericType The optional generic type range.
147+
* @param genericDefault The optional generic default value.
146148
*/
147149
public loadClassGeneric(
148150
classLoaded: ClassReferenceLoaded,
149151
genericTypeParameters: GenericTypeParameterData<ParameterRangeUnresolved>[],
150152
genericName: string,
151153
genericType: TSESTree.TypeNode | undefined,
154+
genericDefault: TSESTree.TypeNode | undefined,
152155
): void {
153156
genericTypeParameters.push({
154157
name: genericName,
@@ -159,6 +162,13 @@ export class ParameterLoader {
159162
this.getErrorIdentifierGeneric(classLoaded, genericName),
160163
) } :
161164
{},
165+
...genericDefault ?
166+
{ default: this.getRangeFromTypeNode(
167+
classLoaded,
168+
genericDefault,
169+
this.getErrorIdentifierGeneric(classLoaded, genericName),
170+
) } :
171+
{},
162172
});
163173
}
164174

@@ -753,6 +763,10 @@ export interface GenericTypeParameterData<R> {
753763
* The range of the generic type parameter.
754764
*/
755765
range?: R;
766+
/**
767+
* The default value.
768+
*/
769+
default?: R;
756770
/**
757771
* The human-readable description of this parameter.
758772
*/

lib/parse/ParameterResolver.ts

+3
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,9 @@ export class ParameterResolver {
115115
range: generic.range ?
116116
await this.resolveRange(generic.range, owningClass, genericTypeRemappings, false, new Set()) :
117117
undefined,
118+
default: generic.default ?
119+
await this.resolveRange(generic.default, owningClass, genericTypeRemappings, false, new Set()) :
120+
undefined,
118121
})));
119122
}
120123

lib/serialize/ComponentConstructor.ts

+5
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,11 @@ export class ComponentConstructor {
472472
...genericType.range ?
473473
{ range: await this.constructParameterRange(genericType.range, context, externalContextsCallback, id) } :
474474
{},
475+
...genericType.default ?
476+
{
477+
default: await this.constructParameterRange(genericType.default, context, externalContextsCallback, id),
478+
} :
479+
{},
475480
});
476481
}
477482
return definitions;

lib/serialize/ComponentDefinitions.ts

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ export type ExtensionDefinition = string | {
3636
export interface GenericTypeParameterDefinition {
3737
'@id': string;
3838
range?: ParameterDefinitionRange;
39+
default?: ParameterDefinitionRange;
3940
}
4041

4142
export interface ParameterDefinition {

test/parse/GenericsLoader.test.ts

+37
Original file line numberDiff line numberDiff line change
@@ -119,5 +119,42 @@ describe('GenericsLoader', () => {
119119
},
120120
});
121121
});
122+
123+
it('should return for a single class with default generic types', async() => {
124+
resolutionContext.contentsOverrides = {
125+
'file.d.ts': `export class A<A, B extends number = 3>{
126+
constructor(){}
127+
}`,
128+
};
129+
const A = await classIndexer.loadClassChain({
130+
packageName: 'p',
131+
localName: 'A',
132+
fileName: 'file',
133+
fileNameReferenced: 'fileReferenced',
134+
});
135+
expect(parser.getGenerics({
136+
A,
137+
})).toEqual({
138+
A: {
139+
genericTypeParameters: [
140+
{
141+
name: 'A',
142+
},
143+
{
144+
name: 'B',
145+
range: {
146+
type: 'raw',
147+
value: 'number',
148+
},
149+
default: {
150+
type: 'literal',
151+
value: 3,
152+
},
153+
},
154+
],
155+
classLoaded: A,
156+
},
157+
});
158+
});
122159
});
123160
});

test/parse/ParameterResolver.test.ts

+14
Original file line numberDiff line numberDiff line change
@@ -184,6 +184,13 @@ describe('ParameterResolver', () => {
184184
value: 'number',
185185
},
186186
},
187+
{
188+
name: 'C',
189+
default: {
190+
type: 'literal',
191+
value: 3,
192+
},
193+
},
187194
], classReference, {})).resolves.toEqual([
188195
{
189196
name: 'A',
@@ -195,6 +202,13 @@ describe('ParameterResolver', () => {
195202
value: 'number',
196203
},
197204
},
205+
{
206+
name: 'C',
207+
default: {
208+
type: 'literal',
209+
value: 3,
210+
},
211+
},
198212
]);
199213
});
200214

test/serialize/ComponentConstructor.test.ts

+20
Original file line numberDiff line numberDiff line change
@@ -1137,6 +1137,26 @@ describe('ComponentConstructor', () => {
11371137
]);
11381138
});
11391139

1140+
it('should handle a constructor with a single generic with default', async() => {
1141+
await expect(ctor.constructGenericTypeParameters(context, externalContextsCallback, classReference, [
1142+
{
1143+
name: 'T',
1144+
default: {
1145+
type: 'literal',
1146+
value: 3,
1147+
},
1148+
},
1149+
])).resolves.toEqual([
1150+
{
1151+
'@id': 'mp:components/a/b/file-param.jsonld#MyClass__generic_T',
1152+
default: {
1153+
'@type': 'ParameterRangeLiteral',
1154+
parameterRangeValueLiteral: 3,
1155+
},
1156+
},
1157+
]);
1158+
});
1159+
11401160
it('should handle a constructor with a multiple generics', async() => {
11411161
await expect(ctor.constructGenericTypeParameters(context, externalContextsCallback, classReference, [
11421162
{

0 commit comments

Comments
 (0)