Skip to content

Commit

Permalink
Revise parse for infer..extends, improve parenthesizer
Browse files Browse the repository at this point in the history
  • Loading branch information
rbuckton committed Mar 11, 2022
1 parent 8fd5eda commit 2fb093c
Show file tree
Hide file tree
Showing 53 changed files with 715 additions and 294 deletions.
68 changes: 49 additions & 19 deletions src/compiler/emitter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,9 @@ namespace ts {
let currentParenthesizerRule: ((node: Node) => Node) | undefined;
const { enter: enterComment, exit: exitComment } = performance.createTimerIf(extendedDiagnostics, "commentTime", "beforeComment", "afterComment");
const parenthesizer = factory.parenthesizer;
const typeArgumentParenthesizerRuleSelector: OrdinalParentheizerRuleSelector<Node> = {
select: index => index === 0 ? parenthesizer.parenthesizeLeadingTypeArgument : undefined
};
const emitBinaryExpression = createEmitBinaryExpression();

reset();
Expand Down Expand Up @@ -2240,7 +2243,7 @@ namespace ts {
}

function emitArrayType(node: ArrayTypeNode) {
emit(node.elementType, parenthesizer.parenthesizeElementTypeOfArrayType);
emit(node.elementType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType);
writePunctuation("[");
writePunctuation("]");
}
Expand All @@ -2253,7 +2256,7 @@ namespace ts {
function emitTupleType(node: TupleTypeNode) {
emitTokenWithComment(SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node);
const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements : ListFormat.MultiLineTupleTypeElements;
emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty);
emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty, parenthesizer.parenthesizeElementTypeOfTupleType);
emitTokenWithComment(SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node);
}

Expand All @@ -2267,24 +2270,24 @@ namespace ts {
}

function emitOptionalType(node: OptionalTypeNode) {
emit(node.type, parenthesizer.parenthesizeElementTypeOfArrayType);
emit(node.type, parenthesizer.parenthesizeTypeOfOptionalType);
writePunctuation("?");
}

function emitUnionType(node: UnionTypeNode) {
emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeMemberOfElementType);
emitList(node, node.types, ListFormat.UnionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfUnionType);
}

function emitIntersectionType(node: IntersectionTypeNode) {
emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeMemberOfElementType);
emitList(node, node.types, ListFormat.IntersectionTypeConstituents, parenthesizer.parenthesizeConstituentTypeOfIntersectionType);
}

function emitConditionalType(node: ConditionalTypeNode) {
emit(node.checkType, parenthesizer.parenthesizeMemberOfConditionalType);
emit(node.checkType, parenthesizer.parenthesizeCheckTypeOfConditionalType);
writeSpace();
writeKeyword("extends");
writeSpace();
emit(node.extendsType, parenthesizer.parenthesizeMemberOfConditionalType);
emit(node.extendsType, parenthesizer.parenthesizeExtendsTypeOfConditionalType);
writeSpace();
writePunctuation("?");
writeSpace();
Expand Down Expand Up @@ -2314,11 +2317,15 @@ namespace ts {
function emitTypeOperator(node: TypeOperatorNode) {
writeTokenText(node.operator, writeKeyword);
writeSpace();
emit(node.type, parenthesizer.parenthesizeMemberOfElementType);

const parenthesizerRule = node.operator === SyntaxKind.ReadonlyKeyword ?
parenthesizer.parenthesizeOperandOfReadonlyTypeOperator :
parenthesizer.parenthesizeOperandOfTypeOperator;
emit(node.type, parenthesizerRule);
}

function emitIndexedAccessType(node: IndexedAccessTypeNode) {
emit(node.objectType, parenthesizer.parenthesizeMemberOfElementType);
emit(node.objectType, parenthesizer.parenthesizeNonArrayTypeOfPostfixType);
writePunctuation("[");
emit(node.indexType);
writePunctuation("]");
Expand Down Expand Up @@ -4254,7 +4261,7 @@ namespace ts {
}

function emitTypeArguments(parentNode: Node, typeArguments: NodeArray<TypeNode> | undefined) {
emitList(parentNode, typeArguments, ListFormat.TypeArguments, parenthesizer.parenthesizeMemberOfElementType);
emitList(parentNode, typeArguments, ListFormat.TypeArguments, typeArgumentParenthesizerRuleSelector);
}

function emitTypeParameters(parentNode: SignatureDeclaration | InterfaceDeclaration | TypeAliasDeclaration | ClassDeclaration | ClassExpression, typeParameters: NodeArray<TypeParameterDeclaration> | undefined) {
Expand Down Expand Up @@ -4322,15 +4329,15 @@ namespace ts {
}
}

function emitList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: (node: Node) => Node, start?: number, count?: number) {
function emitList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector<Node>, start?: number, count?: number) {
emitNodeList(emit, parentNode, children, format, parenthesizerRule, start, count);
}

function emitExpressionList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: (node: Expression) => Expression, start?: number, count?: number) {
function emitExpressionList(parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule?: ParenthesizerRuleOrSelector<Expression>, start?: number, count?: number) {
emitNodeList(emitExpression, parentNode, children, format, parenthesizerRule, start, count);
}

function emitNodeList(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule: ((node: Node) => Node) | undefined, start = 0, count = children ? children.length - start : 0) {
function emitNodeList(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parentNode: Node | undefined, children: NodeArray<Node> | undefined, format: ListFormat, parenthesizerRule: ParenthesizerRuleOrSelector<Node> | undefined, start = 0, count = children ? children.length - start : 0) {
const isUndefined = children === undefined;
if (isUndefined && format & ListFormat.OptionalIfUndefined) {
return;
Expand Down Expand Up @@ -4386,6 +4393,8 @@ namespace ts {
increaseIndent();
}

const emitListItem = getEmitListItem(emit, parenthesizerRule);

// Emit each child.
let previousSibling: Node | undefined;
let previousSourceFileTextKind: ReturnType<typeof recordBundleFileInternalSectionStart>;
Expand Down Expand Up @@ -4441,12 +4450,7 @@ namespace ts {
}

nextListElementPos = child.pos;
if (emit.length === 1) {
emit(child);
}
else {
emit(child, parenthesizerRule);
}
emitListItem(child, emit, parenthesizerRule, i);

if (shouldDecreaseIndentAfterEmit) {
decreaseIndent();
Expand Down Expand Up @@ -5888,4 +5892,30 @@ namespace ts {
CountMask = 0x0FFFFFFF, // Temp variable counter
_i = 0x10000000, // Use/preference flag for '_i'
}

interface OrdinalParentheizerRuleSelector<T extends Node> {
select(index: number): ((node: T) => T) | undefined;
}

type ParenthesizerRule<T extends Node> = (node: T) => T;

type ParenthesizerRuleOrSelector<T extends Node> = OrdinalParentheizerRuleSelector<T> | ParenthesizerRule<T>;

function emitListItemNoParenthesizer(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, _parenthesizerRule: ParenthesizerRuleOrSelector<Node> | undefined, _index: number) {
emit(node);
}

function emitListItemWithParenthesizerRuleSelector(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRuleSelector: OrdinalParentheizerRuleSelector<Node>, index: number) {
emit(node, parenthesizerRuleSelector.select(index));
}

function emitListItemWithParenthesizerRule(node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: ParenthesizerRule<Node> | undefined, _index: number) {
emit(node, parenthesizerRule);
}

function getEmitListItem<T extends Node, R extends ParenthesizerRuleOrSelector<T> | undefined>(emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R): (node: Node, emit: (node: Node, parenthesizerRule?: ((node: Node) => Node) | undefined) => void, parenthesizerRule: R, index: number) => void {
return emit.length === 1 ? emitListItemNoParenthesizer :
typeof parenthesizerRule === "object" ? emitListItemWithParenthesizerRuleSelector :
emitListItemWithParenthesizerRule;
}
}
Loading

0 comments on commit 2fb093c

Please sign in to comment.