Skip to content

Commit

Permalink
Add parser support for satisfies operator
Browse files Browse the repository at this point in the history
  • Loading branch information
nicolo-ribaudo committed Aug 31, 2022
1 parent b65e3ba commit 816b009
Show file tree
Hide file tree
Showing 7 changed files with 144 additions and 10 deletions.
32 changes: 22 additions & 10 deletions packages/babel-parser/src/plugins/typescript/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2554,23 +2554,35 @@ export default (superClass: ClassWithMixin<typeof Parser, IJSXParserMixin>) =>
leftStartLoc: Position,
minPrec: number,
): N.Expression {
let isSatisfies: boolean;
if (
tokenOperatorPrecedence(tt._in) > minPrec &&
!this.hasPrecedingLineBreak() &&
this.isContextual(tt._as)
(this.isContextual(tt._as) ||
(isSatisfies = this.isContextual(tt._satisfies)))
) {
const node = this.startNodeAt<N.TsAsExpression>(
leftStartPos,
leftStartLoc,
);
const node = this.startNodeAt<
N.TsAsExpression | N.TsSatisfiesExpression
>(leftStartPos, leftStartLoc);
node.expression = left;
node.typeAnnotation = this.tsInType(() => {
this.next(); // "as"
return this.match(tt._const)
? this.tsParseTypeReference()
: this.tsParseType();
this.next(); // "as" or "satisfies"
if (this.match(tt._const)) {
if (isSatisfies) {
this.raise(Errors.UnexpectedKeyword, {
at: this.state.startLoc,
keyword: "const",
});
}
return this.tsParseTypeReference();
}

return this.tsParseType();
});
this.finishNode(node, "TSAsExpression");
this.finishNode(
node,
isSatisfies ? "TSSatisfiesExpression" : "TSAsExpression",
);
// rescan `<`, `>` because they were scanned when this.state.inType was true
this.reScan_lt_gt();
return this.parseExprOp(
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/tokenizer/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ export const tt: InternalTokenTypes = {
_mixins: createKeywordLike("mixins", { startsExpr }),
_proto: createKeywordLike("proto", { startsExpr }),
_require: createKeywordLike("require", { startsExpr }),
_satisfies: createKeywordLike("satisfies", { startsExpr }),
// start: isTSTypeOperator
_keyof: createKeywordLike("keyof", { startsExpr }),
_readonly: createKeywordLike("readonly", { startsExpr }),
Expand Down
4 changes: 4 additions & 0 deletions packages/babel-parser/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1639,6 +1639,10 @@ export interface TsTypeAssertion extends TsTypeAssertionLikeBase {
type: "TSTypeAssertion";
}

export type TsSatisfiesExpression = TsTypeAssertionLikeBase & {
type: "TSSatisfiesExpression";
};

export interface TsNonNullExpression extends NodeBase {
type: "TSNonNullExpression";
expression: Expression;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
x satisfies const
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{
"type": "File",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"errors": [
"SyntaxError: Unexpected keyword 'const'. (1:12)"
],
"program": {
"type": "Program",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"expression": {
"type": "TSSatisfiesExpression",
"start":0,"end":17,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":17,"index":17}},
"expression": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1},"identifierName":"x"},
"name": "x"
},
"typeAnnotation": {
"type": "TSTypeReference",
"start":12,"end":17,"loc":{"start":{"line":1,"column":12,"index":12},"end":{"line":1,"column":17,"index":17}},
"typeName": {
"type": "Identifier",
"start":12,"end":17,"loc":{"start":{"line":1,"column":12,"index":12},"end":{"line":1,"column":17,"index":17},"identifierName":"const"},
"name": "const"
}
}
}
}
],
"directives": []
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
x satisfies T;
x < y satisfies boolean; // (x < y) satisfies boolean;
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
{
"type": "File",
"start":0,"end":69,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":54,"index":69}},
"program": {
"type": "Program",
"start":0,"end":69,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":2,"column":54,"index":69}},
"sourceType": "module",
"interpreter": null,
"body": [
{
"type": "ExpressionStatement",
"start":0,"end":14,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":14,"index":14}},
"expression": {
"type": "TSSatisfiesExpression",
"start":0,"end":13,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":13,"index":13}},
"expression": {
"type": "Identifier",
"start":0,"end":1,"loc":{"start":{"line":1,"column":0,"index":0},"end":{"line":1,"column":1,"index":1},"identifierName":"x"},
"name": "x"
},
"typeAnnotation": {
"type": "TSTypeReference",
"start":12,"end":13,"loc":{"start":{"line":1,"column":12,"index":12},"end":{"line":1,"column":13,"index":13}},
"typeName": {
"type": "Identifier",
"start":12,"end":13,"loc":{"start":{"line":1,"column":12,"index":12},"end":{"line":1,"column":13,"index":13},"identifierName":"T"},
"name": "T"
}
}
}
},
{
"type": "ExpressionStatement",
"start":15,"end":39,"loc":{"start":{"line":2,"column":0,"index":15},"end":{"line":2,"column":24,"index":39}},
"expression": {
"type": "TSSatisfiesExpression",
"start":15,"end":38,"loc":{"start":{"line":2,"column":0,"index":15},"end":{"line":2,"column":23,"index":38}},
"expression": {
"type": "BinaryExpression",
"start":15,"end":20,"loc":{"start":{"line":2,"column":0,"index":15},"end":{"line":2,"column":5,"index":20}},
"left": {
"type": "Identifier",
"start":15,"end":16,"loc":{"start":{"line":2,"column":0,"index":15},"end":{"line":2,"column":1,"index":16},"identifierName":"x"},
"name": "x"
},
"operator": "<",
"right": {
"type": "Identifier",
"start":19,"end":20,"loc":{"start":{"line":2,"column":4,"index":19},"end":{"line":2,"column":5,"index":20},"identifierName":"y"},
"name": "y"
}
},
"typeAnnotation": {
"type": "TSBooleanKeyword",
"start":31,"end":38,"loc":{"start":{"line":2,"column":16,"index":31},"end":{"line":2,"column":23,"index":38}}
}
},
"trailingComments": [
{
"type": "CommentLine",
"value": " (x < y) satisfies boolean;",
"start":40,"end":69,"loc":{"start":{"line":2,"column":25,"index":40},"end":{"line":2,"column":54,"index":69}}
}
]
}
],
"directives": []
},
"comments": [
{
"type": "CommentLine",
"value": " (x < y) satisfies boolean;",
"start":40,"end":69,"loc":{"start":{"line":2,"column":25,"index":40},"end":{"line":2,"column":54,"index":69}}
}
]
}

0 comments on commit 816b009

Please sign in to comment.