Add asserts this [is type] parsing support (#10677)
This commit is contained in:
@@ -680,6 +680,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishNode(node, "TSLiteralType");
|
||||
}
|
||||
|
||||
tsParseThisTypeOrThisTypePredicate(): N.TsThisType | N.TsTypePredicate {
|
||||
const thisKeyword = this.tsParseThisTypeNode();
|
||||
if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
|
||||
return this.tsParseThisTypePredicate(thisKeyword);
|
||||
} else {
|
||||
return thisKeyword;
|
||||
}
|
||||
}
|
||||
|
||||
tsParseNonArrayType(): N.TsType {
|
||||
switch (this.state.type) {
|
||||
case tt.name:
|
||||
@@ -715,14 +724,8 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishNode(node, "TSLiteralType");
|
||||
}
|
||||
break;
|
||||
case tt._this: {
|
||||
const thisKeyword = this.tsParseThisTypeNode();
|
||||
if (this.isContextual("is") && !this.hasPrecedingLineBreak()) {
|
||||
return this.tsParseThisTypePredicate(thisKeyword);
|
||||
} else {
|
||||
return thisKeyword;
|
||||
}
|
||||
}
|
||||
case tt._this:
|
||||
return this.tsParseThisTypeOrThisTypePredicate();
|
||||
case tt._typeof:
|
||||
return this.tsParseTypeQuery();
|
||||
case tt._import:
|
||||
@@ -937,6 +940,24 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.tsParseTypePredicateAsserts.bind(this),
|
||||
);
|
||||
|
||||
if (asserts && this.match(tt._this)) {
|
||||
// When asserts is false, thisKeyword is handled by tsParseNonArrayType
|
||||
// : asserts this is type
|
||||
let thisTypePredicate = this.tsParseThisTypeOrThisTypePredicate();
|
||||
// if it turns out to be a `TSThisType`, wrap it with `TSTypePredicate`
|
||||
// : asserts this
|
||||
if (thisTypePredicate.type === "TSThisType") {
|
||||
const node: N.TsTypePredicate = this.startNodeAtNode(t);
|
||||
node.parameterName = (thisTypePredicate: N.TsThisType);
|
||||
node.asserts = true;
|
||||
thisTypePredicate = this.finishNode(node, "TSTypePredicate");
|
||||
} else {
|
||||
(thisTypePredicate: N.TsTypePredicate).asserts = true;
|
||||
}
|
||||
t.typeAnnotation = thisTypePredicate;
|
||||
return this.finishNode(t, "TSTypeAnnotation");
|
||||
}
|
||||
|
||||
const typePredicateVariable =
|
||||
this.tsIsIdentifier() &&
|
||||
this.tsTryParse(this.tsParseTypePredicatePrefix.bind(this));
|
||||
@@ -947,15 +968,15 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.tsParseTypeAnnotation(/* eatColon */ false, t);
|
||||
}
|
||||
|
||||
const node: N.TsTypePredicate = this.startNodeAtNode(t);
|
||||
// : asserts foo
|
||||
const node = this.startNodeAtNode(t);
|
||||
node.parameterName = this.parseIdentifier();
|
||||
node.asserts = asserts;
|
||||
t.typeAnnotation = this.finishNode(node, "TSTypePredicate");
|
||||
return this.finishNode(t, "TSTypeAnnotation");
|
||||
}
|
||||
|
||||
// : foo is type
|
||||
// : asserts foo is type
|
||||
const type = this.tsParseTypeAnnotation(/* eatColon */ false);
|
||||
const node = this.startNodeAtNode(t);
|
||||
node.parameterName = typePredicateVariable;
|
||||
@@ -989,17 +1010,24 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsParseTypePredicateAsserts(): boolean {
|
||||
if (!this.tsIsIdentifier()) {
|
||||
if (
|
||||
!this.match(tt.name) ||
|
||||
this.state.value !== "asserts" ||
|
||||
this.hasPrecedingLineBreak()
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
const containsEsc = this.state.containsEsc;
|
||||
this.next();
|
||||
if (!this.match(tt.name) && !this.match(tt._this)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const id = this.parseIdentifier();
|
||||
if (
|
||||
id.name !== "asserts" ||
|
||||
this.hasPrecedingLineBreak() ||
|
||||
!this.tsIsIdentifier()
|
||||
) {
|
||||
return false;
|
||||
if (containsEsc) {
|
||||
this.raise(
|
||||
this.state.lastTokStart,
|
||||
"Escape sequence in keyword asserts",
|
||||
);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
Reference in New Issue
Block a user