Skip to content

Commit 28dfb91

Browse files
committed
Use a cache with a key on subset of options
1 parent 4102e95 commit 28dfb91

File tree

8 files changed

+39
-28
lines changed

8 files changed

+39
-28
lines changed

src/compiler/checker.ts

+7-9
Original file line numberDiff line numberDiff line change
@@ -111,10 +111,7 @@ import {
111111
createGetCanonicalFileName,
112112
createGetSymbolWalker,
113113
createModeAwareCacheKey,
114-
createPrinterWithDefaults,
115-
createPrinterWithRemoveComments,
116-
createPrinterWithRemoveCommentsNeverAsciiEscape,
117-
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
114+
createOrReusePrinter,
118115
createPropertyNameNodeForIdentifierOrLiteral,
119116
createSymbolTable,
120117
createTextWriter,
@@ -6127,8 +6124,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61276124
const entity = builder(symbol, meaning!, enclosingDeclaration, nodeFlags)!; // TODO: GH#18217
61286125
// add neverAsciiEscape for GH#39027
61296126
const printer = enclosingDeclaration?.kind === SyntaxKind.SourceFile
6130-
? createPrinterWithRemoveCommentsNeverAsciiEscape()
6131-
: createPrinterWithRemoveComments();
6127+
? createOrReusePrinter({ removeComments: true, neverAsciiEscape: true })
6128+
: createOrReusePrinter({ removeComments: true });
61326129
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
61336130
printer.writeNode(EmitHint.Unspecified, entity, /*sourceFile*/ sourceFile, writer);
61346131
return writer;
@@ -6147,7 +6144,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61476144
sigOutput = kind === SignatureKind.Construct ? SyntaxKind.ConstructSignature : SyntaxKind.CallSignature;
61486145
}
61496146
const sig = nodeBuilder.signatureToSignatureDeclaration(signature, sigOutput, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName);
6150-
const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon();
6147+
const printer = createOrReusePrinter({ removeComments: true, omitTrailingSemicolon: true });
61516148
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
61526149
printer.writeNode(EmitHint.Unspecified, sig!, /*sourceFile*/ sourceFile, getTrailingSemicolonDeferringWriter(writer)); // TODO: GH#18217
61536150
return writer;
@@ -6160,7 +6157,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
61606157
if (typeNode === undefined) return Debug.fail("should always get typenode");
61616158
// The unresolved type gets a synthesized comment on `any` to hint to users that it's not a plain `any`.
61626159
// Otherwise, we always strip comments out.
6163-
const printer = type !== unresolvedType ? createPrinterWithRemoveComments() : createPrinterWithDefaults();
6160+
const options = { removeComments: type !== unresolvedType };
6161+
const printer = createOrReusePrinter(options);
61646162
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
61656163
printer.writeNode(EmitHint.Unspecified, typeNode, /*sourceFile*/ sourceFile, writer);
61666164
const result = writer.getText();
@@ -9640,7 +9638,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
96409638
typePredicate.kind === TypePredicateKind.Identifier || typePredicate.kind === TypePredicateKind.AssertsIdentifier ? factory.createIdentifier(typePredicate.parameterName) : factory.createThisTypeNode(),
96419639
typePredicate.type && nodeBuilder.typeToTypeNode(typePredicate.type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName)! // TODO: GH#18217
96429640
);
9643-
const printer = createPrinterWithRemoveComments();
9641+
const printer = createOrReusePrinter({ removeComments: true });
96449642
const sourceFile = enclosingDeclaration && getSourceFileOfNode(enclosingDeclaration);
96459643
printer.writeNode(EmitHint.Unspecified, predicate, /*sourceFile*/ sourceFile, writer);
96469644
return writer;

src/compiler/emitter.ts

+18-6
Original file line numberDiff line numberDiff line change
@@ -1343,17 +1343,29 @@ const enum PipelinePhase {
13431343
Emit,
13441344
}
13451345

1346-
/** @internal */
1347-
export const createPrinterWithDefaults = memoize(() => createPrinter({}));
1346+
const printerCache = new Map<string, Printer>();
13481347

1348+
// If updating this, make sure the cache key is updated too.
13491349
/** @internal */
1350-
export const createPrinterWithRemoveComments = memoize(() => createPrinter({ removeComments: true }));
1350+
export type ReusablePrinterOptions = Pick<PrinterOptions, "removeComments" | "neverAsciiEscape" | "omitTrailingSemicolon" | "module" | "target" | "newLine">;
13511351

13521352
/** @internal */
1353-
export const createPrinterWithRemoveCommentsNeverAsciiEscape = memoize(() => createPrinter({ removeComments: true, neverAsciiEscape: true }));
1353+
export function createOrReusePrinter(o: ReusablePrinterOptions = {}) {
1354+
const key = `${keyBool(o.removeComments)}|${keyBool(o.neverAsciiEscape)}|${keyBool(o.omitTrailingSemicolon)}|${keyNum(o.module)}|${keyNum(o.target)}|${keyNum(o.newLine)}`;
1355+
let printer = printerCache.get(key);
1356+
if (!printer) {
1357+
printerCache.set(key, printer = createPrinter(o));
1358+
}
1359+
return printer;
13541360

1355-
/** @internal */
1356-
export const createPrinterWithRemoveCommentsOmitTrailingSemicolon = memoize(() => createPrinter({ removeComments: true, omitTrailingSemicolon: true }));
1361+
function keyBool(value: boolean | undefined) {
1362+
return value === undefined ? "u" : value ? 1 : 0;
1363+
}
1364+
1365+
function keyNum(value: number | undefined) {
1366+
return value === undefined ? "u" : `${value}`;
1367+
}
1368+
}
13571369

13581370
export function createPrinter(printerOptions: PrinterOptions = {}, handlers: PrintHandlers = {}): Printer {
13591371
const {

src/services/callHierarchy.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
ClassLikeDeclaration,
1515
ClassStaticBlockDeclaration,
1616
compareStringsCaseSensitive,
17-
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
17+
createOrReusePrinter,
1818
createTextRangeFromNode,
1919
createTextSpanFromBounds,
2020
createTextSpanFromRange,
@@ -245,7 +245,7 @@ function getCallHierarchyItemName(program: Program, node: CallHierarchyDeclarati
245245
}
246246
if (text === undefined) {
247247
// get the text from printing the node on a single line without comments...
248-
const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon();
248+
const printer = createOrReusePrinter({ removeComments: true, omitTrailingSemicolon: true });
249249
text = usingSingleLineStringWriter(writer => printer.writeNode(EmitHint.Unspecified, node, node.getSourceFile(), writer));
250250
}
251251
return { text, pos: declName.getStart(), end: declName.getEnd() };

src/services/completions.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ import {
3434
ConstructorDeclaration,
3535
ContextFlags,
3636
createModuleSpecifierResolutionHost,
37+
createOrReusePrinter,
3738
createPackageJsonImportFilter,
3839
createPrinter,
3940
createSortedArray,
@@ -1747,7 +1748,7 @@ function getEntryForObjectLiteralMethodCompletion(
17471748
insertText = printer.printSnippetList(ListFormat.CommaDelimited | ListFormat.AllowTrailingComma, factory.createNodeArray([method], /*hasTrailingComma*/ true), sourceFile);
17481749
}
17491750

1750-
const signaturePrinter = createPrinter({
1751+
const signaturePrinter = createOrReusePrinter({
17511752
removeComments: true,
17521753
module: options.module,
17531754
target: options.target,

src/services/inlayHints.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import {
22
__String,
33
ArrowFunction,
44
CallExpression,
5-
createPrinterWithRemoveComments,
5+
createOrReusePrinter,
66
Debug,
77
EmitHint,
88
EnumMember,
@@ -382,7 +382,7 @@ export function provideInlayHints(context: InlayHintsContext): InlayHint[] {
382382

383383
function printTypeInSingleLine(type: Type) {
384384
const flags = NodeBuilderFlags.IgnoreErrors | TypeFormatFlags.AllowUniqueESSymbolType | TypeFormatFlags.UseAliasDefinedOutsideCurrentScope;
385-
const printer = createPrinterWithRemoveComments();
385+
const printer = createOrReusePrinter({ removeComments: true });
386386

387387
return usingSingleLineStringWriter(writer => {
388388
const typeNode = checker.typeToTypeNode(type, /*enclosingDeclaration*/ undefined, flags);

src/services/signatureHelp.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
CheckFlags,
88
contains,
99
countWhere,
10-
createPrinterWithRemoveComments,
10+
createOrReusePrinter,
1111
createTextSpan,
1212
createTextSpanFromBounds,
1313
createTextSpanFromNode,
@@ -659,7 +659,7 @@ function createTypeHelpItems(
659659
function getTypeHelpItem(symbol: Symbol, typeParameters: readonly TypeParameter[], checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItem {
660660
const typeSymbolDisplay = symbolToDisplayParts(checker, symbol);
661661

662-
const printer = createPrinterWithRemoveComments();
662+
const printer = createOrReusePrinter({ removeComments: true });
663663
const parameters = typeParameters.map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer));
664664

665665
const documentation = symbol.getDocumentationComment(checker);
@@ -699,7 +699,7 @@ interface SignatureHelpItemInfo { readonly isVariadic: boolean; readonly paramet
699699

700700
function itemInfoForTypeParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] {
701701
const typeParameters = (candidateSignature.target || candidateSignature).typeParameters;
702-
const printer = createPrinterWithRemoveComments();
702+
const printer = createOrReusePrinter({ removeComments: true });
703703
const parameters = (typeParameters || emptyArray).map(t => createSignatureHelpParameterForTypeParameter(t, checker, enclosingDeclaration, sourceFile, printer));
704704
const thisParameter = candidateSignature.thisParameter ? [checker.symbolToParameterDeclaration(candidateSignature.thisParameter, enclosingDeclaration, signatureHelpNodeBuilderFlags)!] : [];
705705

@@ -713,7 +713,7 @@ function itemInfoForTypeParameters(candidateSignature: Signature, checker: TypeC
713713
}
714714

715715
function itemInfoForParameters(candidateSignature: Signature, checker: TypeChecker, enclosingDeclaration: Node, sourceFile: SourceFile): SignatureHelpItemInfo[] {
716-
const printer = createPrinterWithRemoveComments();
716+
const printer = createOrReusePrinter({ removeComments: true });
717717
const typeParameterParts = mapToDisplayParts(writer => {
718718
if (candidateSignature.typeParameters && candidateSignature.typeParameters.length) {
719719
const args = factory.createNodeArray(candidateSignature.typeParameters.map(p => checker.typeParameterToDeclaration(p, enclosingDeclaration, signatureHelpNodeBuilderFlags)!));

src/services/symbolDisplay.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import {
55
CallExpression,
66
CheckFlags,
77
contains,
8-
createPrinterWithRemoveComments,
8+
createOrReusePrinter,
99
Debug,
1010
displayPart,
1111
EmitHint,
@@ -728,7 +728,7 @@ export function getSymbolDisplayPartsDocumentationAndSymbolKind(typeChecker: Typ
728728
return { displayParts, documentation, symbolKind, tags: tags.length === 0 ? undefined : tags };
729729

730730
function getPrinter() {
731-
return createPrinterWithRemoveComments();
731+
return createOrReusePrinter({ removeComments: true });
732732
}
733733

734734
function prefixNextMeaning() {

src/services/utilities.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ import {
3030
ConditionalExpression,
3131
contains,
3232
ContextFlags,
33-
createPrinterWithRemoveCommentsOmitTrailingSemicolon,
33+
createOrReusePrinter,
3434
createRange,
3535
createScanner,
3636
createTextSpan,
@@ -2984,7 +2984,7 @@ export function signatureToDisplayParts(typechecker: TypeChecker, signature: Sig
29842984
export function nodeToDisplayParts(node: Node, enclosingDeclaration: Node): SymbolDisplayPart[] {
29852985
const file = enclosingDeclaration.getSourceFile();
29862986
return mapToDisplayParts(writer => {
2987-
const printer = createPrinterWithRemoveCommentsOmitTrailingSemicolon();
2987+
const printer = createOrReusePrinter({ removeComments: true, omitTrailingSemicolon: true });
29882988
printer.writeNode(EmitHint.Unspecified, node, file, writer);
29892989
});
29902990
}

0 commit comments

Comments
 (0)