Skip to content

Commit

Permalink
#36, convert type node: PrefixOperators, QualifiedName.
Browse files Browse the repository at this point in the history
  • Loading branch information
ajvincent committed Jan 12, 2024
1 parent 3d824e8 commit e3c26d7
Show file tree
Hide file tree
Showing 3 changed files with 152 additions and 10 deletions.
58 changes: 58 additions & 0 deletions stage_1_integration/bootstrap/convertTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TemplateLiteralTypeNode,
TypeLiteralNode,
TypeNode,
TypeOperatorTypeNode,
TypeParameterDeclaration,
} from "ts-morph";

Expand All @@ -26,6 +27,8 @@ import {
MemberedObjectTypeStructureImpl,
ParameterTypeStructureImpl,
ParenthesesTypeStructureImpl,
PrefixOperatorsTypeStructureImpl,
PrefixUnaryOperator,
QualifiedNameTypeStructureImpl,
StringTypeStructureImpl,
TemplateLiteralTypeStructureImpl,
Expand Down Expand Up @@ -137,6 +140,16 @@ export default function convertTypeNode(
return new ParenthesesTypeStructureImpl(childStructure);
}

// PrefixOperators
if (Node.isTypeOperatorTypeNode(typeNode)) {
return convertTypeOperatorNode(typeNode, consoleTrap, subStructureResolver);
}

if (Node.isTypeQuery(typeNode)) {
const structure = buildStructureForEntityName(typeNode.getExprName());
return prependPrefixOperator("typeof", structure);
}

if (Node.isTemplateLiteralTypeNode(typeNode)) {
return convertTemplateLiteralTypeNode(typeNode, consoleTrap, subStructureResolver);
}
Expand Down Expand Up @@ -519,6 +532,51 @@ function convertTypeLiteralNode(
return structure;
}

function convertTypeOperatorNode(
typeNode: TypeOperatorTypeNode,
consoleTrap: TypeNodeToTypeStructureConsole,
subStructureResolver: SubstructureResolver,
): PrefixOperatorsTypeStructureImpl | null
{
const structure = convertTypeNode(
typeNode.getTypeNode(),
consoleTrap,
subStructureResolver,
);
if (!structure)
return null;

switch (typeNode.getOperator()) {
case SyntaxKind.ReadonlyKeyword:
return prependPrefixOperator("readonly", structure);

case SyntaxKind.KeyOfKeyword:
return prependPrefixOperator("keyof", structure);

case SyntaxKind.UniqueKeyword:
return prependPrefixOperator("unique", structure);

// no other possibilities
default:
return null;
}
}

function prependPrefixOperator(
operator: PrefixUnaryOperator,
typeStructure: string | TypeStructures
): PrefixOperatorsTypeStructureImpl
{
if (typeStructure instanceof PrefixOperatorsTypeStructureImpl) {
typeStructure.operators.unshift(operator);
return typeStructure;
}

return new PrefixOperatorsTypeStructureImpl(
[operator], typeStructure
);
}

function convertAndAppendChildTypes(
childTypeNodes: readonly TypeNode[],
elements: (string | TypeStructures)[],
Expand Down
58 changes: 58 additions & 0 deletions stage_2_fullset/snapshot/source/bootstrap/convertTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
TemplateLiteralTypeNode,
TypeLiteralNode,
TypeNode,
TypeOperatorTypeNode,
TypeParameterDeclaration,
} from "ts-morph";

Expand All @@ -26,6 +27,8 @@ import {
MemberedObjectTypeStructureImpl,
ParameterTypeStructureImpl,
ParenthesesTypeStructureImpl,
PrefixOperatorsTypeStructureImpl,
PrefixUnaryOperator,
QualifiedNameTypeStructureImpl,
StringTypeStructureImpl,
TemplateLiteralTypeStructureImpl,
Expand Down Expand Up @@ -137,6 +140,16 @@ export default function convertTypeNode(
return new ParenthesesTypeStructureImpl(childStructure);
}

// PrefixOperators
if (Node.isTypeOperatorTypeNode(typeNode)) {
return convertTypeOperatorNode(typeNode, consoleTrap, subStructureResolver);
}

if (Node.isTypeQuery(typeNode)) {
const structure = buildStructureForEntityName(typeNode.getExprName());
return prependPrefixOperator("typeof", structure);
}

if (Node.isTemplateLiteralTypeNode(typeNode)) {
return convertTemplateLiteralTypeNode(typeNode, consoleTrap, subStructureResolver);
}
Expand Down Expand Up @@ -519,6 +532,51 @@ function convertTypeLiteralNode(
return structure;
}

function convertTypeOperatorNode(
typeNode: TypeOperatorTypeNode,
consoleTrap: TypeNodeToTypeStructureConsole,
subStructureResolver: SubstructureResolver,
): PrefixOperatorsTypeStructureImpl | null
{
const structure = convertTypeNode(
typeNode.getTypeNode(),
consoleTrap,
subStructureResolver,
);
if (!structure)
return null;

switch (typeNode.getOperator()) {
case SyntaxKind.ReadonlyKeyword:
return prependPrefixOperator("readonly", structure);

case SyntaxKind.KeyOfKeyword:
return prependPrefixOperator("keyof", structure);

case SyntaxKind.UniqueKeyword:
return prependPrefixOperator("unique", structure);

// no other possibilities
default:
return null;
}
}

function prependPrefixOperator(
operator: PrefixUnaryOperator,
typeStructure: string | TypeStructures
): PrefixOperatorsTypeStructureImpl
{
if (typeStructure instanceof PrefixOperatorsTypeStructureImpl) {
typeStructure.operators.unshift(operator);
return typeStructure;
}

return new PrefixOperatorsTypeStructureImpl(
[operator], typeStructure
);
}

function convertAndAppendChildTypes(
childTypeNodes: readonly TypeNode[],
elements: (string | TypeStructures)[],
Expand Down
46 changes: 36 additions & 10 deletions stage_2_fullset/spec-snapshot/source/bootstrap/convertTypeNode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ import {
MappedTypeStructureImpl,
MemberedObjectTypeStructureImpl,
ParenthesesTypeStructureImpl,
PrefixOperatorsTypeStructureImpl,
QualifiedNameTypeStructureImpl,
StringTypeStructureImpl,
TemplateLiteralTypeStructureImpl,
TupleTypeStructureImpl,
Expand Down Expand Up @@ -133,16 +135,6 @@ let A: string;
expect(failNode).toBeNull();
});

it(`string literal "foo"`, () => {
setTypeStructure(`"foo"`, failCallback);
expect(structure).toBeInstanceOf(StringTypeStructureImpl);
if (structure instanceof StringTypeStructureImpl) {
expect(structure.stringValue).toBe("foo");
}
expect(failMessage).toBe(undefined);
expect(failNode).toBe(null);
});

it(`identifier (NumberStringType)`, () => {
setTypeStructure(`NumberStringType`, failCallback);
expect(structure).toBe("NumberStringType");
Expand Down Expand Up @@ -369,6 +361,40 @@ let A: string;
expect(failNode).toBeNull();
});

it("PrefixOperators: keyof typeof NumberStringClass", () => {
setTypeStructure(`keyof typeof NumberStringClass`, failCallback);
expect(structure).toBeInstanceOf(PrefixOperatorsTypeStructureImpl);
if (!(structure instanceof PrefixOperatorsTypeStructureImpl))
return;
expect(structure.operators).toEqual(["keyof", "typeof"]);
expect(structure.objectType).toBe("NumberStringClass");
expect(failMessage).toBe(undefined);
expect(failNode).toBe(null);
});

it(`QualifiedName: NumberEnum.one`, () => {
setTypeStructure(`NumberEnum.one`, failCallback);
expect(structure).toBeInstanceOf(QualifiedNameTypeStructureImpl);

if (structure instanceof QualifiedNameTypeStructureImpl) {
expect(structure.childTypes.length).toBe(2);
expect(structure.childTypes[0]).toBe("NumberEnum");
expect(structure.childTypes[1]).toBe("one");
}
expect(failMessage).toBe(undefined);
expect(failNode).toBe(null);
});

it(`String: string literal "foo"`, () => {
setTypeStructure(`"foo"`, failCallback);
expect(structure).toBeInstanceOf(StringTypeStructureImpl);
if (structure instanceof StringTypeStructureImpl) {
expect(structure.stringValue).toBe("foo");
}
expect(failMessage).toBe(undefined);
expect(failNode).toBe(null);
});

it('TemplateLiteral: `one${"A" | "B"}two${"C" | "D"}three${"E" | "F"}` (template literal)', () => {
setTypeStructure('`one${"A" | "B"}two${"C" | "D"}three${"E" | "F"}`', failCallback);
expect(structure).toBeInstanceOf(TemplateLiteralTypeStructureImpl);
Expand Down

0 comments on commit e3c26d7

Please sign in to comment.