Skip to content

Commit

Permalink
feature: implement constructor type
Browse files Browse the repository at this point in the history
  • Loading branch information
mistlog committed Mar 12, 2021
1 parent 36368d9 commit 259c1a4
Show file tree
Hide file tree
Showing 8 changed files with 74 additions and 3 deletions.
6 changes: 4 additions & 2 deletions src/generator/generator.ts
Expand Up @@ -183,10 +183,12 @@ function tsArrayType(ast: IArrayType): t.TSArrayType {
return _tsArrayType(TSType(ast.elementType), ast.dimension);
}

function tsFunctionType(ast: IFunctionType): t.TSFunctionType {
function tsFunctionType(ast: IFunctionType): t.TSFunctionType | t.TSConstructorType {
const params = tsFunctionParams(ast.params);
const typeParams = ast.typeParams ? tsTypeParameterDeclaration(ast.typeParams) : null;
return t.tsFunctionType(typeParams, params, t.tsTypeAnnotation(TSType(ast.returnType)));
const args = [typeParams, params, t.tsTypeAnnotation(TSType(ast.returnType))] as const;
const type = ast.isConstructor ? t.tsConstructorType(...args) : t.tsFunctionType(...args);
return type;
}

function tsFunctionParams(params: IFunctionTypeParam[]) {
Expand Down
9 changes: 8 additions & 1 deletion src/parser/function/function.tsx
Expand Up @@ -8,10 +8,11 @@ export interface IFunctionType {
params: IFunctionTypeParam[]
returnType: ITypeExpression
typeParams?: IParamList
isConstructor?: boolean
}

export function FunctionType() {
const action = ({ params, returnType, typeParams }): IFunctionType => {
const action = ({ params, returnType, typeParams, isConstructor }): IFunctionType => {
const type: IFunctionType = {
kind: "FunctionType",
params,
Expand All @@ -20,12 +21,18 @@ export function FunctionType() {
if (typeParams) {
type.typeParams = typeParams
}
if (isConstructor) {
type.isConstructor = true;
}
return type
}

return (
<pattern action={action}>
{Text("type")}
<opt label="isConstructor">
{Text("new")}
</opt>
<_ />
<opt label="typeParams">
<pattern action={({ typeParams }) => typeParams}>
Expand Down
2 changes: 2 additions & 0 deletions test/__snapshots__/generator.test.ts.snap
Expand Up @@ -88,6 +88,8 @@ exports[`ts-type ConditionalTypeExpression: 2 1`] = `"T extends string ? \\"stri
exports[`ts-type FunctionType 1`] = `"() => void"`;
exports[`ts-type FunctionType: constructor 1`] = `"new (...arg: any) => any"`;
exports[`ts-type FunctionType: nested 1`] = `"() => (a: number, b: string) => void"`;
exports[`ts-type FunctionType: optional param 1`] = `"(a: number, b?: string) => number"`;
Expand Down
22 changes: 22 additions & 0 deletions test/assets/ast/FunctionType-Constructor.json
@@ -0,0 +1,22 @@
{
"kind": "FunctionType",
"params": [
{
"kind": "FunctionTypeParam",
"name": {
"kind": "Identifier",
"name": "arg"
},
"type": {
"kind": "AnyType",
"value": "any"
},
"rest": true
}
],
"returnType": {
"kind": "AnyType",
"value": "any"
},
"isConstructor": true
}
1 change: 1 addition & 0 deletions test/assets/ts-type/FunctionType-Constructor
@@ -0,0 +1 @@
new (...arg: any) => any
5 changes: 5 additions & 0 deletions test/generator.test.ts
Expand Up @@ -88,6 +88,11 @@ describe("ts-type", () => {
expect(toCode(name)).toMatchSnapshot();
})

test("FunctionType: constructor", () => {
const name = "FunctionType-Constructor";
expect(toCode(name)).toMatchSnapshot();
})

test("FunctionType: optional param", () => {
const name = "FunctionType-OptionalParam";
expect(toCode(name)).toMatchSnapshot();
Expand Down
25 changes: 25 additions & 0 deletions test/parser/__snapshots__/function.test.tsx.snap
Expand Up @@ -11,6 +11,31 @@ Object {
}
`;

exports[`parser: function FunctionType: constructor 1`] = `
Object {
"isConstructor": true,
"kind": "FunctionType",
"params": Array [
Object {
"kind": "FunctionTypeParam",
"name": Object {
"kind": "Identifier",
"name": "arg",
},
"rest": true,
"type": Object {
"kind": "AnyType",
"value": "any",
},
},
],
"returnType": Object {
"kind": "AnyType",
"value": "any",
},
}
`;

exports[`parser: function FunctionType: nested 1`] = `
Object {
"kind": "FunctionType",
Expand Down
7 changes: 7 additions & 0 deletions test/parser/function.test.tsx
Expand Up @@ -10,6 +10,13 @@ describe("parser: function", () => {
expect(ast).toMatchSnapshot();
})

test("FunctionType: constructor", () => {
const parser = ReactPeg.render(<TypeExpression />);
const ast = parser.parse(`type new (...arg: any) => any`);
saveAST(ast, "FunctionType-Constructor.json");
expect(ast).toMatchSnapshot();
})

test("FunctionType: optional param", () => {
const parser = ReactPeg.render(<TypeExpression />);
const ast = parser.parse(`type (a:number, b?: string) => number`);
Expand Down

0 comments on commit 259c1a4

Please sign in to comment.