Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
cce9164
Add `properties` of `ObjectLiteralExpression` in the API
virtulis Mar 21, 2026
ab1154a
Fix typing error in #3029
virtulis Mar 21, 2026
b491b96
Fix IntersectionType encoding
virtulis Mar 22, 2026
c533e9a
Make isTypeNode true for KeywordTypeNode
virtulis Mar 22, 2026
1e59b82
Fix HeritageClause token encoding
virtulis Mar 22, 2026
be3dd16
Cleanup
virtulis Mar 22, 2026
5a7fc65
Add ArrayType elementType
virtulis Mar 22, 2026
0511837
Fix cast
virtulis Mar 22, 2026
e9f4b5e
Reorder to align with #3085
virtulis Mar 22, 2026
76e52ad
Undo pointless single-child listing
virtulis Mar 23, 2026
c28c33c
Let Printer emit UndefinedKeyword
virtulis Mar 23, 2026
23e5d18
Merge branch 'main' into object-literal-fix
virtulis Mar 23, 2026
2b3f328
Merge branch 'main' into object-literal-fix
virtulis Mar 25, 2026
e24e4f1
Roundtrip test on original TS sources
virtulis Mar 25, 2026
e4968aa
Return an empty "node list" for required node properties
virtulis Mar 25, 2026
3050728
Ensure CaseOrDefaultClause always has statements
virtulis Mar 25, 2026
baaccea
Undo erroneous change
virtulis Mar 25, 2026
6bbcb97
Modify test to check for the actually optional property
virtulis Mar 25, 2026
6b79aec
Merge branch 'main' into object-literal-fix
virtulis Mar 25, 2026
736f9c9
Exceptions for required properties
virtulis Mar 25, 2026
36558e9
Merge branch 'main' into object-literal-fix
virtulis Mar 26, 2026
38155a5
Just print the whole error
virtulis Mar 26, 2026
f8f6c12
Add other valid BinaryOperator kinds
virtulis Mar 26, 2026
156cc48
Single roundtrip test, compare output word-for-word
virtulis Mar 26, 2026
0c62194
Encode TypeOperator kind
virtulis Mar 26, 2026
0de21ec
This does look like an error (untested)
virtulis Mar 26, 2026
3394d08
Merge branch 'main' into object-literal-fix
virtulis Mar 26, 2026
bbf15b5
Sync test
virtulis Mar 26, 2026
b2e4d83
Revert an oops
virtulis Mar 26, 2026
24c2a0f
Merge branch 'main' into object-literal-fix
virtulis Mar 28, 2026
ab3c35b
Merge branch 'main' into object-literal-fix
virtulis Mar 31, 2026
5e58898
Fix wrong sync api merge
virtulis Mar 31, 2026
2b25cce
Fix SpreadAssignment encoding
virtulis Mar 31, 2026
7112e17
Fix generateFactory instead
virtulis Mar 31, 2026
1694332
Preserve VariableDeclarationList flags (const/let) in factory/clone
virtulis Mar 31, 2026
d5c778b
Roundtrip test fixes
virtulis Mar 31, 2026
49fb899
Add decoding of empty node types
virtulis Mar 31, 2026
1201160
Allow extra JSDoc children in single-child nodes
virtulis Mar 31, 2026
d2c6e18
Merge branch 'main' into object-literal-fix
virtulis Mar 31, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions _packages/api/src/node/encoder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import type {
ExportDeclaration,
ExportSpecifier,
FileReference,
HeritageClause,
ImportAttributes,
ImportClause,
ImportEqualsDeclaration,
Expand All @@ -22,6 +23,7 @@ import type {
PrefixUnaryExpression,
SourceFile,
TemplateLiteralLikeNode,
TypeOperatorNode,
} from "@typescript/ast";
import {
NodeFlags,
Expand All @@ -44,6 +46,7 @@ import {
NODE_DATA_TYPE_STRING,
NODE_LEN,
PROTOCOL_VERSION,
typeOperatorKinds,
} from "./protocol.ts";

const NODE_FIELDS = NODE_LEN / 4;
Expand Down Expand Up @@ -171,6 +174,12 @@ function getNodeDefinedData(node: Node): number {
return ((attrs.multiLine ? 1 : 0) << 24) |
((attrs.token === SyntaxKind.AssertKeyword ? 1 : 0) << 25);
}
case SyntaxKind.HeritageClause: {
const attrs = node as HeritageClause;
return (attrs.token === SyntaxKind.ExtendsKeyword ? 1 : 0) << 24;
}
case SyntaxKind.TypeOperator:
return Math.max(typeOperatorKinds.indexOf((node as TypeOperatorNode).operator), 0) << 24;
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
return ((node as PrefixUnaryExpression | PostfixUnaryExpression).operator & 0x3f) << 24;
Expand Down
52 changes: 36 additions & 16 deletions _packages/api/src/node/node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import {
NODE_DATA_TYPE_EXTENDED,
NODE_DATA_TYPE_STRING,
NODE_LEN,
typeOperatorKinds,
} from "./protocol.ts";

const popcount8 = [0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 1, 2, 2, 3, 2, 3, 3, 4, 2, 3, 3, 4, 3, 4, 4, 5, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 2, 3, 3, 4, 3, 4, 4, 5, 3, 4, 4, 5, 4, 5, 5, 6, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 3, 4, 4, 5, 4, 5, 5, 6, 4, 5, 5, 6, 5, 6, 6, 7, 4, 5, 5, 6, 5, 6, 6, 7, 5, 6, 6, 7, 6, 7, 7, 8];
Expand Down Expand Up @@ -317,6 +318,13 @@ export class RemoteNodeList extends Array<RemoteNode> implements NodeArray<Remot
}
}

// This cannot be an actual RemoteNodeList because we have nowhere to point to in the data
function createStubNodeList() {
const array = [] as unknown as any[] & { pos: number; end: number; };
array.pos = array.end = -1;
Comment thread
virtulis marked this conversation as resolved.
return array as RemoteNodeList;
}

export class RemoteNode extends RemoteNodeBase implements Node {
protected static NODE_LEN: number = NODE_LEN;
protected override get sourceFile(): RemoteSourceFile {
Expand Down Expand Up @@ -413,17 +421,20 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return nextNodeParent === this.index;
}

private getNamedChild(propertyName: string): RemoteNode | RemoteNodeList | undefined {
private getNamedChild(propertyName: string, required = false): RemoteNode | RemoteNodeList | undefined {
const propertyNames = childProperties[this.kind];
if (!propertyNames) {
// `childProperties` is only defined for nodes with more than one child property.
// Get the only child if it exists.
if (!this.hasChildren()) {
return undefined;
return required ? createStubNodeList() : undefined;
}
const child = this.getOrCreateChildAtNodeIndex(this.index + 1);
if (child.next !== 0) {
throw new Error("Expected only one child");
const next = this.getOrCreateChildAtNodeIndex(child.next);
if (!(next instanceof RemoteNode) || next.kind != SyntaxKind.JSDoc) {
throw new Error("Expected only one child");
}
}
return child;
}
Expand All @@ -447,8 +458,10 @@ export class RemoteNode extends RemoteNodeBase implements Node {
switch (propertyName) {
case "name":
order = this.isNameFirst ? 1 : 2;
break;
case "typeExpression":
order = this.isNameFirst ? 2 : 1;
break;
}
}
// Node kind does not have this property
Expand All @@ -457,7 +470,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
const mask = this.childMask;
if (!(mask & (1 << order))) {
// Property is not present
return undefined;
return required ? createStubNodeList() : undefined;
}

// The property index is `order`, minus the number of zeros in the mask that are in bit positions less
Expand Down Expand Up @@ -619,6 +632,8 @@ export class RemoteNode extends RemoteNodeBase implements Node {
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
return ((this.data >> 24) & 0x3f) as SyntaxKind;
case SyntaxKind.TypeOperator:
return typeOperatorKinds[(this.data >> 24) & 3];
}
}

Expand All @@ -630,7 +645,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("argumentExpression") as RemoteNode;
}
get arguments(): RemoteNodeList | undefined {
return this.getNamedChild("arguments") as RemoteNodeList;
return this.getNamedChild("arguments", this.kind != SyntaxKind.NewExpression) as RemoteNodeList;
}
get assertsModifier(): RemoteNode | undefined {
return this.getNamedChild("assertsModifier") as RemoteNode;
Expand Down Expand Up @@ -660,13 +675,13 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("checkType") as RemoteNode;
}
get children(): RemoteNodeList | undefined {
return this.getNamedChild("children") as RemoteNodeList;
return this.getNamedChild("children", true) as RemoteNodeList;
}
get class(): RemoteNode | undefined {
return this.getNamedChild("class") as RemoteNode;
}
get clauses(): RemoteNodeList | undefined {
return this.getNamedChild("clauses") as RemoteNodeList;
return this.getNamedChild("clauses", true) as RemoteNodeList;
}
get closingElement(): RemoteNode | undefined {
return this.getNamedChild("closingElement") as RemoteNode;
Expand All @@ -690,7 +705,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("declarationList") as RemoteNode;
}
get declarations(): RemoteNodeList | undefined {
return this.getNamedChild("declarations") as RemoteNodeList;
return this.getNamedChild("declarations", true) as RemoteNodeList;
}
get default(): RemoteNode | undefined {
return this.getNamedChild("default") as RemoteNode;
Expand All @@ -702,7 +717,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("elementType") as RemoteNode;
}
get elements(): RemoteNodeList | undefined {
return this.getNamedChild("elements") as RemoteNodeList;
return this.getNamedChild("elements", true) as RemoteNodeList;
}
get elseStatement(): RemoteNode | undefined {
return this.getNamedChild("elseStatement") as RemoteNode;
Expand Down Expand Up @@ -771,7 +786,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("literal") as RemoteNode;
}
get members(): RemoteNodeList | undefined {
return this.getNamedChild("members") as RemoteNodeList;
return this.getNamedChild("members", this.kind != SyntaxKind.MappedType) as RemoteNodeList;
}
get modifiers(): RemoteNodeList | undefined {
return this.getNamedChild("modifiers") as RemoteNodeList;
Expand Down Expand Up @@ -817,13 +832,13 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("parameterName") as RemoteNode;
}
get parameters(): RemoteNodeList | undefined {
return this.getNamedChild("parameters") as RemoteNodeList;
return this.getNamedChild("parameters", true) as RemoteNodeList;
}
get postfixToken(): RemoteNode | undefined {
return this.getNamedChild("postfixToken") as RemoteNode;
}
get properties(): RemoteNodeList | undefined {
return this.getNamedChild("properties") as RemoteNodeList;
return this.getNamedChild("properties", true) as RemoteNodeList;
}
get propertyName(): RemoteNode | undefined {
return this.getNamedChild("propertyName") as RemoteNode;
Expand All @@ -847,7 +862,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("statement") as RemoteNode;
}
get statements(): RemoteNodeList | undefined {
return this.getNamedChild("statements") as RemoteNodeList;
return this.getNamedChild("statements", true) as RemoteNodeList;
}
get tag(): RemoteNode | undefined {
return this.getNamedChild("tag") as RemoteNode;
Expand All @@ -862,7 +877,7 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("template") as RemoteNode;
}
get templateSpans(): RemoteNodeList | undefined {
return this.getNamedChild("templateSpans") as RemoteNodeList;
return this.getNamedChild("templateSpans", true) as RemoteNodeList;
}
get thenStatement(): RemoteNode | undefined {
return this.getNamedChild("thenStatement") as RemoteNode;
Expand All @@ -889,10 +904,10 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return this.getNamedChild("typeParameter") as RemoteNode;
}
get typeParameters(): RemoteNodeList | undefined {
return this.getNamedChild("typeParameters") as RemoteNodeList;
return this.getNamedChild("typeParameters", this.kind == SyntaxKind.JSDocTemplateTag) as RemoteNodeList;
}
get types(): RemoteNodeList | undefined {
return this.getNamedChild("types") as RemoteNodeList;
return this.getNamedChild("types", true) as RemoteNodeList;
}
get value(): RemoteNode | undefined {
return this.getNamedChild("value") as RemoteNode;
Expand Down Expand Up @@ -1071,6 +1086,11 @@ export class RemoteNode extends RemoteNodeBase implements Node {
return SyntaxKind.AssertKeyword;
}
return SyntaxKind.WithKeyword;
case SyntaxKind.HeritageClause:
if ((this.data & 1 << 24) !== 0) {
return SyntaxKind.ExtendsKeyword;
}
return SyntaxKind.ImplementsKeyword;
}
}

Expand Down
3 changes: 2 additions & 1 deletion _packages/api/src/node/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ export const childProperties: Readonly<Partial<Record<SyntaxKind, readonly strin
[SyntaxKind.TaggedTemplateExpression]: ["tag", "questionDotToken", "typeArguments", "template"],
[SyntaxKind.PropertyAssignment]: ["modifiers", "name", "postfixToken", "initializer"],
[SyntaxKind.ShorthandPropertyAssignment]: ["modifiers", "name", "postfixToken", "equalsToken", "objectAssignmentInitializer"],
[SyntaxKind.SpreadAssignment]: ["expression"],
[SyntaxKind.TypeAssertionExpression]: ["type", "expression"],
[SyntaxKind.ConditionalType]: ["checkType", "extendsType", "trueType", "falseType"],
[SyntaxKind.IndexedAccessType]: ["objectType", "indexType"],
Expand Down Expand Up @@ -150,3 +149,5 @@ export const childProperties: Readonly<Partial<Record<SyntaxKind, readonly strin
[SyntaxKind.JSDocPropertyTag]: [undefined!, undefined!],
[SyntaxKind.JSDocParameterTag]: ["tagName", undefined!, undefined!, "comment"],
};

export const typeOperatorKinds: SyntaxKind[] = [SyntaxKind.Unknown, SyntaxKind.KeyOfKeyword, SyntaxKind.UniqueKeyword, SyntaxKind.ReadonlyKeyword];
Loading