Skip to content

Commit

Permalink
Refactoring accoring to tsc implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
sosukesuzuki committed May 1, 2022
1 parent 926581e commit 1509f4e
Show file tree
Hide file tree
Showing 4 changed files with 63 additions and 21 deletions.
75 changes: 58 additions & 17 deletions packages/babel-parser/src/plugins/typescript/index.js
Expand Up @@ -1260,19 +1260,37 @@ export default (superClass: Class<Parser>): Class<Parser> =>
this.expectContextual(tt._infer);
const typeParameter = this.startNode();
typeParameter.name = this.tsParseTypeParameterName();
typeParameter.constraint = this.tsEatThenParseType(tt._extends);
typeParameter.constraint = this.tsTryParse(() =>
this.tsParseConstraintForInferType(),
);
node.typeParameter = this.finishNode(typeParameter, "TSTypeParameter");
return this.finishNode(node, "TSInferType");
}

tsParseConstraintForInferType() {
if (this.eat(tt._extends)) {
const constraint = this.tsInDisallowConditionalTypesContext(() =>
this.tsParseType(),
);
if (
this.state.inDisallowConditionalTypesContext ||
!this.match(tt.question)
) {
return constraint;
}
}
}

tsParseTypeOperatorOrHigher(): N.TsType {
const isTypeOperator =
tokenIsTSTypeOperator(this.state.type) && !this.state.containsEsc;
return isTypeOperator
? this.tsParseTypeOperator()
: this.isContextual(tt._infer)
? this.tsParseInferType()
: this.tsParseArrayTypeOrHigher();
: this.tsInAllowConditionalTypesContext(() =>
this.tsParseArrayTypeOrHigher(),
);
}

tsParseUnionOrIntersectionType(
Expand Down Expand Up @@ -1507,31 +1525,30 @@ export default (superClass: Class<Parser>): Class<Parser> =>
assert(this.state.inType);
const type = this.tsParseNonConditionalType();

const constraintForInfer =
type.type === "TSInferType" && type.typeParameter.constraint;
const inParsingConditionalType =
constraintForInfer && this.state.type === tt.question;

if (
!inParsingConditionalType &&
(this.hasPrecedingLineBreak() || !this.eat(tt._extends))
this.state.inDisallowConditionalTypesContext ||
this.hasPrecedingLineBreak() ||
!this.eat(tt._extends)
) {
return type;
}
const node: N.TsConditionalType = this.startNodeAtNode(type);
node.checkType = type;

node.extendsType = inParsingConditionalType
? ((constraintForInfer: any): N.TsType)
: this.tsParseNonConditionalType();
if (inParsingConditionalType) {
((type: any): N.TsInferType).typeParameter.constraint = undefined;
}
node.extendsType = this.tsInDisallowConditionalTypesContext(() =>
this.tsParseNonConditionalType(),
);

this.expect(tt.question);
node.trueType = this.tsParseType();
node.trueType = this.tsInAllowConditionalTypesContext(() =>
this.tsParseType(),
);

this.expect(tt.colon);
node.falseType = this.tsParseType();
node.falseType = this.tsInAllowConditionalTypesContext(() =>
this.tsParseType(),
);

return this.finishNode(node, "TSConditionalType");
}

Expand Down Expand Up @@ -1676,6 +1693,30 @@ export default (superClass: Class<Parser>): Class<Parser> =>
}
}

tsInDisallowConditionalTypesContext<T>(cb: () => T): T {
const oldInDisallowConditionalTypesContext =
this.state.inDisallowConditionalTypesContext;
this.state.inDisallowConditionalTypesContext = true;
try {
return cb();
} finally {
this.state.inDisallowConditionalTypesContext =
oldInDisallowConditionalTypesContext;
}
}

tsInAllowConditionalTypesContext<T>(cb: () => T): T {
const oldInDisallowConditionalTypesContext =
this.state.inDisallowConditionalTypesContext;
this.state.inDisallowConditionalTypesContext = false;
try {
return cb();
} finally {
this.state.inDisallowConditionalTypesContext =
oldInDisallowConditionalTypesContext;
}
}

tsEatThenParseType(token: TokenType): N.TsType | typeof undefined {
return !this.match(token) ? undefined : this.tsNextThenParseType();
}
Expand Down
1 change: 1 addition & 0 deletions packages/babel-parser/src/tokenizer/state.js
Expand Up @@ -75,6 +75,7 @@ export default class State {
hasFlowComment: boolean = false;
isAmbientContext: boolean = false;
inAbstractClass: boolean = false;
inDisallowConditionalTypesContext: boolean = false;

// For the Hack-style pipelines plugin
topicContext: TopicContextState = {
Expand Down
Expand Up @@ -52,10 +52,10 @@
"start":26,"end":51,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":51,"index":51}},
"checkType": {
"type": "TSInferType",
"start":26,"end":43,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":43,"index":43}},
"start":26,"end":33,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":33,"index":33}},
"typeParameter": {
"type": "TSTypeParameter",
"start":32,"end":43,"loc":{"start":{"line":1,"column":32,"index":32},"end":{"line":1,"column":43,"index":43}},
"start":32,"end":33,"loc":{"start":{"line":1,"column":32,"index":32},"end":{"line":1,"column":33,"index":33}},
"name": "U"
}
},
Expand Down
Expand Up @@ -60,10 +60,10 @@
"start":26,"end":51,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":51,"index":51}},
"checkType": {
"type": "TSInferType",
"start":26,"end":43,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":43,"index":43}},
"start":26,"end":33,"loc":{"start":{"line":1,"column":26,"index":26},"end":{"line":1,"column":33,"index":33}},
"typeParameter": {
"type": "TSTypeParameter",
"start":32,"end":43,"loc":{"start":{"line":1,"column":32,"index":32},"end":{"line":1,"column":43,"index":43}},
"start":32,"end":33,"loc":{"start":{"line":1,"column":32,"index":32},"end":{"line":1,"column":33,"index":33}},
"name": {
"type": "Identifier",
"start":32,"end":33,"loc":{"start":{"line":1,"column":32,"index":32},"end":{"line":1,"column":33,"index":33},"identifierName":"U"},
Expand Down

0 comments on commit 1509f4e

Please sign in to comment.