Skip to content

Commit

Permalink
Protobuf postprocessing: Use NodeFactory to create nodes
Browse files Browse the repository at this point in the history
Most `ts.create*` and `ts.update*` functions are deprecated as of
TypeScript 4.0.

See this pull request for more details:
microsoft/TypeScript#35282

Additionally, some API calls (especially `createImportClause`) needed to
be updated because apparently the API changed.
  • Loading branch information
threema-danilo committed Jan 4, 2023
1 parent b189826 commit 150b6f2
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 43 deletions.
58 changes: 32 additions & 26 deletions tools/generate-protobuf-postprocess.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@ const {
/**
* Convert interface name `IFoo` or `Foo` to `FooEncodable`.
*
* @param interface Interface name (`IFoo` or `Foo`).
* @param iface Interface name (`IFoo` or `Foo`).
* @returns Converted interface name (`FooEncodable`).
*/
function getEncodableInterfaceName(interface) {
function getEncodableInterfaceName(iface) {
const base =
interface.escapedText.match(/^I[A-Z]/u) !== null
? interface.escapedText.slice(1)
: interface.escapedText;
iface.escapedText.match(/^I[A-Z]/u) !== null
? iface.escapedText.slice(1)
: iface.escapedText;
return `${base}Encodable`;
}

Expand All @@ -28,9 +28,9 @@ function getEncodableInterfaceName(interface) {
* - Make all array properties `readonly`
* - Tag the interface with `tag.ProtobufMessage`
*/
function updateMessageInterface(interface) {
function updateMessageInterface(iface) {
// Make all array properties `readonly`
for (const member of interface.members) {
for (const member of iface.members) {
if (
member.type.kind !== ts.SyntaxKind.ParenthesizedType ||
member.type.type.kind !== ts.SyntaxKind.UnionType
Expand All @@ -43,16 +43,16 @@ function updateMessageInterface(interface) {
if (type.kind !== ts.SyntaxKind.ArrayType) {
continue;
}
union.types[i] = ts.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, type);
union.types[i] = ts.factory.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, type);
}
}

// Tag the interface with `tag.ProtobufMessage`
return createNewtypeNode(getEncodableInterfaceName(interface.name), interface, [
ts.createTypeReferenceNode(
ts.createQualifiedName(
ts.createIdentifier('tag'),
ts.createIdentifier('ProtobufMessage'),
return createNewtypeNode(getEncodableInterfaceName(iface.name), iface, [
ts.factory.createTypeReferenceNode(
ts.factory.createQualifiedName(
ts.factory.createIdentifier('tag'),
ts.factory.createIdentifier('ProtobufMessage'),
),
undefined,
),
Expand All @@ -74,7 +74,10 @@ function updateMessageClass(class_) {
member.kind === ts.SyntaxKind.PropertyDeclaration &&
member.type.kind === ts.SyntaxKind.ArrayType
) {
member.type = ts.createTypeOperatorNode(ts.SyntaxKind.ReadonlyKeyword, member.type);
member.type = ts.factory.createTypeOperatorNode(
ts.SyntaxKind.ReadonlyKeyword,
member.type,
);
}

// Update `encode` method interface reference
Expand All @@ -86,7 +89,7 @@ function updateMessageClass(class_) {
if (parameter.name.escapedText !== 'message') {
continue;
}
parameter.type.typeName.right = ts.createIdentifier(
parameter.type.typeName.right = ts.factory.createIdentifier(
getEncodableInterfaceName(parameter.type.typeName.right),
);
}
Expand All @@ -96,17 +99,20 @@ function updateMessageClass(class_) {

/**
* Create tag import (for `ProtobufMessage`).
*
* Output:
*
* import type * as tag from "../tag";
*/
function createTagImportNode() {
return ts.createImportDeclaration(
undefined,
return ts.factory.createImportDeclaration(
undefined,
ts.createImportClause(
undefined,
ts.createNamespaceImport(ts.createIdentifier('tag')),
ts.factory.createImportClause(
true,
ts.factory.createNamespaceImport(ts.factory.createIdentifier('tag')),
undefined,
),
ts.createStringLiteral('../tag'),
ts.factory.createStringLiteral('../tag'),
);
}

Expand Down Expand Up @@ -153,7 +159,8 @@ function updateMessageNamespaces(root, matchers) {

function main() {
// Parse source from stdin
const source = createSource('index.d.ts', fs.readFileSync(0, 'utf8'));
const sourceFromStdin = fs.readFileSync(0, 'utf8');
const source = createSource('index.d.ts', sourceFromStdin);

// Insert tag import
source.statements.unshift(createTagImportNode());
Expand All @@ -164,11 +171,10 @@ function main() {
// Insert 'Long' import
// TODO(WEBMD-48): To be removed once we make use of BigInt
source.statements.unshift(
ts.createImportDeclaration(
undefined,
ts.factory.createImportDeclaration(
undefined,
ts.createImportClause(ts.createIdentifier('Long'), undefined, true),
ts.createStringLiteral('long'),
ts.factory.createImportClause(true, ts.factory.createIdentifier('Long'), undefined),
ts.factory.createStringLiteral('long'),
),
);

Expand Down
39 changes: 22 additions & 17 deletions tools/generator-utils.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -33,17 +33,20 @@ function traverse(root, matchers, transform) {

/**
* Create types import (for `WeakOpaque`).
*
* Output:
*
* import type * as types from "~/common/types";
*/
function createTypesImportNode() {
return ts.createImportDeclaration(
undefined,
return ts.factory.createImportDeclaration(
undefined,
ts.createImportClause(
undefined,
ts.createNamespaceImport(ts.createIdentifier('types')),
ts.factory.createImportClause(
true,
ts.factory.createNamespaceImport(ts.factory.createIdentifier('types')),
undefined,
),
ts.createStringLiteral('~/common/types'),
ts.factory.createStringLiteral('~/common/types'),
);
}

Expand All @@ -56,24 +59,26 @@ function createTypesImportNode() {
* @returns a new-type node.
*/
function createNewtypeNode(name, target, tags) {
return ts.createTypeAliasDeclaration(
undefined,
return ts.factory.createTypeAliasDeclaration(
undefined,
name,
undefined,
ts.createTypeReferenceNode(
ts.createQualifiedName(ts.createIdentifier('types'), ts.createIdentifier('WeakOpaque')),
ts.factory.createTypeReferenceNode(
ts.factory.createQualifiedName(
ts.factory.createIdentifier('types'),
ts.factory.createIdentifier('WeakOpaque'),
),
[
ts.createTypeReferenceNode(target.name, undefined),
ts.createIntersectionTypeNode([
ts.createTypeLiteralNode([
ts.createPropertySignature(
[ts.createModifier(ts.SyntaxKind.ReadonlyKeyword)],
ts.factory.createTypeReferenceNode(target.name, undefined),
ts.factory.createIntersectionTypeNode([
ts.factory.createTypeLiteralNode([
ts.factory.createPropertySignature(
[ts.factory.createModifier(ts.SyntaxKind.ReadonlyKeyword)],
name,
undefined,
ts.createTypeOperatorNode(
ts.factory.createTypeOperatorNode(
ts.SyntaxKind.UniqueKeyword,
ts.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword),
ts.factory.createKeywordTypeNode(ts.SyntaxKind.SymbolKeyword),
),
undefined,
),
Expand Down

0 comments on commit 150b6f2

Please sign in to comment.