Skip to content

Commit

Permalink
Use replaceAll instead of an incorrect RegExp for tsserver log sa…
Browse files Browse the repository at this point in the history
…nitization.
  • Loading branch information
DanielRosenwasser committed May 30, 2023
1 parent 0b170d0 commit 2a9c204
Showing 1 changed file with 54 additions and 22 deletions.
76 changes: 54 additions & 22 deletions src/testRunner/unittests/helpers/tsserver.ts
Expand Up @@ -36,6 +36,29 @@ export const customTypesMap = {
}`
};

function replaceAll(source: string, searchValue: string, replaceValue: string): string {
let result: string | undefined =
(source as string & { replaceAll: typeof source.replace }).replaceAll?.(searchValue, replaceValue);

if (result !== undefined) {
return result;
}

result = "";
const searchLength = searchValue.length;
while (true) {
const index = source.indexOf(searchValue);
if (index < 0) {
break;
}
result += source.slice(0, index);
result += replaceValue;
source = source.slice(index + searchLength);
}
result += source;
return result;
}

export interface PostExecAction {
readonly success: boolean;
requestId: number;
Expand Down Expand Up @@ -115,23 +138,24 @@ export function createLoggerWritingToConsole(host: TestServerHost): Logger {
}, host);
}

function sanitizeLog(s: string) {
return s.replace(/Elapsed::?\s*\d+(?:\.\d+)?ms/g, "Elapsed:: *ms")
.replace(/\"updateGraphDurationMs\"\:\s*\d+(?:\.\d+)?/g, `"updateGraphDurationMs": *`)
.replace(/\"createAutoImportProviderProgramDurationMs\"\:\s*\d+(?:\.\d+)?/g, `"createAutoImportProviderProgramDurationMs": *`)
.replace(versionRegExp, `FakeVersion`)
.replace(/getCompletionData: Get current token: \d+(?:\.\d+)?/g, `getCompletionData: Get current token: *`)
.replace(/getCompletionData: Is inside comment: \d+(?:\.\d+)?/g, `getCompletionData: Is inside comment: *`)
.replace(/getCompletionData: Get previous token: \d+(?:\.\d+)?/g, `getCompletionData: Get previous token: *`)
.replace(/getCompletionsAtPosition: isCompletionListBlocker: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: isCompletionListBlocker: *`)
.replace(/getCompletionData: Semantic work: \d+(?:\.\d+)?/g, `getCompletionData: Semantic work: *`)
.replace(/getCompletionsAtPosition: getCompletionEntriesFromSymbols: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: getCompletionEntriesFromSymbols: *`)
.replace(/forEachExternalModuleToImportFrom autoImportProvider: \d+(?:\.\d+)?/g, `forEachExternalModuleToImportFrom autoImportProvider: *`)
.replace(/getExportInfoMap: done in \d+(?:\.\d+)?/g, `getExportInfoMap: done in *`)
.replace(/collectAutoImports: \d+(?:\.\d+)?/g, `collectAutoImports: *`)
.replace(/continuePreviousIncompleteResponse: \d+(?:\.\d+)?/g, `continuePreviousIncompleteResponse: *`)
.replace(/dependencies in \d+(?:\.\d+)?/g, `dependencies in *`)
.replace(/\"exportMapKey\"\:\s*\"[_$a-zA-Z][_$_$a-zA-Z0-9]*\|\d+\|/g, match => match.replace(/\|\d+\|/, `|*|`));
function sanitizeLog(s: string): string {
s = s.replace(/Elapsed::?\s*\d+(?:\.\d+)?ms/g, "Elapsed:: *ms");
s = s.replace(/\"updateGraphDurationMs\"\:\s*\d+(?:\.\d+)?/g, `"updateGraphDurationMs": *`);
s = s.replace(/\"createAutoImportProviderProgramDurationMs\"\:\s*\d+(?:\.\d+)?/g, `"createAutoImportProviderProgramDurationMs": *`);
s = replaceAll(s, ts.version, "FakeVersion");
s = s.replace(/getCompletionData: Get current token: \d+(?:\.\d+)?/g, `getCompletionData: Get current token: *`);
s = s.replace(/getCompletionData: Is inside comment: \d+(?:\.\d+)?/g, `getCompletionData: Is inside comment: *`);
s = s.replace(/getCompletionData: Get previous token: \d+(?:\.\d+)?/g, `getCompletionData: Get previous token: *`);
s = s.replace(/getCompletionsAtPosition: isCompletionListBlocker: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: isCompletionListBlocker: *`);
s = s.replace(/getCompletionData: Semantic work: \d+(?:\.\d+)?/g, `getCompletionData: Semantic work: *`);
s = s.replace(/getCompletionsAtPosition: getCompletionEntriesFromSymbols: \d+(?:\.\d+)?/g, `getCompletionsAtPosition: getCompletionEntriesFromSymbols: *`);
s = s.replace(/forEachExternalModuleToImportFrom autoImportProvider: \d+(?:\.\d+)?/g, `forEachExternalModuleToImportFrom autoImportProvider: *`);
s = s.replace(/getExportInfoMap: done in \d+(?:\.\d+)?/g, `getExportInfoMap: done in *`);
s = s.replace(/collectAutoImports: \d+(?:\.\d+)?/g, `collectAutoImports: *`);
s = s.replace(/continuePreviousIncompleteResponse: \d+(?:\.\d+)?/g, `continuePreviousIncompleteResponse: *`);
s = s.replace(/dependencies in \d+(?:\.\d+)?/g, `dependencies in *`);
s = s.replace(/\"exportMapKey\"\:\s*\"[_$a-zA-Z][_$_$a-zA-Z0-9]*\|\d+\|/g, match => match.replace(/\|\d+\|/, `|*|`));
return s;
}

export function createLoggerWithInMemoryLogs(host: TestServerHost): Logger {
Expand Down Expand Up @@ -159,14 +183,22 @@ export function appendAllScriptInfos(session: TestSession) {
session.logger.log("");
}

const versionRegExp = new RegExp(ts.version, "g");
const tsMajorMinorVersion = new RegExp(`@ts${ts.versionMajorMinor}`, "g");
function loggerToTypingsInstallerLog(logger: Logger): ts.server.typingsInstaller.Log | undefined {
return logger?.loggingEnabled() ? {
isEnabled: ts.returnTrue,
writeLine: s => logger.log(`TI:: [${nowString(logger.host!)}] ${sanitizeLog(s).replace(versionRegExp, "FakeVersion")
.replace(tsMajorMinorVersion, `@tsFakeMajor.Minor`)
}`),
writeLine: s => {
// This is a VERY VERY NAIVE sanitization strategy.
// If a substring containing the exact TypeScript version is found,
// even if it's unrelated to TypeScript itself, then it will be replaced,
// leaving us with two options:
//
// 1. Deal with flip-flopping baselines.
// 2. Change the TypeScript version until no matching substring is found.
//
const initialLog = sanitizeLog(s);
const pseudoSanitizedLog = replaceAll(initialLog, `@ts${ts.versionMajorMinor}`, `@tsFakeMajor.Minor`);
return logger.log(`TI:: [${nowString(logger.host!)}] ${pseudoSanitizedLog}`);
},
} : undefined;
}

Expand Down

0 comments on commit 2a9c204

Please sign in to comment.