refactor: extract tt.lt and tt.gt from tt.relation (#13892)
This commit is contained in:
parent
05af38cff2
commit
1fa759f989
@ -1211,23 +1211,24 @@ export default class ExpressionParser extends LValParser {
|
||||
|
||||
if (pipeProposal) {
|
||||
return this.parseTopicReference(pipeProposal);
|
||||
} else {
|
||||
throw this.unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
// fall through
|
||||
case tt.relational: {
|
||||
if (this.state.value === "<") {
|
||||
case tt.lt: {
|
||||
const lookaheadCh = this.input.codePointAt(this.nextTokenStart());
|
||||
if (
|
||||
isIdentifierStart(lookaheadCh) || // Element/Type Parameter <foo>
|
||||
lookaheadCh === charCodes.greaterThan // Fragment <>
|
||||
) {
|
||||
this.expectOnePlugin(["jsx", "flow", "typescript"]);
|
||||
}
|
||||
break;
|
||||
} else {
|
||||
throw this.unexpected();
|
||||
}
|
||||
}
|
||||
|
||||
// fall through
|
||||
default:
|
||||
if (tokenIsIdentifier(type)) {
|
||||
if (
|
||||
|
||||
@ -50,22 +50,6 @@ export default class UtilParser extends Tokenizer {
|
||||
extra[key] = val;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
isRelational(op: "<" | ">"): boolean {
|
||||
return this.match(tt.relational) && this.state.value === op;
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
expectRelational(op: "<" | ">"): void {
|
||||
if (this.isRelational(op)) {
|
||||
this.next();
|
||||
} else {
|
||||
this.unexpected(null, tt.relational);
|
||||
}
|
||||
}
|
||||
|
||||
// Tests whether parsed token is a contextual keyword.
|
||||
|
||||
isContextual(token: TokenType): boolean {
|
||||
|
||||
@ -316,7 +316,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
const typeNode = this.startNode();
|
||||
const typeContainer = this.startNode();
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
typeNode.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
} else {
|
||||
typeNode.typeParameters = null;
|
||||
@ -600,7 +600,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.id.start,
|
||||
);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
} else {
|
||||
node.typeParameters = null;
|
||||
@ -643,7 +643,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
const node = this.startNode();
|
||||
|
||||
node.id = this.flowParseQualifiedTypeIdentifier();
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||||
} else {
|
||||
node.typeParameters = null;
|
||||
@ -692,7 +692,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
);
|
||||
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
} else {
|
||||
node.typeParameters = null;
|
||||
@ -715,7 +715,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
);
|
||||
this.scope.declareName(node.id.name, BIND_LEXICAL, node.id.start);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
} else {
|
||||
node.typeParameters = null;
|
||||
@ -770,7 +770,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.state.inType = true;
|
||||
|
||||
// istanbul ignore else: this condition is already checked at all call sites
|
||||
if (this.isRelational("<") || this.match(tt.jsxTagStart)) {
|
||||
if (this.match(tt.lt) || this.match(tt.jsxTagStart)) {
|
||||
this.next();
|
||||
} else {
|
||||
this.unexpected();
|
||||
@ -787,11 +787,11 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
defaultRequired = true;
|
||||
}
|
||||
|
||||
if (!this.isRelational(">")) {
|
||||
if (!this.match(tt.gt)) {
|
||||
this.expect(tt.comma);
|
||||
}
|
||||
} while (!this.isRelational(">"));
|
||||
this.expectRelational(">");
|
||||
} while (!this.match(tt.gt));
|
||||
this.expect(tt.gt);
|
||||
|
||||
this.state.inType = oldInType;
|
||||
|
||||
@ -805,17 +805,17 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
this.state.inType = true;
|
||||
|
||||
this.expectRelational("<");
|
||||
this.expect(tt.lt);
|
||||
const oldNoAnonFunctionType = this.state.noAnonFunctionType;
|
||||
this.state.noAnonFunctionType = false;
|
||||
while (!this.isRelational(">")) {
|
||||
while (!this.match(tt.gt)) {
|
||||
node.params.push(this.flowParseType());
|
||||
if (!this.isRelational(">")) {
|
||||
if (!this.match(tt.gt)) {
|
||||
this.expect(tt.comma);
|
||||
}
|
||||
}
|
||||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||||
this.expectRelational(">");
|
||||
this.expect(tt.gt);
|
||||
|
||||
this.state.inType = oldInType;
|
||||
|
||||
@ -829,14 +829,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
this.state.inType = true;
|
||||
|
||||
this.expectRelational("<");
|
||||
while (!this.isRelational(">")) {
|
||||
this.expect(tt.lt);
|
||||
while (!this.match(tt.gt)) {
|
||||
node.params.push(this.flowParseTypeOrImplicitInstantiation());
|
||||
if (!this.isRelational(">")) {
|
||||
if (!this.match(tt.gt)) {
|
||||
this.expect(tt.comma);
|
||||
}
|
||||
}
|
||||
this.expectRelational(">");
|
||||
this.expect(tt.gt);
|
||||
|
||||
this.state.inType = oldInType;
|
||||
|
||||
@ -902,7 +902,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.id = this.flowParseObjectPropertyKey();
|
||||
this.expect(tt.bracketR);
|
||||
this.expect(tt.bracketR);
|
||||
if (this.isRelational("<") || this.match(tt.parenL)) {
|
||||
if (this.match(tt.lt) || this.match(tt.parenL)) {
|
||||
node.method = true;
|
||||
node.optional = false;
|
||||
node.value = this.flowParseObjectTypeMethodish(
|
||||
@ -926,7 +926,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.typeParameters = null;
|
||||
node.this = null;
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
}
|
||||
|
||||
@ -1047,7 +1047,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.flowParseObjectTypeIndexer(node, isStatic, variance),
|
||||
);
|
||||
}
|
||||
} else if (this.match(tt.parenL) || this.isRelational("<")) {
|
||||
} else if (this.match(tt.parenL) || this.match(tt.lt)) {
|
||||
if (protoStart != null) {
|
||||
this.unexpected(protoStart);
|
||||
}
|
||||
@ -1169,7 +1169,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.kind = kind;
|
||||
|
||||
let optional = false;
|
||||
if (this.isRelational("<") || this.match(tt.parenL)) {
|
||||
if (this.match(tt.lt) || this.match(tt.parenL)) {
|
||||
// This is a method property
|
||||
node.method = true;
|
||||
|
||||
@ -1287,7 +1287,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.typeParameters = null;
|
||||
node.id = this.flowParseQualifiedTypeIdentifier(startPos, startLoc, id);
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||||
}
|
||||
|
||||
@ -1453,8 +1453,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.state.noAnonFunctionType = oldNoAnonFunctionType;
|
||||
return type;
|
||||
|
||||
case tt.relational:
|
||||
if (this.state.value === "<") {
|
||||
case tt.lt:
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
this.expect(tt.parenL);
|
||||
tmp = this.flowParseFunctionTypeParams();
|
||||
@ -1468,8 +1467,6 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.returnType = this.flowParseType();
|
||||
|
||||
return this.finishNode(node, "FunctionTypeAnnotation");
|
||||
}
|
||||
break;
|
||||
|
||||
case tt.parenL:
|
||||
this.next();
|
||||
@ -2178,7 +2175,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
parseClassId(node: N.Class, isStatement: boolean, optionalId: ?boolean) {
|
||||
super.parseClassId(node, isStatement, optionalId);
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
}
|
||||
}
|
||||
@ -2241,7 +2238,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.state.inType &&
|
||||
(code === charCodes.greaterThan || code === charCodes.lessThan)
|
||||
) {
|
||||
return this.finishOp(tt.relational, 1);
|
||||
return this.finishOp(code === charCodes.greaterThan ? tt.gt : tt.lt, 1);
|
||||
} else if (this.state.inType && code === charCodes.questionMark) {
|
||||
if (next === charCodes.dot) {
|
||||
return this.finishOp(tt.questionDot, 2);
|
||||
@ -2369,7 +2366,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
// determine whether or not we're currently in the position where a class method would appear
|
||||
isClassMethod(): boolean {
|
||||
return this.isRelational("<") || super.isClassMethod();
|
||||
return this.match(tt.lt) || super.isClassMethod();
|
||||
}
|
||||
|
||||
// determine whether or not we're currently in the position where a class property would appear
|
||||
@ -2394,7 +2391,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.unexpected((method: $FlowFixMe).variance.start);
|
||||
}
|
||||
delete (method: $FlowFixMe).variance;
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
method.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
}
|
||||
|
||||
@ -2436,7 +2433,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.unexpected((method: $FlowFixMe).variance.start);
|
||||
}
|
||||
delete (method: $FlowFixMe).variance;
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
method.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
}
|
||||
|
||||
@ -2446,7 +2443,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
// parse a the super class type parameters and implements
|
||||
parseClassSuper(node: N.Class): void {
|
||||
super.parseClassSuper(node);
|
||||
if (node.superClass && this.isRelational("<")) {
|
||||
if (node.superClass && this.match(tt.lt)) {
|
||||
node.superTypeParameters = this.flowParseTypeParameterInstantiation();
|
||||
}
|
||||
if (this.isContextual(tt._implements)) {
|
||||
@ -2455,7 +2452,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
do {
|
||||
const node = this.startNode();
|
||||
node.id = this.flowParseRestrictedIdentifier(/*liberal*/ true);
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterInstantiation();
|
||||
} else {
|
||||
node.typeParameters = null;
|
||||
@ -2508,7 +2505,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
let typeParameters;
|
||||
|
||||
// method shorthand
|
||||
if (this.isRelational("<") && !isAccessor) {
|
||||
if (this.match(tt.lt) && !isAccessor) {
|
||||
typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
if (!this.match(tt.parenL)) this.unexpected();
|
||||
}
|
||||
@ -2740,7 +2737,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
parseFunctionParams(node: N.Function, allowModifiers?: boolean): void {
|
||||
// $FlowFixMe
|
||||
const kind = node.kind;
|
||||
if (kind !== "get" && kind !== "set" && this.isRelational("<")) {
|
||||
if (kind !== "get" && kind !== "set" && this.match(tt.lt)) {
|
||||
node.typeParameters = this.flowParseTypeParameterDeclaration();
|
||||
}
|
||||
super.parseFunctionParams(node, allowModifiers);
|
||||
@ -2798,7 +2795,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
if (
|
||||
this.hasPlugin("jsx") &&
|
||||
(this.match(tt.jsxTagStart) || this.isRelational("<"))
|
||||
(this.match(tt.jsxTagStart) || this.match(tt.lt))
|
||||
) {
|
||||
state = this.state.clone();
|
||||
|
||||
@ -2823,7 +2820,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
if (jsx?.error || this.isRelational("<")) {
|
||||
if (jsx?.error || this.match(tt.lt)) {
|
||||
state = state || this.state.clone();
|
||||
|
||||
let typeParameters;
|
||||
@ -3020,7 +3017,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
} else if (
|
||||
base.type === "Identifier" &&
|
||||
base.name === "async" &&
|
||||
this.isRelational("<")
|
||||
this.match(tt.lt)
|
||||
) {
|
||||
const state = this.state.clone();
|
||||
const arrow = this.tryParse(
|
||||
@ -3081,11 +3078,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.arguments = this.parseCallExpressionArguments(tt.parenR, false);
|
||||
node.optional = true;
|
||||
return this.finishCallExpression(node, /* optional */ true);
|
||||
} else if (
|
||||
!noCalls &&
|
||||
this.shouldParseTypes() &&
|
||||
this.isRelational("<")
|
||||
) {
|
||||
} else if (!noCalls && this.shouldParseTypes() && this.match(tt.lt)) {
|
||||
const node = this.startNodeAt(startPos, startLoc);
|
||||
node.callee = base;
|
||||
|
||||
@ -3118,7 +3111,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
parseNewArguments(node: N.NewExpression): void {
|
||||
let targs = null;
|
||||
if (this.shouldParseTypes() && this.isRelational("<")) {
|
||||
if (this.shouldParseTypes() && this.match(tt.lt)) {
|
||||
targs = this.tryParse(() =>
|
||||
this.flowParseTypeParameterInstantiationCallOrNew(),
|
||||
).node;
|
||||
@ -3665,7 +3658,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
return this.finishNode(node, "EnumDeclaration");
|
||||
}
|
||||
|
||||
// check if the next token is a tt.relation("<")
|
||||
// check if the next token is a tt.lt
|
||||
isLookaheadToken_lt(): boolean {
|
||||
const next = this.nextTokenStart();
|
||||
if (this.input.charCodeAt(next) === charCodes.lessThan) {
|
||||
|
||||
@ -520,7 +520,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.closingElement = closingElement;
|
||||
}
|
||||
node.children = children;
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
throw this.raise(
|
||||
this.state.start,
|
||||
JsxErrors.UnwrappedAdjacentJSXElements,
|
||||
@ -551,7 +551,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
} else if (this.match(tt.jsxTagStart)) {
|
||||
return this.jsxParseElement();
|
||||
} else if (
|
||||
this.isRelational("<") &&
|
||||
this.match(tt.lt) &&
|
||||
this.input.charCodeAt(this.state.pos) !== charCodes.exclamationMark
|
||||
) {
|
||||
// In case we encounter an lt token here it will always be the start of
|
||||
|
||||
@ -351,7 +351,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
case "TupleElementTypes":
|
||||
return this.match(tt.bracketR);
|
||||
case "TypeParametersOrArguments":
|
||||
return this.isRelational(">");
|
||||
return this.match(tt.gt);
|
||||
}
|
||||
|
||||
throw new Error("Unreachable");
|
||||
@ -440,7 +440,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (bracket) {
|
||||
this.expect(tt.bracketL);
|
||||
} else {
|
||||
this.expectRelational("<");
|
||||
this.expect(tt.lt);
|
||||
}
|
||||
}
|
||||
|
||||
@ -453,7 +453,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (bracket) {
|
||||
this.expect(tt.bracketR);
|
||||
} else {
|
||||
this.expectRelational(">");
|
||||
this.expect(tt.gt);
|
||||
}
|
||||
|
||||
return result;
|
||||
@ -474,7 +474,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (this.eat(tt.dot)) {
|
||||
node.qualifier = this.tsParseEntityName(/* allowReservedWords */ true);
|
||||
}
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
return this.finishNode(node, "TSImportType");
|
||||
@ -494,7 +494,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
tsParseTypeReference(): N.TsTypeReference {
|
||||
const node: N.TsTypeReference = this.startNode();
|
||||
node.typeName = this.tsParseEntityName(/* allowReservedWords */ false);
|
||||
if (!this.hasPrecedingLineBreak() && this.isRelational("<")) {
|
||||
if (!this.hasPrecedingLineBreak() && this.match(tt.lt)) {
|
||||
node.typeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
return this.finishNode(node, "TSTypeReference");
|
||||
@ -535,7 +535,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsTryParseTypeParameters(): ?N.TsTypeParameterDeclaration {
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
return this.tsParseTypeParameters();
|
||||
}
|
||||
}
|
||||
@ -543,7 +543,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
tsParseTypeParameters() {
|
||||
const node: N.TsTypeParameterDeclaration = this.startNode();
|
||||
|
||||
if (this.isRelational("<") || this.match(tt.jsxTagStart)) {
|
||||
if (this.match(tt.lt) || this.match(tt.jsxTagStart)) {
|
||||
this.next();
|
||||
} else {
|
||||
this.unexpected();
|
||||
@ -672,12 +672,12 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (this.eat(tt.question)) node.optional = true;
|
||||
const nodeAny: any = node;
|
||||
|
||||
if (this.match(tt.parenL) || this.isRelational("<")) {
|
||||
if (this.match(tt.parenL) || this.match(tt.lt)) {
|
||||
if (readonly) {
|
||||
this.raise(node.start, TSErrors.ReadonlyForMethodSignature);
|
||||
}
|
||||
const method: N.TsMethodSignature = nodeAny;
|
||||
if (method.kind && this.isRelational("<")) {
|
||||
if (method.kind && this.match(tt.lt)) {
|
||||
this.raise(this.state.pos, TSErrors.AccesorCannotHaveTypeParameters);
|
||||
}
|
||||
this.tsFillSignature(tt.colon, method);
|
||||
@ -742,14 +742,14 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
tsParseTypeMember(): N.TsTypeElement {
|
||||
const node: any = this.startNode();
|
||||
|
||||
if (this.match(tt.parenL) || this.isRelational("<")) {
|
||||
if (this.match(tt.parenL) || this.match(tt.lt)) {
|
||||
return this.tsParseSignatureMember("TSCallSignatureDeclaration", node);
|
||||
}
|
||||
|
||||
if (this.match(tt._new)) {
|
||||
const id: N.Identifier = this.startNode();
|
||||
this.next();
|
||||
if (this.match(tt.parenL) || this.isRelational("<")) {
|
||||
if (this.match(tt.parenL) || this.match(tt.lt)) {
|
||||
return this.tsParseSignatureMember(
|
||||
"TSConstructSignatureDeclaration",
|
||||
node,
|
||||
@ -1199,7 +1199,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
tsIsStartOfFunctionType() {
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
return true;
|
||||
}
|
||||
return (
|
||||
@ -1441,7 +1441,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
const node: N.TsTypeAssertion = this.startNode();
|
||||
const _const = this.tsTryNextParseConstantContext();
|
||||
node.typeAnnotation = _const || this.tsNextThenParseType();
|
||||
this.expectRelational(">");
|
||||
this.expect(tt.gt);
|
||||
node.expression = this.parseMaybeUnary();
|
||||
return this.finishNode(node, "TSTypeAssertion");
|
||||
}
|
||||
@ -1468,7 +1468,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
// Note: TS uses parseLeftHandSideExpressionOrHigher,
|
||||
// then has grammar errors later if it's not an EntityName.
|
||||
node.expression = this.tsParseEntityName(/* allowReservedWords */ false);
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
node.typeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
|
||||
@ -1917,7 +1917,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
startPos: number,
|
||||
startLoc: Position,
|
||||
): ?N.ArrowFunctionExpression {
|
||||
if (!this.isRelational("<")) {
|
||||
if (!this.match(tt.lt)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@ -1955,7 +1955,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
node.params = this.tsInType(() =>
|
||||
// Temporarily remove a JSX parsing context, which makes us scan different tokens.
|
||||
this.tsInNoContext(() => {
|
||||
this.expectRelational("<");
|
||||
this.expect(tt.lt);
|
||||
return this.tsParseDelimitedList(
|
||||
"TypeParametersOrArguments",
|
||||
this.tsParseType.bind(this),
|
||||
@ -1965,7 +1965,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
if (node.params.length === 0) {
|
||||
this.raise(node.start, TSErrors.EmptyTypeArguments);
|
||||
}
|
||||
this.expectRelational(">");
|
||||
this.expect(tt.gt);
|
||||
return this.finishNode(node, "TSTypeParameterInstantiation");
|
||||
}
|
||||
|
||||
@ -2149,7 +2149,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
this.next();
|
||||
}
|
||||
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
let missingParenErrorPos;
|
||||
// tsTryParseAndCatch is expensive, so avoid if not necessary.
|
||||
// There are number of things we are going to "maybe" parse, like type arguments on
|
||||
@ -2222,7 +2222,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
parseNewArguments(node: N.NewExpression): void {
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
// tsTryParseAndCatch is expensive, so avoid if not necessary.
|
||||
// 99% certain this is `new C<T>();`. But may be `new C < T;`, which is also legal.
|
||||
const typeParameters = this.tsTryParseAndCatch(() => {
|
||||
@ -2803,7 +2803,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
parseClassSuper(node: N.Class): void {
|
||||
super.parseClassSuper(node);
|
||||
if (node.superClass && this.isRelational("<")) {
|
||||
if (node.superClass && this.match(tt.lt)) {
|
||||
node.superTypeParameters = this.tsParseTypeArguments();
|
||||
}
|
||||
if (this.eatContextual(tt._implements)) {
|
||||
@ -2861,7 +2861,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
if (
|
||||
this.hasPlugin("jsx") &&
|
||||
(this.match(tt.jsxTagStart) || this.isRelational("<"))
|
||||
(this.match(tt.jsxTagStart) || this.match(tt.lt))
|
||||
) {
|
||||
// Prefer to parse JSX if possible. But may be an arrow fn.
|
||||
state = this.state.clone();
|
||||
@ -2883,7 +2883,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
}
|
||||
|
||||
if (!jsx?.error && !this.isRelational("<")) {
|
||||
if (!jsx?.error && !this.match(tt.lt)) {
|
||||
return super.parseMaybeAssign(...args);
|
||||
}
|
||||
|
||||
@ -2973,7 +2973,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
// Handle type assertions
|
||||
parseMaybeUnary(refExpressionErrors?: ?ExpressionErrors): N.Expression {
|
||||
if (!this.hasPlugin("jsx") && this.isRelational("<")) {
|
||||
if (!this.hasPlugin("jsx") && this.match(tt.lt)) {
|
||||
return this.tsParseTypeAssertion();
|
||||
} else {
|
||||
return super.parseMaybeUnary(refExpressionErrors);
|
||||
@ -3114,7 +3114,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
}
|
||||
|
||||
parseMaybeDecoratorArguments(expr: N.Expression): N.Expression {
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
const typeArguments = this.tsParseTypeArguments();
|
||||
|
||||
if (this.match(tt.parenL)) {
|
||||
@ -3147,7 +3147,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
// === === === === === === === === === === === === === === === ===
|
||||
|
||||
isClassMethod(): boolean {
|
||||
return this.isRelational("<") || super.isClassMethod();
|
||||
return this.match(tt.lt) || super.isClassMethod();
|
||||
}
|
||||
|
||||
isClassProperty(): boolean {
|
||||
@ -3175,24 +3175,26 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
|
||||
// ensure that inside types, we bypass the jsx parser plugin
|
||||
getTokenFromCode(code: number): void {
|
||||
if (
|
||||
this.state.inType &&
|
||||
(code === charCodes.greaterThan || code === charCodes.lessThan)
|
||||
) {
|
||||
return this.finishOp(tt.relational, 1);
|
||||
} else {
|
||||
return super.getTokenFromCode(code);
|
||||
if (this.state.inType) {
|
||||
if (code === charCodes.greaterThan) {
|
||||
return this.finishOp(tt.gt, 1);
|
||||
}
|
||||
if (code === charCodes.lessThan) {
|
||||
return this.finishOp(tt.lt, 1);
|
||||
}
|
||||
}
|
||||
return super.getTokenFromCode(code);
|
||||
}
|
||||
|
||||
// used after we have finished parsing types
|
||||
reScan_lt_gt() {
|
||||
if (this.match(tt.relational)) {
|
||||
const code = this.input.charCodeAt(this.state.start);
|
||||
if (code === charCodes.lessThan || code === charCodes.greaterThan) {
|
||||
const { type } = this.state;
|
||||
if (type === tt.lt) {
|
||||
this.state.pos -= 1;
|
||||
this.readToken_lt_gt(code);
|
||||
}
|
||||
this.readToken_lt();
|
||||
} else if (type === tt.gt) {
|
||||
this.state.pos -= 1;
|
||||
this.readToken_gt();
|
||||
}
|
||||
}
|
||||
|
||||
@ -3248,7 +3250,7 @@ export default (superClass: Class<Parser>): Class<Parser> =>
|
||||
jsxParseOpeningElementAfterName(
|
||||
node: N.JSXOpeningElement,
|
||||
): N.JSXOpeningElement {
|
||||
if (this.isRelational("<")) {
|
||||
if (this.match(tt.lt)) {
|
||||
const typeArguments = this.tsTryParseAndCatch(() =>
|
||||
this.tsParseTypeArguments(),
|
||||
);
|
||||
|
||||
@ -727,18 +727,38 @@ export default class Tokenizer extends ParserErrors {
|
||||
}
|
||||
}
|
||||
|
||||
readToken_lt_gt(code: number): void {
|
||||
// '<>'
|
||||
const next = this.input.charCodeAt(this.state.pos + 1);
|
||||
let size = 1;
|
||||
readToken_lt(): void {
|
||||
// '<'
|
||||
const { pos } = this.state;
|
||||
const next = this.input.charCodeAt(pos + 1);
|
||||
|
||||
if (next === code) {
|
||||
size =
|
||||
code === charCodes.greaterThan &&
|
||||
this.input.charCodeAt(this.state.pos + 2) === charCodes.greaterThan
|
||||
? 3
|
||||
: 2;
|
||||
if (this.input.charCodeAt(this.state.pos + size) === charCodes.equalsTo) {
|
||||
if (next === charCodes.lessThan) {
|
||||
if (this.input.charCodeAt(pos + 2) === charCodes.equalsTo) {
|
||||
this.finishOp(tt.assign, 3);
|
||||
return;
|
||||
}
|
||||
this.finishOp(tt.bitShift, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
if (next === charCodes.equalsTo) {
|
||||
// <=
|
||||
this.finishOp(tt.relational, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
this.finishOp(tt.lt, 1);
|
||||
}
|
||||
|
||||
readToken_gt(): void {
|
||||
// '>'
|
||||
const { pos } = this.state;
|
||||
const next = this.input.charCodeAt(pos + 1);
|
||||
|
||||
if (next === charCodes.greaterThan) {
|
||||
const size =
|
||||
this.input.charCodeAt(pos + 2) === charCodes.greaterThan ? 3 : 2;
|
||||
if (this.input.charCodeAt(pos + size) === charCodes.equalsTo) {
|
||||
this.finishOp(tt.assign, size + 1);
|
||||
return;
|
||||
}
|
||||
@ -748,10 +768,11 @@ export default class Tokenizer extends ParserErrors {
|
||||
|
||||
if (next === charCodes.equalsTo) {
|
||||
// <= | >=
|
||||
size = 2;
|
||||
this.finishOp(tt.relational, 2);
|
||||
return;
|
||||
}
|
||||
|
||||
this.finishOp(tt.relational, size);
|
||||
this.finishOp(tt.gt, 1);
|
||||
}
|
||||
|
||||
readToken_eq_excl(code: number): void {
|
||||
@ -963,8 +984,11 @@ export default class Tokenizer extends ParserErrors {
|
||||
return;
|
||||
|
||||
case charCodes.lessThan:
|
||||
this.readToken_lt();
|
||||
return;
|
||||
|
||||
case charCodes.greaterThan:
|
||||
this.readToken_lt_gt(code);
|
||||
this.readToken_gt();
|
||||
return;
|
||||
|
||||
case charCodes.equalsTo:
|
||||
|
||||
@ -200,6 +200,8 @@ export const tt: { [name: string]: TokenType } = {
|
||||
bitwiseXOR: createBinop("^", 4),
|
||||
bitwiseAND: createBinop("&", 5),
|
||||
equality: createBinop("==/!=/===/!==", 6),
|
||||
lt: createBinop("</>/<=/>=", 7),
|
||||
gt: createBinop("</>/<=/>=", 7),
|
||||
relational: createBinop("</>/<=/>=", 7),
|
||||
bitShift: createBinop("<</>>/>>>", 8),
|
||||
plusMin: createToken("+/-", { beforeExpr, binop: 9, prefix, startsExpr }),
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user